opencv – 删除纸张折叠文物

我需要识别用软笔写的文字上的一些笔迹.使用OpenCV,不同的阈值处理方法,双边过滤等,我从纸上提取文本得到了很好的结果.但我也从折叠中得到了文物:

在处理之前,我无法改变处理或拍摄纸张的方式.阈值处理相同的纸张看起来像这样:

我想删除这些工件.对我来说最大的麻烦是当一些像“T”这样的角色碰巧出现在这条线上时. “T”的水平部分可以很好地适合这条线.

我现在做的是:我可以检测出是否存在独立行.如果某些东西像素很高而且非常宽,我会消除它.

我一直在阅读有关阴影消除的大量信息(因为我认为问题是阴影).但他们都期望在其他环境中工作 – 监控视频输入或带彩色背景的图像.

有任何想法吗?

更新:

正在研究基于类似作品的想法:http://ivrgwww.epfl.ch/alumni/fredemba/papers/FFICPR06.pdf

测试输入

输出测试代码:

源代码:

#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int filt1_trackbar=13;
int filt2_trackbar=49;
int filt3_trackbar=6;

int main( int argc, char** argv ) {
    Mat src, shadow;

    src = imread( argv[1], 1 );

    if( !src.data ) {
        return -1;
    }
    Mat histImage1( src.rows, src.cols, CV_8UC3, Scalar(127,127,127) );
    Mat histImage2( src.rows, src.cols, CV_8UC3, Scalar(127,127,127) );

    int cn = src.channels();
    uint8_t* pixelPtr = (uint8_t*)src.data;

    for(int i=0 ; i< src.rows;i++) {
        for(int j=0 ; j< src.cols;j++) {
            Scalar_<uint8_t> bgrPixel;
            bgrPixel.val[0] = pixelPtr[i*src.cols*cn + j*cn + 0]; // B
            bgrPixel.val[1] = pixelPtr[i*src.cols*cn + j*cn + 1]; // G
            bgrPixel.val[2] = pixelPtr[i*src.cols*cn + j*cn + 2]; // R
            if(bgrPixel.val[2] !=0 ) { // avoid division by zero
                float a= 100.0*(((float)bgrPixel.val[0] / (float)bgrPixel.val[2])); // B/R
                float b= 100.0*(((float)bgrPixel.val[1] / (float)bgrPixel.val[2])); // G/R
                if(!isinf(a) && !isinf(b)) {
                    histImage1.at<Vec3b>(i,j)=Vec3b(a,a,a);
                    histImage2.at<Vec3b>(i,j)=Vec3b(b,b,b);
                }
            }
        }
    }

    addWeighted(histImage1, 2.0, histImage2, -1.0, 0, shadow);

    Mat hsv1,hsv2;
    cvtColor(shadow, hsv1, CV_BGR2HSV);
    cvtColor(src,    hsv2, CV_BGR2HSV);

    vector<Mat> channels1;
    vector<Mat> channels2;
    split(hsv1, channels1);
    split(hsv2, channels2);

    addWeighted(channels1[2], 0.5, channels2[2], 0.5, 0, channels1[2]);
    insertChannel(channels1[2],hsv2,2);

    Mat unshadow;
    cvtColor(hsv2,unshadow,  CV_HSV2BGR);
    namedWindow( "src", WINDOW_NORMAL);
    namedWindow( "shadow", WINDOW_NORMAL);
    namedWindow( "unshadow", WINDOW_NORMAL);

    imshow("src", src);
    imshow("shadow", shadow);
    imshow("unshadow", unshadow);
    imwrite("shadow.png", shadow);
    imwrite("unshadow.png", unshadow);
    waitKey(0);

    return 0;
}

它确实改善了图像,但在我看来还不够好.我对这种灰度背景下的工作印象深刻.也许有人可以发现错误?

最佳答案 我会写一个“答案”因为评论太多了:

阴影去除(根据我的经验)并不容易,您可能对本文感兴趣:“Fredembach and Finlayson – Simple Shadow Removal

我在处理类似问题时得到了一段时间的另一个想法(我自己没有尝试过):

您基本上想要识别图像上的大区域(与字符相比)并以不同方式对待它们.如果你知道阴影区域,你可以通过增亮较暗的区域使页面更均匀.问题是如何获得这个大区域.

您可以先将黑色书写与周围纸张相同的颜色进行着色.之后,您可以使用OpenCV的双边滤镜来获得大的均匀色块.您可以通过轮廓检测识别边框,并且您可以知道纸张颜色的不同(由阴影引起).

希望这篇文章能够为你的问题带来新的亮点,并为你提供一些想法.

点赞