如何按位置对矩形数组进行排序?
How to sort an array of rectangles by position?
我刚刚意识到,如果我只对包含文本的区域执行 OCR 处理,速度会快很多。所以我所做的是检测图像中的文本区域,然后对每个文本区域执行 OCR 处理。这是使用 OpenCV "detecting text regions" 步骤的结果(我用它在图像上绘制矩形):
唯一的问题是我无法按照它们在原始图像上出现的顺序排列文本结果。在这种情况下,它应该是:
circle oval triangle square trapezium
diamond rhombus parallelogram rectangle pentagon
hexagon heptagon octagon nonagon decagon
其他一些情况:
基本上任何其他带有文字的图像。
所以我尝试对矩形数组(原点、宽度和高度)进行排序,然后重新排列与它们关联的文本。
更多信息
我不知道是否有必要,但这是我使用的代码:
我是如何检测文本区域的
+(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);
}
您想要的是按 y 位置 (y - height/2) 对矩形数组进行排序,然后按 x 位置 (x - width/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));
}];
我刚刚意识到,如果我只对包含文本的区域执行 OCR 处理,速度会快很多。所以我所做的是检测图像中的文本区域,然后对每个文本区域执行 OCR 处理。这是使用 OpenCV "detecting text regions" 步骤的结果(我用它在图像上绘制矩形):
唯一的问题是我无法按照它们在原始图像上出现的顺序排列文本结果。在这种情况下,它应该是:
circle oval triangle square trapezium
diamond rhombus parallelogram rectangle pentagon
hexagon heptagon octagon nonagon decagon
其他一些情况:
基本上任何其他带有文字的图像。
所以我尝试对矩形数组(原点、宽度和高度)进行排序,然后重新排列与它们关联的文本。
更多信息
我不知道是否有必要,但这是我使用的代码:
我是如何检测文本区域的
+(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);
}
您想要的是按 y 位置 (y - height/2) 对矩形数组进行排序,然后按 x 位置 (x - width/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));
}];