去除纸张折叠文物

时间:2014-05-22 09:28:49

标签: opencv

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

enter image description here

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

enter image description here

我想删除这些工件。对我来说最大的麻烦就是某些人物喜欢" T"正好在这条线上。水平部分" T"可能很适合这条线。

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

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

有什么想法吗?

更新:

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

测试输入 enter image description here

输出测试代码:

enter image description here

源代码:

#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;
}

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

1 个答案:

答案 0 :(得分:2)

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

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

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

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

你可以先在与周围纸张相同的色调中着色。之后,您可以使用OpenCV的双边滤镜来获得大的均匀色块。您可以使用轮廓检测​​识别边框,并且您可以知道纸张在颜色上的差异(由阴影引起)。

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