首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS特斯拉:坏结果

iOS特斯拉:坏结果
EN

Stack Overflow用户
提问于 2014-05-13 08:55:26
回答 5查看 6.6K关注 0票数 11

我刚开始用Tesseract库弄脏我的手,但是结果真的很糟糕。

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

代码语言:javascript
复制
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的示例映像。

工作良好(这告诉我,项目本身的设置是正确的),但每当我试图使用其他图像,被识别的文本是一个完整的混乱。例如,我试图为显示示例图像的查找器拍摄一张照片:

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

但Tesseract认识到:

代码语言:javascript
复制
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

即使字符白名单只包含数字,我也无法得到接近图像的结果:

代码语言:javascript
复制
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迷你型相机中的fotos是有问题的,但是我不知道是什么以及为什么。

有什么暗示吗?

更新#1

针对Tomas:

我在你的文章中遵循了教程,但是在这过程中我遇到了一些错误.

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

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

由于我不知道您在这一点上可能认为什么是“重要的”(我已经读过几篇文章和教程,尝试了不同的步骤),所以可以随意问:)

更新#2

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

继续到下一个挑战;)

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

老实说:我还没来得及阅读OpenCV的文档并了解您的代码是干什么的,但到目前为止,我不认为有什么办法。对我来说,不幸的是,我的初始任务(扫描收据,运行OCR,在表中显示项目)比我想象的需要更多的资源(=时间)。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-05-13 10:57:37

你从你的iPad中获取照片的方式本身并没有错。但是你不可能提交这样复杂的图像,并期望Tesseract神奇地确定要提取的文本。仔细看一下图像,你会发现它没有统一的闪电,它非常嘈杂,所以它可能不是最好的开始玩的样本。

在这种情况下,必须对图像进行预处理,以便为tesseract库提供更简单的识别方法。

下面是一个非常简单的预处理示例,它使用了流行的图像处理框架OpenCV (http://www.opencv.org)。它应该给你和想法,让你开始。

代码语言:javascript
复制
#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); 

代码语言:javascript
复制
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);
    }
}

代码语言:javascript
复制
// 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];

代码语言:javascript
复制
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...");

Notes

  • UIImage+OpenCV类别可以找到这里。如果您在ARC下,请检查
  • 看看,让您开始使用Xcode中的OpenCV。请注意,OpenCV是一个不能在普通C(或Objective)源文件中导入的C++框架。最简单的解决方法是将视图控制器从.m重命名为.mm (Objective++),并在项目中重新导入它。
票数 7
EN

Stack Overflow用户

发布于 2014-05-13 12:26:42

的结果有不同的行为。

  • 它要求良好的图像质量意味着良好的纹理可见度。
  • 大尺寸的图片需要很长的时间来处理,它也很好地在处理前把它调整成小尺寸。
  • 在将图像发送到tesseract之前,对图像执行一些颜色效果将是很好的。使用能提高图像可见度的效果。
  • 使用相机或相机相册处理照片有时会有不同的行为。

如果直接从相机拍摄照片,请尝试下面的功能。

代码语言:javascript
复制
- (UIImage *) getImageForTexture:(UIImage *)src_img{
CGColorSpaceRef d_colorSpace = CGColorSpaceCreateDeviceRGB();
/*
 * Note we specify 4 bytes per pixel here even though we ignore the
 * alpha value; you can't specify 3 bytes per-pixel.
 */
size_t d_bytesPerRow = src_img.size.width * 4;
unsigned char * imgData = (unsigned char*)malloc(src_img.size.height*d_bytesPerRow);
CGContextRef context =  CGBitmapContextCreate(imgData, src_img.size.width,
                                              src_img.size.height,
                                              8, d_bytesPerRow,
                                              d_colorSpace,
                                              kCGImageAlphaNoneSkipFirst);

UIGraphicsPushContext(context);
// These next two lines 'flip' the drawing so it doesn't appear upside-down.
CGContextTranslateCTM(context, 0.0, src_img.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// Use UIImage's drawInRect: instead of the CGContextDrawImage function, otherwise you'll have issues when the source image is in portrait orientation.
[src_img drawInRect:CGRectMake(0.0, 0.0, src_img.size.width, src_img.size.height)];
UIGraphicsPopContext();

/*
 * At this point, we have the raw ARGB pixel data in the imgData buffer, so
 * we can perform whatever image processing here.
 */

// After we've processed the raw data, turn it back into a UIImage instance.
CGImageRef new_img = CGBitmapContextCreateImage(context);
UIImage * convertedImage = [[UIImage alloc] initWithCGImage:
                            new_img];

CGImageRelease(new_img);
CGContextRelease(context);
CGColorSpaceRelease(d_colorSpace);
free(imgData);
return convertedImage;
}
票数 2
EN

Stack Overflow用户

发布于 2016-04-04 22:35:27

几个星期来,我一直在挣扎于Tesseract字符识别。这里有两件事我学会了让它更好地工作..。

  1. 如果你知道你要读的是哪种字体,那就清除训练,并且只对它进行再训练。多字体降低了OCR处理的速度,也增加了Tesseract决策过程中的模糊性。这将导致更高的准确性和速度。
  2. 经过OCR处理是真正需要的。你最终会得到一个被Tesseract识别的字符矩阵。您将需要进一步处理字符,以缩小您正在试图阅读的范围。例如,如果您的应用程序正在阅读食品标签,了解构成食品标签的单词和句子的规则将有助于识别构成该标签的一系列字符。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23626756

复制
相关文章

相似问题

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