2012-11-22 8 views
15

사진의 텍스트를 인식하는 OCR 응용 프로그램을 구현하고 싶습니다.iOS Tesseract OCR 이미지 준비

iOS에 Tesseract Engine을 컴파일하고 통합하는 데 성공했지만 명확한 문서 (또는 화면에서이 텍스트의 포토 샷)를 촬영할 때 합리적인 탐지를 얻었지만 푯말, 상점 표지판, 컬러 배경과 같은 다른 텍스트는 성공했습니다. , 감지에 실패했습니다.

질문은 더 나은 인식을 얻기 위해 어떤 종류의 이미지 처리 준비가 필요한가입니다. 예를 들어, 이미지를 그레이 스케일/B & W로 변환 할 필요가 있고 콘트라스트 등을 고정시킬 필요가 있습니다.

iOS에서 어떻게 할 수 있습니까?이 패키지가 있습니까?

답변

15

현재 동일한 작업을하고 있습니다. Photoshop에 저장 한 PNG가 정상적으로 작동하지만 카메라에서 가져온 이미지가 제대로 작동하지 않는 것으로 나타났습니다. 설명을 요구하지 마십시오. 그러나이 기능을 적용하면 이러한 이미지가 작동합니다. 어쩌면 그것은 당신을 위해 또한 작동 할 것입니다.

// this does the trick to have tesseract accept the UIImage. 
UIImage * gs_convert_image (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; 
} 

나는 tesseract에 대한 이미지를 준비하기 위해 많은 실험을했습니다. 크기 조정, 그레이 스케일로 변환 한 다음 밝기와 대비를 조정하면 가장 잘 작동하는 것 같습니다.

나는 또한이 GPUImage 라이브러리를 사용해 보았습니다. https://github.com/BradLarson/GPUImage 그리고 GPUImageAverageLuminanceThresholdFilter는 나에게 훌륭한 조정 이미지를주는 것처럼 보이지만 tesseract가 제대로 작동하지 않는 것 같습니다.

나는 또한 내 프로젝트에 opencv를 넣었으며 이미지 루틴을 시험해 볼 계획이다. 아마도 심지어 일부 상자 감지 (이 tesseract 속도를 기대하고있다) 텍스트 영역을 찾으려면.

+0

이 gs_convert_image()를 추가 한 후에도이 메서드를 적용하기 전에 동일한 결과가 나타납니다. tessaract 스캐닝 데이터의 정확성을 향상시킬 방법이 있습니까? –

+1

왜 OCR이 저장된 이미지에서는 작동하지만 카메라의 이미지에서는 작동하지 않는지 알아낼 수 있었습니까? 지금은 같은 문제가 있지만 스위프트에서 일하고 위 코드를 구현하는 방법을 모르겠습니다.방금 여기에 게시 http://stackoverflow.com/questions/29336501/tesseract-ocr-w-ios-swift-returns-error-or-gibberish 귀하의 답변을 찾았습니다. 관련이있는 것 같습니다. 어떤 아이디어? – Andrew

+0

마인드 블로잉 코드, @roocell 내 시간을 절약하십시오. –

9

나는 위의 코드를 사용했지만 Tesseract와 함께 사용할 수 있도록 이미지를 변환하는 두 가지 다른 함수 호출도 추가했습니다.

먼저 이미지 크기 조정 스크립트를 사용하여 Tesseract에서 더 잘 관리 할 수있는 640x640으로 변환했습니다. 라디안가 작동하도록 그래서

