Могут быть и лучшие решения, но вот мой подход:
- Сделать операцию эрозии для изображения, чтобы можно было видеть абзацы как один контур.
- Удалите среднюю линию, сделав ее белой.
- Сделайте эрозию снова после удаления средней линии.
- Тогда ваши абзацы будут выглядеть как один контур. Применить minAreaRect .
- Рисование прямоугольников к исходному изображению.
Примечание : я кодировал в C ++, потому что моя среда основана на C ++, и я не знаком с Python, но преобразование должно быть простым.
Вот код и результирующие изображения:
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <vector>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
Mat img = imread("/ur/source/image/orijinal.jpg",CV_LOAD_IMAGE_GRAYSCALE);
resize(img,img,Size(img.cols/4,img.rows/4));
Mat org = img.clone();
Mat element = getStructuringElement( MORPH_ELLIPSE,
Size( 2*10 + 1, 2*10+1 ),
Point( 5, 5 ) );
Mat dst;
erode( img, dst, element );
for(int i=0;i<dst.rows;i++)
{
for(int j=0;j<dst.cols;j++)
{
if(dst.at<uchar>(Point(j,i))<252 && dst.at<uchar>(Point(j,i)) > 50 )
dst.at<uchar>(Point(j,i)) = 255;
}
}
Mat element2 = getStructuringElement( MORPH_ELLIPSE,
Size( 2*10 + 1, 2*10+1 ),
Point( 5, 5 ) );
Mat dst2,threshold_output;
erode( dst, dst2, element2);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold( dst2, threshold_output, 100, 255, THRESH_BINARY );
/// Find contours
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Find the rotated rectangles for each contour
vector<RotatedRect> minRect( contours.size() );
for( int i = 0; i < contours.size(); i++ )
minRect[i] = minAreaRect( Mat(contours[i]) );
/// Draw contours + rotated rects
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
Mat result_zero = Mat::zeros( threshold_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color(0,255,255);
// detect contours
drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
Point2f rect_points[4]; minRect[i].points( rect_points );
for( int j = 0; j < 4; j++ )
{
line( img, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
}
}
imshow("Source",org);
imshow("Output1",dst);
imshow("Output2",dst2);
imshow("Output3",img);
waitKey(0);
return 0;
}
Источник:
Первая эрозия:
Устранить среднюю линию и эрозию снова:
После minAreaRect нарисуйте прямоугольники для исходного изображения: