2013-09-05 12 views
5

Miałem procedurę binaryzacji C++, której używałem do późniejszej operacji OCR. Jednak stwierdziłem, że spowodowało niepotrzebne pochylenie tekstu. Poszukując alternatyw znalazłem GPUImage o wielkiej wartości i rozwiązałem problem pochylania.iOS Unieważnienie binarizacji dla OCR - obsługa obrazów o różnej luminancji

Używam GPUImage code like this do binaryzacji obrazów wejściowych przed zastosowaniem OCR.

Jednak wartość progowa nie obejmuje zakresu obrazów, które otrzymuję. Zobacz dwie próbki z moich obrazów wejściowych:

enter image description here

enter image description here

nie mogę poradzić zarówno z samej wartości progowej. Niska wartość wydaje się być dobra z późniejszym, a wyższa wartość jest w porządku z pierwszą.

Drugi obraz wydaje się być szczególnie złożony, ponieważ nigdy nie uzyskałem prawidłowej binaryzacji wszystkich znaków, niezależnie od ustawionej wartości progowej. Z drugiej strony moja rutyna binaryzacji C++ wydaje się robić to dobrze, ale nie mam zbyt wiele wglądu, by eksperymentować z nią jak uproszczona wartość progowa w GPUImage.

Jak mam sobie z tym poradzić?

UPDATE:

Próbowałem z GPUImageAverageLuminanceThresholdFilter z domyślnym mnożnik = 1. Współpracuje z pierwszego obrazu ale drugi obraz nadal jest problemem.

Niektóre bardziej różnorodne wejścia dla binaryzacji:

enter image description here

enter image description here

UPDATE II:

Po przejściu przez this answer by Brad próbował GPUImageAdaptiveThresholdFilter (również włączenie GPUImagePicture ponieważ Wcześniej używał go tylko na UIImag mi).

Dzięki temu otrzymałem doskonały obraz binarny. Jednak pierwszy wydaje się mieć dużo hałasu po binaryzacji, gdy ustawię rozmiar rozmycia na 3.0. OCR powoduje dodanie dodatkowych znaków. Przy mniejszej wartości rozmycia drugi obraz traci precyzję.

Oto ona:

+(UIImage *)binarize : (UIImage *) sourceImage 
{ 
    UIImage * grayScaledImg = [self toGrayscale:sourceImage]; 
    GPUImagePicture *imageSource = [[GPUImagePicture alloc] initWithImage:grayScaledImg]; 
    GPUImageAdaptiveThresholdFilter *stillImageFilter = [[GPUImageAdaptiveThresholdFilter alloc] init]; 
    stillImageFilter.blurSize = 3.0;  

    [imageSource addTarget:stillImageFilter]; 
    [imageSource processImage];   

    UIImage *imageWithAppliedThreshold = [stillImageFilter imageFromCurrentlyProcessedOutput]; 
    // UIImage *destImage = [thresholdFilter imageByFilteringImage:grayScaledImg]; 
    return imageWithAppliedThreshold; 
} 
+0

Co robi twój C++ binaryzacji rutynowe wyglądać? Być może można to zaadaptować do niestandardowego filtra w ramach. Czy jest to lokalna binaryza adaptacyjna, czy też globalna progresja? –

+0

Co robi procedura C++ to skalowanie skali szarości + binaryzacja. Jeśli chodzi o GPUImage, samodzielnie wykonuję skalowanie w skali szarości, a następnie przekazuję dane wyjściowe do filtra GPUImage. Używam jednej z wielu technik skalowania szarości wspomnianych na stackoverflow. Czy chcesz, żebym o tym wspomniał? Zasadniczo używam do tego 3 różnych programów, ale wyniki nie różnią się zbytnio, więc uważam, że nie ma to znaczenia. –

+0

To nie jest moja rutyna C++, jak już powiedziałem, dostarczona przez kogoś innego i nie mogę jej tutaj całkowicie udostępnić, ani nie mogę podsumować, jak to działa, ponieważ nie mam zbyt wiele wglądu w to, jak to działa. To dość skomplikowane. To, co opisałem, jest tym, co czerpię z zawartych w nim komentarzy. –

Odpowiedz

1

I w końcu skończyło się zwiedzania na własną rękę, i tu jest mój wynik z GPUImage filtra:

+ (UIImage *) doBinarize:(UIImage *)sourceImage 
{ 
    //first off, try to grayscale the image using iOS core Image routine 
    UIImage * grayScaledImg = [self grayImage:sourceImage]; 
    GPUImagePicture *imageSource = [[GPUImagePicture alloc] initWithImage:grayScaledImg]; 
    GPUImageAdaptiveThresholdFilter *stillImageFilter = [[GPUImageAdaptiveThresholdFilter alloc] init]; 
    stillImageFilter.blurSize = 8.0; 

    [imageSource addTarget:stillImageFilter]; 
    [imageSource processImage]; 

    UIImage *retImage = [stillImageFilter imageFromCurrentlyProcessedOutput]; 
    return retImage; 
} 

+ (UIImage *) grayImage :(UIImage *)inputImage 
{  
    // Create a graphic context. 
    UIGraphicsBeginImageContextWithOptions(inputImage.size, NO, 1.0); 
    CGRect imageRect = CGRectMake(0, 0, inputImage.size.width, inputImage.size.height); 

    // Draw the image with the luminosity blend mode. 
    // On top of a white background, this will give a black and white image. 
    [inputImage drawInRect:imageRect blendMode:kCGBlendModeLuminosity alpha:1.0]; 

    // Get the resulting image. 
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return outputImage; 
} 

to osiągnąć prawie 90% za pomocą tego - Jestem pewien, że musi być lepsze opcje, ale próbowałem z blurSize tak daleko, jak to możliwe, a 8.0 jest wartością, która działa z większością moich obrazów wejściowych.

Dla każdego, powodzenia z próbowaniem!

2

Na etapie wstępnym przetwarzania trzeba adaptive thresholding tutaj.

Otrzymałem te wyniki, stosując metody skalowania w skali szarości i adaptacyjnego progu . Może z dodatkiem filtru z niską częstotliwością (gaussia lub mediana) powinien działać jak urok.

luminance

diverse

użyłem provisia (jego UI, które pomogą Ci szybko przetwarzać obrazy), aby uzyskać rozmiar bloku muszę: 43 dla obrazu dostarczanego tutaj. Rozmiar bloku może się zmienić, jeśli zrobisz zdjęcie z bliska lub dalej. Jeśli chcesz algorytmu rodzajowy, trzeba opracować taki, który powinien wyszukania najlepszego rozmiaru (szukaj, dopóki nie zostaną wykryte numery)

EDIT: I właśnie ten ostatni obraz. Jest nieuleczalnie mały. Nawet jeśli zastosujesz najlepszy algorytm przetwarzania wstępnego, nie wykryjesz tych liczb. Pobieranie próbek nie byłoby rozwiązaniem, ponieważ pojawią się odgłosy.

+0

+1 za świetny wynik. Tak, to jest ta jakość, której potrzebuję.Jestem jednak kompletnie nowym użytkownikiem Opencv i jeśli istnieje natywny przykładowy kod iOS, który można wskazać, będzie bardzo pomocny. –

+0

Cóż, już dostarczyłem link, ale oto jest. http://docs.opencv.org/doc/tutorials/ios/table_of_content_ios/table_of_content_ios.html. Przede wszystkim spróbuj połączyć opencv z projektem i uruchom przykładową próbkę świata. Następnie sprawdź przykład przetwarzania obrazu. Wszystko, co musisz zrobić, to uimage <-> cv :: mat transformation, faktycznie kod już tam jest. Następnie użyj metod "cvtColor" i "adaptiveThreshold". Są one również tam udokumentowane. http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html – baci

+1

http://www.cse.iitk.ac.in/users/vision/dipakmj/papers/OReilly%20Learning%20OpenCV.pdf możesz sprawdzić stronę 139 (lub 155 w pdf). – baci

0

SWIFT3

ROZWIĄZANIE 1

extension UIImage { 

func doBinarize() -> UIImage? { 

    let grayScaledImg = self.grayImage() 
    let imageSource = GPUImagePicture(image: grayScaledImg) 
    let stillImageFilter = GPUImageAdaptiveThresholdFilter() 
    stillImageFilter.blurRadiusInPixels = 8.0 

    imageSource!.addTarget(stillImageFilter) 
    stillImageFilter.useNextFrameForImageCapture() 
    imageSource!.processImage() 


    guard let retImage: UIImage = stillImageFilter.imageFromCurrentFramebuffer(with: UIImageOrientation.up) else { 
     print("unable to obtain UIImage from filter") 
     return nil 
    } 

    return retImage 
} 

func grayImage() -> UIImage? { 
    UIGraphicsBeginImageContextWithOptions(self.size, false, 1.0) 
    let imageRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) 

    self.draw(in: imageRect, blendMode: .luminosity, alpha: 1.0) 

    let outputImage = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 

    return outputImage 
} 


} 

Wynik będzie enter image description here

ROZWIĄZANIE 2

u se GPUImageLuminanceThresholdFilter osiągnąć 100% efekt czerni i bieli whithout kolorze szarym

let stillImageFilter = GPUImageLuminanceThresholdFilter() 
    stillImageFilter.threshold = 0.9 

Na przykład muszę wykryć światło lampy błyskowej i to działa na mnie enter image description here