简体   繁体   中英

How to increase pixel intensity difference more in image processing?

I have an image as shown in the attached figure. Sometimes, the digit's black color intensity is not much difference from their neighbour pixels and I have problem to extract these digits (for example, setting a threshold is not efficient as black color's intensity is close to gray color's intensity because of reflection or not well focus during the image capture). I like to make it more difference between black and background gray color so I can extract the digit without much noise. What I do is I increase the difference using addWeighted function from OpenCV . color is the original RGB image. Does it make sense with my processing or is there any more efficient approach?

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);

you need to do local thresholding(bernsen,sauvola,local otsu etc), opencv also happens to have adaptiveThreshold function. Here's an example. Just make sure to play around with the parameters.

adaptiveThreshold

adaptiveThreshold

bernsen

伯恩森

code

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

Simple thresholding doesn't account for lighting variations across the image and adaptive thresholding doesn't take advantage of connected regions.

The current leader in extraction of segments like this is MSER. It goes through all possible thresholds and finds connected most stable regions (across all thresholds). Don't re-invent a bicycle, use the proven best features and open source such as openCV MSER. There are more links on stack overflow.

EDIT: Following the comments by Vlad, I found the following link on OpenCV's 3.0 dev branch: http://docs.opencv.org/trunk/modules/objdetect/doc/erfilter.html . That appears to be the technique for detecting text using a modification of the original MSER algorithm for detecting keypoint mentioned by Vlad. Seems like OpenCV may have it soon. The details for this technique is described in 2 papers found in the link above. Thanks Vlad.

If you filter your image using Non-local means denoising before you threshold it using the algorithms mentioned by Zaw, you can reduce some of the noise:

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

Adaptive threshold as described by Zaw above (using same parameters):

adaptive_threshold

Bernsen threshold as described by Zaw (using same parameters): bern_threshold

Adjusting the parameters for thresholding and denoising might give you better results.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM