【发布时间】:2014-04-03 01:23:04
【问题描述】:
我正在使用 OpenCV 为 iPhone 相机的 OCR 准备图像,但我无法获得准确 OCR 扫描所需的结果。这是我现在使用的代码。
cv::cvtColor(cvImage, cvImage, CV_BGR2GRAY);
cv::medianBlur(cvImage, cvImage, 0);
cv::adaptiveThreshold(cvImage, cvImage, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 5, 4);
此方法花费的时间有点太长,并且没有给我带来好的结果。
关于如何使这更有效的任何建议?图片来自 iPhone 相机。
在使用了 Andry 的建议之后。
cv::Mat cvImage = [self cvMatFromUIImage:image];
cv::Mat res;
cv::cvtColor(cvImage, cvImage, CV_RGB2GRAY);
cvImage.convertTo(cvImage,CV_32FC1,1.0/255.0);
CalcBlockMeanVariance(cvImage,res);
res=1.0-res;
res=cvImage+res;
cv::threshold(res,res, 0.85, 1, cv::THRESH_BINARY);
cv::resize(res, res, cv::Size(res.cols/2,res.rows/2));
image = [self UIImageFromCVMat:cvImage];
方法:
void CalcBlockMeanVariance(cv::Mat Img,cv::Mat Res,float blockSide=21) // blockSide - the parameter (set greater for larger font on image)
{
cv::Mat I;
Img.convertTo(I,CV_32FC1);
Res=cv::Mat::zeros(Img.rows/blockSide,Img.cols/blockSide,CV_32FC1);
cv::Mat inpaintmask;
cv::Mat patch;
cv::Mat smallImg;
cv::Scalar m,s;
for(int i=0;i<Img.rows-blockSide;i+=blockSide)
{
for (int j=0;j<Img.cols-blockSide;j+=blockSide)
{
patch=I(cv::Rect(j,i,blockSide,blockSide));
cv::meanStdDev(patch,m,s);
if(s[0]>0.01) // Thresholding parameter (set smaller for lower contrast image)
{
Res.at<float>(i/blockSide,j/blockSide)=m[0];
}else
{
Res.at<float>(i/blockSide,j/blockSide)=0;
}
}
}
cv::resize(I,smallImg,Res.size());
cv::threshold(Res,inpaintmask,0.02,1.0,cv::THRESH_BINARY);
cv::Mat inpainted;
smallImg.convertTo(smallImg,CV_8UC1,255);
inpaintmask.convertTo(inpaintmask,CV_8UC1);
inpaint(smallImg, inpaintmask, inpainted, 5, cv::INPAINT_TELEA);
cv::resize(inpainted,Res,Img.size());
Res.convertTo(Res,CV_32FC1,1.0/255.0);
}
知道为什么我会得到这个结果吗? OCR 结果非常好,但如果我能得到与你得到的图像相似的图像会更好。如果这很重要,我正在为 iOS 开发。我不得不使用cvtColor,因为该方法需要一个单通道图像。
【问题讨论】:
-
第三个参数不是卷积掩码的半径吗?必须是奇数且非零。
-
是的,你说得对,让我去看看默认值是什么,然后试试。编辑:尝试了一些,几乎没有改变结果,还有什么?
-
将自适应阈值的blocksize参数改为一些更高的值,比如25等