OCR:图像到文本?

在标记为复制或重复问题之前,请先阅读整个问题。

我能够做的事情如下:

  1. 获取图像并剪裁OCR所需的部分。
  2. 使用tesseractleptonica处理图像。
  3. 当应用的文档以大块(即,每个图像1个字符)裁剪时,它提供了96%的准确度。
  4. 如果我不这样做,文档背景是白色,文字是黑色的,它的准确度几乎相同。

例如,如果input是这张照片:

照片开始

在这里输入图像说明

照片结束

我想要的是能够为这张照片获得相同的准确性 在这里输入图像说明
没有生成块。

我用来初始化和提取图像文本的代码如下:

对于tesseract的初始化

在.h文件中

 tesseract::TessBaseAPI *tesseract; uint32_t *pixels; 

在.m文件中

 tesseract = new tesseract::TessBaseAPI(); tesseract->Init([dataPath cStringUsingEncoding:NSUTF8StringEncoding], "eng"); tesseract->SetPageSegMode(tesseract::PSM_SINGLE_LINE); tesseract->SetVariable("tessedit_char_whitelist", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); tesseract->SetVariable("language_model_penalty_non_freq_dict_word", "1"); tesseract->SetVariable("language_model_penalty_non_dict_word ", "1"); tesseract->SetVariable("tessedit_flip_0O", "1"); tesseract->SetVariable("tessedit_single_match", "0"); tesseract->SetVariable("textord_noise_normratio", "5"); tesseract->SetVariable("matcher_avg_noise_size", "22"); tesseract->SetVariable("image_default_resolution", "450"); tesseract->SetVariable("editor_image_text_color", "40"); tesseract->SetVariable("textord_projection_scale", "0.25"); tesseract->SetVariable("tessedit_minimal_rejection", "1"); tesseract->SetVariable("tessedit_zero_kelvin_rejection", "1"); 

从图像获取文本

 - (void)processOcrAt:(UIImage *)image { [self setTesseractImage:image]; tesseract->Recognize(NULL); char* utf8Text = tesseract->GetUTF8Text(); int conf = tesseract->MeanTextConf(); NSArray *arr = [[NSArray alloc]initWithObjects:[NSString stringWithUTF8String:utf8Text],[NSString stringWithFormat:@"%d%@",conf,@"%"], nil]; [self performSelectorOnMainThread:@selector(ocrProcessingFinished:) withObject:arr waitUntilDone:YES]; free(utf8Text); } - (void)ocrProcessingFinished0:(NSArray *)result { UIAlertView *alt = [[UIAlertView alloc]initWithTitle:@"Data" message:[result objectAtIndex:0] delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [alt show]; } 

但是,我没有得到适当的输出的车牌图像,它是空的或它给一些垃圾数据的图像。

如果我使用的是第一个图像,即文本为白色的背景为黑色,那么输出的准确率为89%到95%。

请帮我一下

任何build议将不胜感激。

更新

感谢@jcesar提供的链接,也感谢@konstantin pribluda提供有价值的信息和指导。

我能够将图像转换成适当的黑白forms(几乎)。 所以对所有图像的识别是更好的:)

需要帮助正确的图像二进制化。 任何想法将不胜感激

大家好谢谢你的答复,从所有答复我可以得到这个结论如下:

  1. 我需要得到唯一一个包含在其中的号牌的裁剪图像块。
  2. 从该板上需要使用我在这里提供的方法得到的数据找出数字部分的部分。
  3. 然后使用通过上述方法find的RGB数据将图像数据转换成几乎黑白的图像。
  4. 然后使用此处提供的方法将数据转换为图像。

