首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为OCR准备复杂图像

为OCR准备复杂图像
EN

Stack Overflow用户
提问于 2012-02-22 16:02:21
回答 2查看 5.6K关注 0票数 12

我想识别信用卡上的数字。更糟糕的是,源图像不能保证高质量。OCR是通过神经网络实现的,但这不应该是这里的主题。

当前的问题是图像预处理。由于信用卡可以有背景和其他复杂的图形,文本不像扫描文档那样清晰。我做了边缘检测实验(Canny Edge,Sobel),但没有那么成功。此外,计算灰度图像和模糊图像之间的差异(如在Remove background color in image processing for OCR中所述)并不会导致OCRable结果。

我认为大多数方法都失败了,因为特定数字与其背景之间的对比不够强烈。可能需要将图像分割成块,并为每个块找到最佳的预处理方案?

您有什么建议如何将源转换为可读的二进制图像?边缘检测是要走的路还是我应该坚持基本的颜色阈值?

这里是一个灰度阈值处理方法的示例(在这里,我显然对结果不满意):

原始图像:

灰度图像:

缩影图像:

谢谢你的建议,瓦伦丁

EN

回答 2

Stack Overflow用户

发布于 2012-02-22 16:50:16

我处理这个问题的方法是把卡片分成不同的部分。没有很多独特的信用卡可以开始(MasterCard,Visa,列表是由您决定的),所以您可以像下拉列表一样指定它是哪一张信用卡。这样,您就可以消除并指定像素区域:

示例:

只处理底部20像素的区域,从左到右的30像素到底部的30像素(创建一个矩形)-这将覆盖所有的MasterCards。

当我使用图像处理程序(有趣的项目)时,我打开了图片的对比度,将其转换为灰度,将每个RGB值的平均值取为1个像素,并将其与周围的像素进行比较:

示例:

代码语言:javascript
复制
PixAvg[i,j] = (Pix.R + Pix.G + Pix.B)/3
if ((PixAvg[i,j] - PixAvg[i,j+1])>30)
    boolEdge == true;

30是你希望你的形象有多鲜明。差异越小,容忍度就越低。

在我的项目中,为了查看边缘检测,我创建了一个独立的布尔数组(包含来自boolEdge的值)和一个像素数组。像素数组中只填充了黑白点。它从布尔数组中获得值,其中boolEdge = true是一个白点,boolEdge = false是一个黑点。最后,你会得到一个像素数组(完整的图片),它只包含白色和黑色的点。

从那里,更容易检测到一个数字从哪里开始,一个数字在哪里结束。

票数 5
EN

Stack Overflow用户

发布于 2014-02-25 10:18:09

在我的实现中,我尝试从这里使用代码:http://rnd.azoft.com/algorithm-identifying-barely-legible-embossed-text-image/结果更好,但还不够.我发现很难找到贴图卡的正确对角。

代码语言:javascript
复制
(void)processingByStrokesMethod:(cv::Mat)src dst:(cv::Mat*)dst { 
cv::Mat tmp;  
cv::GaussianBlur(src, tmp, cv::Size(3,3), 2.0);                    // gaussian blur  
tmp = cv::abs(src - tmp);                                          // matrix of differences between source image and blur iamge  

//Binarization:  
cv::threshold(tmp, tmp, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);  

//Using method of strokes:  
int Wout = 12;  
int Win = Wout/2;  
int startXY = Win;  
int endY = src.rows - Win;  
int endX = src.cols - Win;  

for (int j = startXY; j < endY; j++) {  
    for (int i = startXY; i < endX; i++) {  
        //Only edge pixels:  
        if (tmp.at<unsigned char="">(j,i) == 255)  
        {  
            //Calculating maxP and minP within Win-region:  
            unsigned char minP = src.at<unsigned char="">(j,i);  
            unsigned char maxP = src.at<unsigned char="">(j,i);  
            int offsetInWin = Win/2;  

            for (int m = - offsetInWin; m < offsetInWin; m++) {  
                for (int n = - offsetInWin; n < offsetInWin; n++) {  
                    if (src.at<unsigned char="">(j+m,i+n) < minP) {  
                        minP = src.at<unsigned char="">(j+m,i+n);  
                    }else if (src.at<unsigned char="">(j+m,i+n) > maxP) {  
                        maxP = src.at<unsigned char="">(j+m,i+n);  
                    }  
                }  
            }  

            //Voiting:  
            unsigned char meanP = lroundf((minP+maxP)/2.0);  

            for (int l = -Win; l < Win; l++) {  
                for (int k = -Win; k < Win; k++) {  
                    if (src.at<unsigned char="">(j+l,i+k) >= meanP) {  
                        dst->at<unsigned char="">(j+l,i+k)++;  
                    }  
                }  
            }  
        }  
    }  
}  

///// Normalization of imageOut:  
unsigned char maxValue = dst->at<unsigned char="">(0,0);  

for (int j = 0; j < dst->rows; j++) {              //finding max value of imageOut  
    for (int i = 0; i < dst->cols; i++) {  
        if (dst->at<unsigned char="">(j,i) > maxValue)  
            maxValue = dst->at<unsigned char="">(j,i);  
    }  
}  
float knorm = 255.0 / maxValue;  

for (int j = 0; j < dst->rows; j++) {             //normalization of imageOut  
    for (int i = 0; i < dst->cols; i++) {  
        dst->at<unsigned char="">(j,i) = lroundf(dst->at<unsigned char="">(j,i)*knorm);  
    }  
}  
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9398374

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档