您需要进行本地二值化(Berensen、Sauvola、局部Otsu等),而OpenCV恰好有
adaptiveThreshold
函数。这里是一个例子,请确保尝试不同的参数。
adaptiveThreshold
![adaptiveThreshold](https://istack.dev59.com/tfqKi.webp)
Berensen
![bernsen](https://istack.dev59.com/4aDZg.webp)
代码
#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);
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);
}