以上4个步骤合并为一个如下所示的方法:

 -(void)getRGBAsFromImage:(UIImage*)image { NSInteger count = (image.size.width * image.size.height); // First get the image into your data buffer CGImageRef imageRef = [image CGImage]; NSUInteger width = CGImageGetWidth(imageRef); NSUInteger height = CGImageGetHeight(imageRef); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char)); NSUInteger bytesPerPixel = 4; NSUInteger bytesPerRow = bytesPerPixel * width; NSUInteger bitsPerComponent = 8; CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); CGContextRelease(context); // Now your rawData contains the image data in the RGBA8888 pixel format. int byteIndex = 0; for (int ii = 0 ; ii < count ; ++ii) { CGFloat red = (rawData[byteIndex] * 1.0) ; CGFloat green = (rawData[byteIndex + 1] * 1.0) ; CGFloat blue = (rawData[byteIndex + 2] * 1.0) ; CGFloat alpha = (rawData[byteIndex + 3] * 1.0) ; NSLog(@"red %f \t green %f \t blue %f \t alpha %f rawData [%d] %d",red,green,blue,alpha,ii,rawData[ii]); if(red > Required_Value_of_red || green > Required_Value_of_green || blue > Required_Value_of_blue)//all values are between 0 to 255 { red = 255.0; green = 255.0; blue = 255.0; alpha = 255.0; // all value set to 255 to get white background. } rawData[byteIndex] = red; rawData[byteIndex + 1] = green; rawData[byteIndex + 2] = blue; rawData[byteIndex + 3] = alpha; byteIndex += 4; } colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef bitmapContext = CGBitmapContextCreate( rawData, width, height, 8, // bitsPerComponent 4*width, // bytesPerRow colorSpace, kCGImageAlphaNoneSkipLast); CFRelease(colorSpace); CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext); UIImage *img = [UIImage imageWithCGImage:cgImage]; //use the img for further use of ocr free(rawData); } 

注意:

这种方法唯一的缺点是消耗的时间和RGB值转换为白色和其他黑色。

更新:

  CGImageRef imageRef = [plate CGImage]; CIContext *context = [CIContext contextWithOptions:nil]; // 1 CIImage *ciImage = [CIImage imageWithCGImage:imageRef]; // 2 CIFilter *filter = [CIFilter filterWithName:@"CIColorMonochrome" keysAndValues:@"inputImage", ciImage, @"inputColor", [CIColor colorWithRed:1.f green:1.f blue:1.f alpha:1.0f], @"inputIntensity", [NSNumber numberWithFloat:1.f], nil]; // 3 CIImage *ciResult = [filter valueForKey:kCIOutputImageKey]; // 4 CGImageRef cgImage = [context createCGImage:ciResult fromRect:[ciResult extent]]; UIImage *img = [UIImage imageWithCGImage:cgImage]; 

用这个代码replace上面的方法( getRGBAsFromImage:代码,结果是一样的,但所花费的时间仅仅是0.1到0.3秒。

我能够使用所提供的演示照片以及它生成正确的字母,实现近乎即时的结果。

我使用GPUImage预处理图像

 // Pre-processing for OCR GPUImageLuminanceThresholdFilter * adaptiveThreshold = [[GPUImageLuminanceThresholdFilter alloc] init]; [adaptiveThreshold setThreshold:0.3f]; [self setProcessedImage:[adaptiveThreshold imageByFilteringImage:_image]]; 

然后将处理后的图像发送给TESS

 - (NSArray *)processOcrAt:(UIImage *)image { [self setTesseractImage:image]; _tesseract->Recognize(NULL); char* utf8Text = _tesseract->GetUTF8Text(); return [self ocrProcessingFinished:[NSString stringWithUTF8String:utf8Text]]; } - (NSArray *)ocrProcessingFinished:(NSString *)result { // Strip extra characters, whitespace/newlines NSString * results_noNewLine = [result stringByReplacingOccurrencesOfString:@"\n" withString:@""]; NSArray * results_noWhitespace = [results_noNewLine componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; NSString * results_final = [results_noWhitespace componentsJoinedByString:@""]; results_final = [results_final lowercaseString]; // Separate out individual letters NSMutableArray * letters = [[NSMutableArray alloc] initWithCapacity:results_final.length]; for (int i = 0; i < [results_final length]; i++) { NSString * newTile = [results_final substringWithRange:NSMakeRange(i, 1)]; [letters addObject:newTile]; } return [NSArray arrayWithArray:letters]; } - (void)setTesseractImage:(UIImage *)image { free(_pixels); CGSize size = [image size]; int width = size.width; int height = size.height; if (width <= 0 || height <= 0) return; // the pixels will be painted to this array _pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t)); // clear the pixels so any transparency is preserved memset(_pixels, 0, width * height * sizeof(uint32_t)); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // create a context with RGBA pixels CGContextRef context = CGBitmapContextCreate(_pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); // paint the bitmap to our context which will fill in the pixels array CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]); _tesseract->SetImage((const unsigned char *) _pixels, width, height, sizeof(uint32_t), width * sizeof(uint32_t)); } 

这留下了'标志 – 但这些也很容易删除。 根据你的图像设置,你可能需要微调一下,但是它会让你朝着正确的方向移动。

让我知道如果你有使用它的问题,它来自我正在使用的一个项目,我不希望必须去掉所有的东西或从头开始创build一个项目。

我敢说,tesseract将为你的目的矫枉过正。 您不需要字典匹配来提高识别质量(您没有此字典,但也许意味着计算许可证号码上的校验和),并且您已为OCR优化字体。 最重要的是,你有标记(橙色和蓝色区域附近是好的)来find图像中的区域。

我的OCR应用程序我使用人工辅助的兴趣区域检索(只是瞄准帮助覆盖相机预览)。 通常使用haar cascade来定位像脸部这样有趣的function。 你也可以计算橙色区域的质心,或者只是通过遍历所有的图像和select合适的颜色的最左/最右/最顶/最底部像素

至于认识itselff我会build议使用不变的时刻(不知道是否实现在tesseract,但你可以很容易地从Java项目移植它: http : //sourceforge.net/projects/javaocr/ )

我在监视器图像上试用了我的演示应用程序,并识别了运动中的数字(未经过字符训练)

至于二值化(从白色分离黑色),我会推荐sauvola方法,因为这样可以提供对亮度变化的最佳容忍度(也在我们的OCR项目中实现)