Reputation: 21
I want to crop the image between two lines, as shown in the image below. But the bottom line is not recognized well with HoughLinesP
.
The bottom line points are not really edged because of eroding, but is it important?
How can I detect the bottom line, and then crop the image according to these 2 lines?
Original image:
Processed image:
Canny edged:
Lines detected:
Code For Line Detection :
Mat dst, cdst,src2;
cv::blur( src, src2, cv::Size(5,5) );
Canny(src2, dst, 150, 300, 5);
cvtColor(dst, cdst, CV_GRAY2BGR);
//Mat original = imread("final_sample1.png",0);
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, 2*CV_PI/180, 100,1000, 50 );
For for displaying lines :
for( size_t i = 0; i < lines.size(); i++ )
{
Vec4i l = lines[i];
// oran = float(l[1] / col_size );
double angle = atan2(l[3] - l[1], l[2] - l[0]) * 180.0 / CV_PI;
if(angle < 5 && angle >=-5 ){
//if(1){
cout << l[0] << "," << l[1] << "," << l[2] << "," << l[3] << endl;
line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
}
}
EDIT:
For line detection appliying adaptive tresholding to original image gives more reliable results.
adaptiveThreshold(img,adaptiveTresholded,255,ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY,75,15);
I tested on 20 samples which has different number of rows , and thanks to Micka, with his modification, I got good results. To detect the right lines I put an if statement.
"ratio" variable is the y1 / row size of the image. And checking the line angle to prevent irrelevant lines.
for( size_t i = 0; i < lines.size(); i++ )
{
Vec4i l = lines[i];
raito = float(l[1] / row_size );
double angle = atan2(l[3] - l[1], l[2] - l[0]) * 180.0 / CV_PI;
if(angle < 10 && angle >=- 10 && ratio > 0.15 && ratio< 0.8){
//if(1){
cout <<"Here: " << l[0] << "," << l[1] << "," << l[2] << "," << l[3] <<
", Oran: " << oran << endl;
line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3);
}
}
Upvotes: 0
Views: 7976
Reputation:
Here are the plots of the accumulated raw intensities along horizontals, in ROIs around the top and bottom line pairs.
Needless to say, detecting the peaks isn't a real problem.
If there can be limited skew, you can repeat the process with a little rotation.
Upvotes: 0
Reputation: 20160
using your image and this code (basically yours but reduced the maximum line gap and used some dilates to actually make connected straigt parts out of the non-straight bottom line:
int main()
{
cv::Mat input = cv::imread("../inputData/LongLine.jpg");
cv::Mat gray;
cv::cvtColor(input,gray,CV_BGR2GRAY);
// threshold because of loaded jpeg artifacts
cv::Mat edges = gray > 100;
cv::dilate(edges, edges, cv::Mat());
cv::dilate(edges, edges, cv::Mat());
cv::dilate(edges, edges, cv::Mat());
std::vector<cv::Vec4i> lines;
cv::HoughLinesP(edges, lines, 1, 2*CV_PI/180, 100,1000, 10 );
for( size_t i = 0; i < lines.size(); i++ )
{
cv::Vec4i l = lines[i];
cv::line( input, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(0,0,255), 3);
}
cv::imwrite("../outputData/LongLine.png", input);
cv::resize(input, input, cv::Size(), 0.1, 0.1);
cv::imshow("input",input);
cv::waitKey(0);
return 0;
}
getting this result:
For HoughLinesP is is important that the line is really straight, because the summed lines are expected to have thickness 1. So if the accumulator misses lines by just one pixel, it fails. Since the bottom lines aren't as straight as the first ones, this might be the problem.
Upvotes: 1