OCR:图像发送短信?(OCR: Image to text?)

2019-08-02 09:14发布

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

我能够在pressent做的是如下:

  1. 为了让形象和作物OCR所需的部分。
  2. 过程,使用所述图像tesseractleptonica
  3. 当所施加的文件中的块被裁切,即1个字符每图像提供精确的96%。
  4. 如果我不这样做,该文件的背景是白色,文字是黑色它让几乎相同的精度。

例如,如果输入是这张照片:

照片开始

照片结束

我想是能够得到同样的精度照片
而不产生块。

我以前的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%的准确的图像。

请帮助我。

任何建议将受到赞赏。

更新

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

我能够在图像转换为适当的黑白形式(几乎)。 等等认可是所有图像更好:)

需要图像二值化适当的帮助。 任何想法可以理解

Answer 1:

大家好感谢您的回复,从所有这一切回复我能够得到这样的结论如下:

  1. 我需要得到与包含在它号牌只有一个裁剪后的图像块。
  2. 从这个板块需要使用我使用所提供的方法中的数据,找出数部分的部分在这里 。
  3. 然后将图像数据转换为使用通过上述方法找到的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]; 

只需更换上述方法的( getRGBAsFromImage:与这一个码,其结果是相同的,但所用的时间是正好0.1〜0.3仅次于)。



Answer 2:

我是能够达到接近使用提供以及它产生正确的字母演示照片立竿见影的效果。

我预处理使用图像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));
}

该左“标志的 - 但这些也容易清除。 根据您有您可能需要微调有点象集,但它应该让你在正确的方向前进。

让我知道,如果你使用它有问题,这是从我使用的一个项目,我没有想必须去除所有的东西或者从头开始创建它的项目。



Answer 3:

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

我在我的OCR应用程序我使用的兴趣检索(只是瞄准了摄像头预览叠加层)的人类辅助区。 通常那些使用类似于哈尔级联找到有趣的功能,如脸。 你也可以简单地通过遍历所有的图像和stoing最左/最右/最上面/最下面的合适颜色的像素计算橙色区域,或橙像素的只是边框的质心

至于承认itselff我会建议使用不变矩(不知道在正方体是否实现,但你可以很容易地将它移植了从Java项目: http://sourceforge.net/projects/javaocr/ )

我试图在监控图像我的演示应用程序,它认识到了这项运动的数字(不训练字符)

至于二值化(分离白黑)我会建议sauvola方法,这给了最好的耐受亮度变化(在我们的OCR项目还实现)



文章来源: OCR: Image to text?