【问题标题】:Removing paper folding artifacts去除折纸伪影
【发布时间】:2014-05-23 15:15:44
【问题描述】:

我需要识别用软笔书写的文字上的一些笔迹。使用 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;
}

它确实改善了形象,但在我看来还不够好。我印象深刻的是它在这样的灰度背景下完全有效。也许有人能发现不对劲?

【问题讨论】:

  • 看看他们如何找到数独的水平和垂直线:stackoverflow.com/questions/10196198/…你的问题应该是相似的
  • 谢谢。看过这个线程,发现它对于学习 OpenCV 和计算机视觉非常有用。但我在纸上也有其他线条,我不想删除。我可以检测线条并删除。但后来我也松开了在线写的文字。至少我是这么认为的。印刷线质量相当高。折叠文物可能有未知的形状和宽度:(

标签: opencv


【解决方案1】:

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

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

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

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

您可以先用与周围纸张相同的颜色为深色文字着色。之后,您可以使用 OpenCV 的双边过滤器来获得大的均匀色块。您可以通过轮廓检测识别边界,并且您会知道纸张颜色的不同之处(由阴影引起)。

希望这篇文章能让您对您的问题有新的认识,并为您提供一些想法。

【讨论】:

  • 更新问题。仍在思考和测试:)
猜你喜欢
  • 2010-11-16
  • 1970-01-01
  • 2018-07-15
  • 2015-12-22
  • 1970-01-01
  • 2018-07-10
  • 2013-02-16
  • 1970-01-01
  • 2020-11-28
相关资源
最近更新 更多