iOS 超正方体 : bad results

标签 ios ocr tesseract

我刚开始接触 Tesseract 库,但结果真的很糟糕。

我遵循了 Git 存储库 ( https://github.com/gali8/Tesseract-OCR-iOS ) 中的说明。我的 ViewController 使用以下方法开始识别:

Tesseract *t = [[Tesseract alloc] initWithLanguage:@"deu"];
t.delegate = self;

[t setVariableValue:@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" forKey:@"tessedit_char_whitelist"];
[t setImage:img];

[t recognize];

NSLog( @"Recognized text: %@", [t recognizedText] );

labelRecognizedText.text = [t recognizedText];

t = nil;

来自项目 tempalte the sample image 的示例图像

效果很好(这告诉我项目本身设置正确),但每当我尝试使用其他图像时,识别的文本都是一团糟。例如,我试图为显示示例图像的取景器拍照:

https://dl.dropboxusercontent.com/u/607872/tesseract.jpg (1,5 MB)

但 Tesseract 识别:

Recognized text: s f l TO  if v   Ysssifss f

 ssqxizg ss sfzzlj z

s N T IYIOGY Z I l EY s s

k Es ETL ZHE s UEY

z xhks Fsjs Es z VIII c 

s I   XFTZT c s  h V Ijzs

L s sk  sisijk J

s f s ssj Jss sssHss H VI

s s  H 

i s H st xzs
s s k 4  is x2 IV
Illlsiqss sssnsiisfjlisszxiij s
K

即使字符白名单只包含数字,我也不会得到与图像看起来更接近的结果:

Recognized text:       3          74 211  

    1             

         1 1    1    

  3  53 379     1  

3  1   33  5    3 2 
      3          9 73
    1  61 2 2  
    3   1  6   5 212   7 
       1 
4     9 4  
           1  17
 111  11    1 1  11  1 1 1 1
 

我假设我目前使用的 iPad mini 相机拍摄照片的方式有问题,但我不知道是什么原因。

有什么提示吗?


更新 #1

回应托马斯:

我按照您帖子中的教程进行操作,但在此过程中遇到了一些错误...

  • 我的 ARC 项目中不能使用 UIImage+OpenCV 类别
  • 我无法在我的 Controller 中导入 <opencv2/...>,自动完成不提供它(因此未定义 [UIImage CVMat])

我认为我的 OpenCV 集成有问题,即使我遵循了 Hello-tutorial 并添加了框架。我是否也需要在我的 Mac 上构建 OpenCV,或者仅将框架包含在我的 Xcode 项目中就足够了吗?

由于目前我真的不知道您可能认为什么是“重要的”(我已经阅读了几篇文章和教程并尝试了不同的步骤),请随时提问 :)


更新#2

@Tomas:谢谢,ARC 部分是必不可少的。我的 ViewController 已经重命名为 .mm 。忘记关于“无法导入 opencv2/”的部分,因为我已经将它包含在我的 TestApp-Prefix.pch 中(如 Hello-tutorial 中所述)。

迎接下一个挑战;)

我注意到当我使用相机拍摄的图像时,roi 对象的边界计算不成功。我玩弄了设备方向并在我的 View 中放置了一个 UIImage 以查看图像处理步骤,但有时(即使图像正确对齐)值是负的,因为 if - bounds.size() -loop 中的 for -condition 不是'没见过面。我遇到的最坏情况:minX/Y 和 maxX/Y 从未被触及。长话短说:以 Mat roi = inranged(cv::Rect( 开头的行抛出异常(断言失败,因为值为 < 0 )。我不知道轮廓的数量是否重要,但我假设是这样,因为图像越大,断言异常的可能性就越大。

老实说:我没有时间阅读 OpenCV 的文档并理解您的代码的作用,但截至目前,我认为没有解决的办法。对我来说不幸的是,我的初始任务(扫描收据、运行 OCR、在表格中显示项目)似乎比我想象的需要更多的资源(=时间)。

最佳答案

