如何在图像处理中增加像素强度差异?

时间:2014-03-13 15:40:48

标签: image opencv image-processing

我有一张图,如附图所示。 有时,数字的黑色强度与它们的相邻像素差别不大,我有问题提取这些数字(例如,设置阈值效率不高,因为黑色的颜色接近灰色& #39;由于在图像捕获期间反射或焦距不好而导致的强度)。我喜欢在黑色和背景灰色之间做出更多区别,这样我就可以在没有太多噪音的情况下提取数字。我所做的是使用addWeighted中的OpenCV函数增加差异。 color是原始RGB图像。我的处理是否有意义,还是有更有效的方法?

Mat blur_img = new Mat(color.size(), color.type());
org.opencv.core.Size size = new Size(9,9);
Imgproc.GaussianBlur(color, blur_img, size, 2);
Mat sharpened = new Mat(color.size(), CvType.CV_32FC3);
Core.addWeighted(color, 1.5, blur_img, -0.5, 0, sharpened);

3 个答案:

答案 0 :(得分:5)

你需要进行本地阈值处理(bernsen,sauvola,local otsu等),opencv也恰好具有adaptiveThreshold功能。这是一个例子。只需确保使用参数即可。

adaptiveThreshold

adaptiveThreshold

伯恩森

bernsen

#include <opencv2/opencv.hpp>
using namespace cv;

Mat thresh_bernsen(Mat& gray,int ksize,int contrast_limit)
{
    Mat ret = Mat::zeros(gray.size(),gray.type());
    for(int i=0;i<gray.cols;i++ )
    {
        for(int j=0;j<gray.rows;j++ )
        {
            double mn=999,mx=0;
            int ti=0,tj=0;
            int tlx=i-ksize/2;
            int tly=j-ksize/2;
            int brx=i+ksize/2;
            int bry=j+ksize/2;
            if(tlx<0) tlx=0;
            if(tly<0) tly=0;
            if(brx>=gray.cols) brx=gray.cols-1;
            if(bry>=gray.rows) bry=gray.rows-1;

            minMaxIdx(gray(Rect(Point(tlx,tly),Point(brx,bry))),&mn,&mx,0,0);
            /* this does the above
            for(int ik=-ksize/2;ik<=ksize/2;ik++)
            {
                for(int jk=-ksize/2;jk<=ksize/2;jk++)
                {
                    ti=i+ik;
                    tj=j+jk;
                    if(ti>0 && ti<gray.cols && tj>0 && tj<gray.rows)
                    {
                        uchar pix = gray.at<uchar>(tj,ti);
                        if(pix<mn) mn=pix;
                        if(pix>mx) mx=pix;
                    }
                }
            }*/
            int median = 0.5 * (mn+mx);
            if(median<contrast_limit)
            {
                ret.at<uchar>(j,i)=0;
            }else
            {
                uchar pix = gray.at<uchar>(j,i);
                ret.at<uchar>(j,i) = pix>median?255:0;
            }
        }
    }
    return ret;
}
int main()
{
    Mat gray = imread("c:/data/number.jpg",0);
    gray=255-gray;
    Mat adaptthresh,bernsen;
    adaptiveThreshold(gray,adaptthresh,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY,41,1);
    bernsen=thresh_bernsen(gray,25,40);
    imshow("gray",gray);
    imshow("adaptthresh",adaptthresh);
    imshow("bernsen",bernsen);
    waitKey(0);
}

答案 1 :(得分:2)

简单阈值处理不考虑图像上的光照变化,自适应阈值处理不利用连接区域。

目前提取此类细分市场的领导者是MSER。它遍历所有可能的阈值并找到连接最稳定的区域(跨所有阈值)。不要重新发明自行车,使用经过验证的最佳功能和开放源代码,例如openCV MSER.堆栈溢出时会有更多links

答案 2 :(得分:1)

编辑:在Vlad的评论之后,我在OpenCV的3.0开发分支上找到了以下链接:http://docs.opencv.org/trunk/modules/objdetect/doc/erfilter.html。 这似乎是使用原始MSER算法的修改来检测文本以检测Vlad提到的关键点的技术。似乎OpenCV很快就会拥有它。在上面的链接中找到的2篇论文中描述了这种技术的细节。谢谢Vlad。

如果您使用非局部方式对图像进行去噪,然后使用Zaw提到的算法对其进行阈值处理,则可以减少一些噪音:

fastNlMeansDenoising(gray, gray, 3, 5, 15);

上面Zaw描述的自适应阈值(使用相同的参数):

adaptive_threshold

Zaw描述的Bernsen阈值(使用相同的参数): bern_threshold

调整阈值和去噪的参数可能会给你带来更好的效果。