我有一张图,如附图所示。
有时,数字的黑色强度与它们的相邻像素差别不大,我有问题提取这些数字(例如,设置阈值效率不高,因为黑色的颜色接近灰色& #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);
答案 0 :(得分:5)
你需要进行本地阈值处理(bernsen,sauvola,local otsu等),opencv也恰好具有adaptiveThreshold
功能。这是一个例子。只需确保使用参数即可。
adaptiveThreshold
伯恩森
码
#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描述的自适应阈值(使用相同的参数):
Zaw描述的Bernsen阈值(使用相同的参数):
调整阈值和去噪的参数可能会给你带来更好的效果。