Tutorial: Detection / recognition of multiple rectangles and extracting with OpenCV
This tutorial will be focused on being able to take a picture and extract the rectangles in the image that are above a certain size:
I am using OpenCV 2.4.2 on Microsoft Visual Express 2008 but it should work with other version as well.
Thanks to: opencv-code.com for their helpful guides
Step 1: Clean up
//Apply blur to smooth edges and use adapative thresholding cv::Size size(3,3); cv::GaussianBlur(img,img,size,0); adaptiveThreshold(img, img,255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,75,10); cv::bitwise_not(img, img);
Step 2: Hough Line detection
vector<Vec4i> lines; HoughLinesP(img, lines, 1, CV_PI/180, 80, 100, 10);
Step 3: Use connected components to determine what they shapes are
cv::Point2f computeIntersect(cv::Vec4i a, cv::Vec4i b)
{
int x1 = a[0], y1 = a[1], x2 = a[2], y2 = a[3];
int x3 = b[0], y3 = b[1], x4 = b[2], y4 = b[3];
if (float d = ((float)(x1-x2) * (y3-y4)) - ((y1-y2) * (x3-x4)))
{
cv::Point2f pt;
pt.x = ((x1*y2 - y1*x2) * (x3-x4) - (x1-x2) * (x3*y4 - y3*x4)) / d;
pt.y = ((x1*y2 - y1*x2) * (y3-y4) - (y1-y2) * (x3*y4 - y3*x4)) / d;
//-10 is a threshold, the POI can be off by at most 10 pixels
if(pt.x<min(x1,x2)-10||pt.x>max(x1,x2)+10||pt.y<min(y1,y2)-10||pt.y>max(y1,y2)+10){
return Point2f(-1,-1);
}
if(pt.x<min(x3,x4)-10||pt.x>max(x3,x4)+10||pt.y<min(y3,y4)-10||pt.y>max(y3,y4)+10){
return Point2f(-1,-1);
}
return pt;
}
else
return cv::Point2f(-1, -1);
}
int* poly = new int[lines.size()];
for(int i=0;i<lines.size();i++)poly[i] = - 1;
int curPoly = 0;
vector<vector<cv::Point2f> > corners;
for (int i = 0; i < lines.size(); i++)
{
for (int j = i+1; j < lines.size(); j++)
{
cv::Point2f pt = computeIntersect(lines[i], lines[j]);
if (pt.x >= 0 && pt.y >= 0&&pt.x<img2.size().width&&pt.y<img2.size().height){
if(poly[i]==-1&&poly[j] == -1){
vector<Point2f> v;
v.push_back(pt);
corners.push_back(v);
poly[i] = curPoly;
poly[j] = curPoly;
curPoly++;
continue;
}
if(poly[i]==-1&&poly[j]>=0){
corners[poly[j]].push_back(pt);
poly[i] = poly[j];
continue;
}
if(poly[i]>=0&&poly[j]==-1){
corners[poly[i]].push_back(pt);
poly[j] = poly[i];
continue;
}
if(poly[i]>=0&&poly[j]>=0){
if(poly[i]==poly[j]){
corners[poly[i]].push_back(pt);
continue;
}
for(int k=0;k<corners[poly[j]].size();k++){
corners[poly[i]].push_back(corners[poly[j]][k]);
}
corners[poly[j]].clear();
poly[j] = poly[i];
continue;
}
}
}
}
Step 4: Find corners of the polygon
bool comparator(Point2f a,Point2f b){
return a.x<b.x;
}
void sortCorners(std::vector<cv::Point2f>& corners, cv::Point2f center)
{
std::vector<cv::Point2f> top, bot;
for (int i = 0; i < corners.size(); i++)
{
if (corners[i].y < center.y)
top.push_back(corners[i]);
else
bot.push_back(corners[i]);
}
sort(top.begin(),top.end(),comparator);
sort(bot.begin(),bot.end(),comparator);
cv::Point2f tl = top[0];
cv::Point2f tr = top[top.size()-1];
cv::Point2f bl = bot[0];
cv::Point2f br = bot[bot.size()-1];
corners.clear();
corners.push_back(tl);
corners.push_back(tr);
corners.push_back(br);
corners.push_back(bl);
}
for(int i=0;i<corners.size();i++){
cv::Point2f center(0,0);
if(corners[i].size()<4)continue;
for(int j=0;j<corners[i].size();j++){
center += corners[i][j];
}
center *= (1. / corners[i].size());
sortCorners(corners[i], center);
}
Step 5: Extraction
for(int i=0;i<corners.size();i++){
if(corners[i].size()<4)continue;
Rect r = boundingRect(corners[i]);
if(r.area()<50000)continue;
cout<<r.area()<<endl;
// Define the destination image
cv::Mat quad = cv::Mat::zeros(r.height, r.width, CV_8UC3);
// Corners of the destination image
std::vector<cv::Point2f> quad_pts;
quad_pts.push_back(cv::Point2f(0, 0));
quad_pts.push_back(cv::Point2f(quad.cols, 0));
quad_pts.push_back(cv::Point2f(quad.cols, quad.rows));
quad_pts.push_back(cv::Point2f(0, quad.rows));
// Get transformation matrix
cv::Mat transmtx = cv::getPerspectiveTransform(corners[i], quad_pts);
// Apply perspective transformation
cv::warpPerspective(img3, quad, transmtx, quad.size());
stringstream ss;
ss<<i<<".jpg";
imshow(ss.str(), quad);
}











Leave a Reply to chayma Cancel reply