您从 iPad 本身拍摄照片的方式没有任何问题。但是您不能只是输入如此复杂的图像并期望 Tesseract 神奇地确定要提取的文本。仔细观察图像,您会发现它没有均匀的闪电,它非常嘈杂,因此它可能不是开始玩的最佳样本。

在这种情况下,必须对图像进行预处理,以便为 tesseract 库提供更易于识别的内容。

下面是一个非常简单的预处理示例,它使用了 OpenCV (http://www.opencv.org),一种流行的图像处理框架。它应该为您提供入门的想法。

#import <TesseractOCR/TesseractOCR.h>
#import <opencv2/opencv.hpp>
#import "UIImage+OpenCV.h"

using namespace cv;

...

// load source image
UIImage *img = [UIImage imageNamed:@"tesseract.jpg"];

Mat mat = [img CVMat];
Mat hsv;

// convert to HSV (better than RGB for this task)
cvtColor(mat, hsv, CV_RGB2HSV_FULL);

// blur is slightly to reduce noise impact
const int blurRadius = img.size.width / 250;
blur(hsv, hsv, cv::Size(blurRadius, blurRadius)); 

// in range = extract pixels within a specified range
// here we work only on the V channel extracting pixels with 0 < V < 120
Mat inranged;
inRange(hsv, cv::Scalar(0, 0, 0), cv::Scalar(255, 255, 120), inranged); 

enter image description here

Mat inrangedforcontours;
inranged.copyTo(inrangedforcontours); // findContours alters src mat

// now find contours to find where characters are approximately located
vector<vector<cv::Point> > contours;
vector<Vec4i> hierarchy;

findContours(inrangedforcontours, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));

int minX = INT_MAX;
int minY = INT_MAX;
int maxX = 0;
int maxY = 0;

// find all contours that match expected character size
for (size_t i = 0; i < contours.size(); i++)
{
    cv::Rect brect = cv::boundingRect(contours[i]);
    float ratio = (float)brect.height / brect.width;

    if (brect.height > 250 && ratio > 1.2 && ratio < 2.0)
    {
        minX = MIN(minX, brect.x);
        minY = MIN(minY, brect.y);
        maxX = MAX(maxX, brect.x + brect.width);
        maxY = MAX(maxY, brect.y + brect.height);
    }
}

enter image description here

// Now we know where our characters are located
// extract relevant part of the image adding a margin that enlarges area
const int margin = img.size.width / 50;
Mat roi = inranged(cv::Rect(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY + 2 * margin));
cvtColor(roi, roi, CV_GRAY2BGRA);
img = [UIImage imageWithCVMat:roi];

enter image description here

Tesseract *t = [[Tesseract alloc] initWithLanguage:@"eng"];

[t setVariableValue:@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" forKey:@"tessedit_char_whitelist"];
[t setImage:img];

[t recognize];

NSString *recognizedText = [[t recognizedText] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

if ([recognizedText isEqualToString:@"1234567890"])
    NSLog(@"Yeah!");
else
    NSLog(@"Epic fail...");

注意事项

  • UIImage+OpenCV 类别可以在 here 中找到。如果您在 ARC 下,请检查 this
  • 查看 this 以开始在 Xcode 中使用 OpenCV。请注意,OpenCV 是一个 C++ 框架,无法在纯 C(或 Objective-C)源文件中导入。最简单的解决方法是将 View Controller 从 .m 重命名为 .mm (Objective-C++),然后将其重新导入到您的项目中。

关于iOS 超正方体 : bad results,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23626756/

相关文章:

ocr - Tesseract OCR 无法识别基本的字母数字代码

python - 从扫描图像中删除水平线

text - 如何向 Tesseract 4.0 添加新字体?

ocr - 如何提高OCR准确率?

ios - 移动 API 设计 - 灵活性与性能

fonts - 已知字体的 OCR

android - 我的 ANDROID 应用程序的 Tesseract OCR 执行过程

iOS,如何使用GMSCoordinateBounds显示 map 的所有标记?

ios - 在 drawRect 中用两种不同的字体绘制一个 NSString?

objective-c - 在快速枚举期间将对象设置为 nil