我刚开始用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的示例映像。

工作良好(这告诉我,项目本身的设置是正确的),但每当我试图使用其他图像,被识别的文本是一个完整的混乱。例如,我试图为显示示例图像的查找器拍摄一张照片:
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迷你型相机中的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,在表中显示项目)比我想象的需要更多的资源(=时间)。
发布于 2014-05-13 10:57:37
你从你的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);

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);
}
}

// 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];

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
发布于 2014-05-13 12:26:42
的结果有不同的行为。
如果直接从相机拍摄照片,请尝试下面的功能。
- (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;
}发布于 2016-04-04 22:35:27
几个星期来,我一直在挣扎于Tesseract字符识别。这里有两件事我学会了让它更好地工作..。
https://stackoverflow.com/questions/23626756
复制相似问题