-(UIImage *)resizeImage:(UIImage *)image { 

    CGImageRef imageRef = [image CGImage]; 
    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef); 
    CGColorSpaceRef colorSpaceInfo = CGColorSpaceCreateDeviceRGB(); 

    if (alphaInfo == kCGImageAlphaNone) 
     alphaInfo = kCGImageAlphaNoneSkipLast; 

    int width, height; 

    width = 640;//[image size].width; 
    height = 640;//[image size].height; 

    CGContextRef bitmap; 

    if (image.imageOrientation == UIImageOrientationUp | image.imageOrientation == UIImageOrientationDown) { 
     bitmap = CGBitmapContextCreate(NULL, width, height, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, alphaInfo); 

    } else { 
     bitmap = CGBitmapContextCreate(NULL, height, width, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, alphaInfo); 

    } 

    if (image.imageOrientation == UIImageOrientationLeft) { 
     NSLog(@"image orientation left"); 
     CGContextRotateCTM (bitmap, radians(90)); 
     CGContextTranslateCTM (bitmap, 0, -height); 

    } else if (image.imageOrientation == UIImageOrientationRight) { 
     NSLog(@"image orientation right"); 
     CGContextRotateCTM (bitmap, radians(-90)); 
     CGContextTranslateCTM (bitmap, -width, 0); 

    } else if (image.imageOrientation == UIImageOrientationUp) { 
     NSLog(@"image orientation up"); 

    } else if (image.imageOrientation == UIImageOrientationDown) { 
     NSLog(@"image orientation down"); 
     CGContextTranslateCTM (bitmap, width,height); 
     CGContextRotateCTM (bitmap, radians(-180.)); 

    } 

    CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), imageRef); 
    CGImageRef ref = CGBitmapContextCreateImage(bitmap); 
    UIImage *result = [UIImage imageWithCGImage:ref]; 

    CGContextRelease(bitmap); 
    CGImageRelease(ref); 

    return result; 
} 

당신은 내가 그레이 스케일로 변환 그런 다음 @implementation

static inline double radians (double degrees) {return degrees * M_PI/180;} 

위를 선언합니다.

회색 음영으로 변환시 Convert image to grayscale이 기사를 발견했습니다.

나는 약간 오히려 자신의 클래스와보다 클래스 내에서 함수로 작업을 성공적으로 여기에서 코드를 사용하고 지금은 코드를 수정 한

다른 색 텍스트와 다른 색 배경을 읽을 수있는 다른 사람이 않았다

- (UIImage *) toGrayscale:(UIImage*)img 
{ 
    const int RED = 1; 
    const int GREEN = 2; 
    const int BLUE = 3; 

    // Create image rectangle with current image width/height 
    CGRect imageRect = CGRectMake(0, 0, img.size.width * img.scale, img.size.height * img.scale); 

    int width = imageRect.size.width; 
    int height = imageRect.size.height; 

    // the pixels will be painted to this array 
    uint32_t *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), [img CGImage]); 

    for(int y = 0; y < height; y++) { 
     for(int x = 0; x < width; x++) { 
      uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x]; 

      // convert to grayscale using recommended method:  http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale 
      uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; 

      // set the pixels to gray 
      rgbaPixel[RED] = gray; 
      rgbaPixel[GREEN] = gray; 
      rgbaPixel[BLUE] = gray; 
     } 
    } 

    // create a new CGImageRef from our context with the modified pixels 
    CGImageRef image = CGBitmapContextCreateImage(context); 

    // we're done with the context, color space, and pixels 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 
    free(pixels); 

    // make a new UIImage to return 
    UIImage *resultUIImage = [UIImage imageWithCGImage:image 
              scale:img.scale 
             orientation:UIImageOrientationUp]; 

    // we're done with image now too 
    CGImageRelease(image); 

    return resultUIImage; 
} 
+0

나는 이것을 시도하고 내 이미지가 변환되지만, UIImage 여전히 내 아이폰에 충돌합니다. 어떤 제안? 소스 코드를 제공 할 수 있습니까? –

+1

카메라에서 이미지를 보내거나 다른 소스에서 이미지를로드하고 있습니까? 또한 위에 제공된 코드는 ARC를 사용한다고 가정합니다. 그렇지 않으면 적절한 시점에 이미지와 다른 객체를 릴리스해야합니다. 그렇지 않으면 메모리로드로 인해 충돌이 발생합니다. –

+0

"image.imageOrientation == UIImageOrientationUp | image.imageOrientation == UIImageOrientationDown"? – Andy

관련 문제