1 | initial version |
Following more or less the technique that I am applying here and here. I am getting the following results, which it seems to be what you want.
I consider that the title of the song has always the same distance from the detected horizontal line, if this is not the case then some further modification most likely will be needed. I am not uploading any code since most of it is based on the two links that I have provided earlier. However, if you still want it just tell me and I will uploaded here.
2 | No.2 Revision |
Following more or less the technique that I am applying here and here. I am getting the following results, which it seems to be what you want.
I consider that the title of the song has always the same distance from the detected horizontal line, if this is not the case then some further modification most likely will be needed. I am not uploading any code since most of it is based on the two links that I have provided earlier. However, if you still want it just tell me and I will uploaded here.
here you go:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("sheet1.jpg");
if(!src.data)
{
cerr << "Problem loading image!!!" << endl;
return EXIT_FAILURE;
}
// imshow("src", src);
// resizing for practical reasons, small screen here :-p
Mat rsz;
Size size(800, 900);
resize(src, rsz, size);
imshow("rsz", rsz);
Mat gray;
cvtColor(rsz, gray, CV_BGR2GRAY);
// Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol
Mat bw;
adaptiveThreshold(~gray, bw, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
// Dilate a bit in order to correct possible gaps
Mat kernel = Mat::ones(2, 2, CV_8UC1);
dilate(bw, bw, kernel);
// Show binary image
imshow("bin", bw);
// Create the images that will use to extract the horizonta and vertical lines
Mat horizontal = bw.clone();
// Specify size on horizontal axis
int scale = 10; // play with this variable in order to increase/decrease the amount of lines to be detected
int horizontalsize = horizontal.cols / scale;
// Create structure element for extracting horizontal lines through morphology operations
Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontalsize,1));
// Apply morphology operations
erode(horizontal, horizontal, horizontalStructure, Point(-1, -1));
dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1));
// Show extracted horizontal lines
imshow("horizontal", horizontal);
// Create the images that will use to extract the horizonta and vertical lines
Mat vertical = bw.clone();
// Specify size on horizontal axis
int verticalsize = vertical.cols / scale;
// Create structure element for extracting horizontal lines through morphology operations
Mat verticalStructure = getStructuringElement(MORPH_RECT, Size( 1,verticalsize));
// Apply morphology operations
erode(vertical, vertical, verticalStructure, Point(-1, -1));
dilate(vertical, vertical, verticalStructure, Point(-1, -1));
// Show extracted horizontal lines
imshow("vertical", vertical);
Mat joints = horizontal + vertical;
imshow("joints", joints);
// Find external contour
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(horizontal, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
vector<vector<Point> > contours_poly( contours.size() );
vector<Rect> boundRect( contours.size() );
// Draw the contour as a solid blob filling also any convexity defect with the extracted hulls
for (size_t i = 0; i < contours.size(); i++)
{
// cout << boundRect[i].tl() << endl;
// cout << boundRect[i].br() << endl << endl;
// cout << arcLength(cv::Mat(contours[i]), true) << endl;
double length = arcLength(cv::Mat(contours[i]), true);
// filter long and short lines
if(length < 75 || length > 1500)
continue;
approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
// if(length > 200)
// {
// boundRect[i] += Size(0, -40); // expanding rectangle by a certain amount
// boundRect[i] -= Point(0, 3); // shifting rectangle by a certain offset
// }else{
boundRect[i] += Size(0, 30);
boundRect[i] -= Point(0, -4);
// }
drawContours( rsz, contours, i, Scalar(0, 0, 255), CV_FILLED, 8, vector<Vec4i>(), 0, Point() );
rectangle( rsz, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 1, 8, 0 );
}
cv::findContours(vertical, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
for (size_t i = 0; i < contours.size(); i++)
drawContours( rsz, contours, i, Scalar(0, 0, 255), CV_FILLED, 8, vector<Vec4i>(), 0, Point() );
imshow("src", rsz);
/* Now you can do whatever post process you want
* with the data within the rectangles. */
waitKey(0);
return 0;
}