2015-07-27 2 views
1

Я только что понял, что если я выполню процесс OCR только в регионах, содержащих текст, это будет намного быстрее. Итак, что я сделал, это обнаружение областей текста на изображении, а затем выполнение процесса OCR на каждом из них. Это результат «обнаружение текстовых областей» шаг с использованием OpenCV (я использовал его, чтобы нарисовать прямоугольник на изображении):Как отсортировать массив прямоугольников по положению?

Text regions detecting

Единственная проблема остается, я не мог организовать текстовый результат в чтобы они отображались на исходном изображении. В этом случае он должен быть:

circle oval triangle square trapezium 
diamond rhombus parallelogram rectangle pentagon 
hexagon heptagon octagon nonagon decagon 

Некоторые другие случаи:

В принципе, любые другие изображения, которые имеют текст на них.

PaperIn-app purchase - Messy Mary:Finding objects

Так что я пытаюсь сортировать массив прямоугольников (исходной точки, ширина и высота), а затем переставить текст ассоциировать с ними.

Дополнительная информация

Я не знаю, если это необходимо, но вот код, который я использовал:

Как я обнаружил тексте регионам

+(NSMutableArray*) detectLetters:(UIImage*) image 


{ 
    cv::Mat img; 
    UIImageToMat(image, img); 
    if (img.channels()!=1) { 
     NSLog(@"NOT A GRAYSCALE IMAGE! CONVERTING TO GRAYSCALE."); 
     cv::cvtColor(img, img, CV_BGR2GRAY); 
    } 
//The array of text regions (rectangle) 
NSMutableArray* array = [[NSMutableArray alloc] init]; 

cv::Mat img_gray=img, img_sobel, img_threshold, element; 

//Edge detection 
cv::Sobel(img_gray, img_sobel, CV_8U, 1, 0, 3, 1, 0, cv::BORDER_DEFAULT); 

cv::threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY); 

element = getStructuringElement(cv::MORPH_RECT, cv::Size(17, 3)); 

cv::morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element); 

std::vector< std::vector< cv::Point> > contours; 

// 
cv::findContours(img_threshold, contours, 0, 1); 

std::vector<std::vector<cv::Point> > contours_poly(contours.size()); 


for(int i = 0; i < contours.size(); i++) 
    if (contours[i].size()>50) 
    { 
     cv::approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 3, true); 
     cv::Rect appRect(boundingRect(cv::Mat(contours_poly[i]))); 
     if (appRect.width>appRect.height){ 
       [array addObject:[NSValue valueWithCGRect:CGRectMake(appRect.x,appRect.y,appRect.width,appRect.height)]]; 
     } 

    } 

return array; 
} 

Это процесс (OCR используя Tesseract):

NSMutableArray *arr=[STOpenCV detectLetters:img]; 

CFTimeInterval totalStartTime = CACurrentMediaTime(); 
NSMutableString *res=[[NSMutableString alloc] init]; 

for(int i=0;i<arr.count;i++){ 
    NSLog(@"\n-------------\nPROCESSING REGION %d/%lu",i+1,(unsigned long)arr.count); 

    //Set the OCR region using the result from last step 
    tesseract.rect=[[arr objectAtIndex:i] CGRectValue]; 


    CFTimeInterval startTime = CACurrentMediaTime(); 

    NSLog(@"Start to recognize: %f",startTime); 

    [tesseract recognize]; 

    NSString *result=[tesseract recognizedText]; 

    NSLog(@"Result: %@", result); 
    [res appendString:result]; 

    CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime; 

    NSLog(@"FINISHED: %f", elapsedTime); 
} 
+0

Это ваш образ справки? Или у вас более сложные изображения? Во всяком случае, разместите свои оригинальные изображения, чтобы мы могли попробовать их и, надеюсь, вернемся к вам с точным ответом – Miki

+0

Спасибо @Miki. Я добавил еще несколько изображений. В основном это могут быть любые изображения с текстом. – FlySoFast

ответ

4

Что вы хотите, чтобы отсортировать массив rects по yp (y - высота/2), а затем x (x - ширина/2), если они находятся на одной вертикальной линии.

NSArray *sortedRects; 
sortedRects = [unsortedRects sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { 
    CGRect *first = (CGRect*)a; 
    CGRect *second = (CGRect*)b; 
CGFloat yDifference = first.y - (first.height/2.0 < second.y) - (second.height/2.0) 
    return (yDifference < 0) || (yDifference == 0 && (first.x - (first.width/2.0 < second.x) || (second.width/2.0))); 
}]; 
+0

Да, но только в идеальном мире, потому что даже когда прямоугольники «на одной линии» на наших глазах, они не всегда имеют одинаковое значение позиции. – FlySoFast

+3

В этом случае вы можете добавить некоторое значение epsilon в сравнение yDifference , Вместо проверки на <0 вы можете проверить <5 (например), а затем (fabs (yDifference) <5 && ...). –

+0

это звучит примерно правый. На самом деле я думал об этом раньше, но я застрял в поиске идеального значения эпсилон для всех текстовых блоков. Я думал об использовании среднего значения высоты блоков как значения epsilon, но похоже, что это было бы неточно, если бы были небольшие блоки среди маленьких. Это действительно близко! – FlySoFast

Смежные вопросы