【OpenCV】物体最⼩外接矩形
⽂章⽬录
基本原理
⼀种通过物体最⼩外接矩形来判别物体⽅向的简单⽅法,必须承认,有⼀定的局限性,同时精度不⾼。
⾸先,假设我们已经识别到⽬标物体,如下图,⽤正交的矩形框将其标记出来。这个标记的矩形框所蕴含的信息是⽐较少的。
通过某些⽅法(例如将矩形框旋转⾓度并保持图形外接),我们可以获得⽬标物体的最⼩外接矩形(如下图蓝⾊矩形框)。
不难发现:
矩形中⼼ ≈ ⽬标物体形⼼
矩形旋转⾓度 ≈ ⽬标物体主体轴线相对于正交坐标的转⾓
通过这个⽅法,我们就可以简单地获取⽬标物体的位置和位姿信息(⼀般适合矩形的物体)。
识别⽰例
以下图中⼀把瑞⼠军⼑为例。
⾸先通过⼆值化确定⽬标物体所在的区域。
之后再运⽤最⼩外接矩形进⾏框选,通过计算外接矩形的中⼼点坐标和转⾓,获得⽬标物体的位置和位姿信息。
注意:这种⽅法仅仅是⼀种简单的判断,具有⼀定的局限性。例如,如果⽬标物体形状长宽区分度不⾼,亦或者形状怪异不均匀,就很难得到较好的结果。
如下图所⽰是⼀个集装箱扭锁图⽚,可以发现其主体部分多出来的拉杆影响到了最⼩外接矩形的判断。这种情况如果继续想使⽤本⽅法的话,就需要去除⼲扰部分。可以参考我的另⼀篇博客中提及的。
代码
#include<opencv2\opencv.hpp>
#include<vector>
#include<algorithm>
using namespace cv;
using namespace std;
Mat toBinary(Mat src);
bool ascendSort(vector<Point> a, vector<Point> b);
Mat getContour(Mat src, Mat binary);
Mat srcImage,binaryImage,contourImage;
int main()
{
srcImage =imread("01.jpg");//input image
imshow("srcImage", srcImage);
binaryImage =toBinary(srcImage);//convert to binary image
imshow("binaryImage", binaryImage);
contourImage =getContour(srcImage, binaryImage);
imshow("contourImage", contourImage);
waitKey(0);
return0;
}
Mat toBinary(Mat src)
{
Mat temp = src.clone();
rectangle函数opencvint thresh =110, maxValue =254;
cvtColor(temp, temp, CV_BGR2GRAY);//convert to gray image
threshold(temp, temp, thresh, maxValue, THRESH_BINARY);//binary processing
return temp;
}
bool ascendSort(vector<Point> a, vector<Point> b)
{
return a.size()> b.size();
}
Mat getContour(Mat src,Mat binary)
{
Mat temp = src.clone();
vector< vector< Point>> contours;//save all contours data
vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//find contours
sort(contours.begin(), d(), ascendSort);//ascending sort
vector< vector<Point>>::iterator itc = contours.begin();//iterator of contour vector
int i =0;
while(itc != d())
{
if(itc->size()>150)//ignore the small object
{
if(i>0)
{
Rect rect =boundingRect(*itc);//get the rectangle bounding
rectangle(temp, rect,{0,0,255},2,8);//draw the rectangle
RotatedRect resultRect;
resultRect =minAreaRect(*itc);//get the min area rectangle
Point2f pt[4];
resultRect.points(pt);//get the coordinate of vertex
//draw the min area rectangle
line(temp, pt[0], pt[1],Scalar(255,0,0),2,8);
line(temp, pt[1], pt[2],Scalar(255,0,0),2,8);
line(temp, pt[2], pt[3],Scalar(255,0,0),2,8);
line(temp, pt[3], pt[0],Scalar(255,0,0),2,8);
cout <<"**************形⼼*************"<< endl;
cout <<"X坐标:"<< x <<" Y坐标:"<< y <<" 偏转⾓度:"<< resultRect.angle << endl;    cout <<"*******************************"<< endl;
}
i++;
}
++itc;
}
return temp;
}
ps: 1.代码中最⼩外接矩形主要使⽤了minAreaRect()函数;
2.细⼼的朋友可能会发现,我去掉了轮廓点集中的第⼀组集合,因为第⼀组集合会框选出整个窗⼝,⽬前我也没弄清楚是什么原因,有待改进。
如有错误,欢迎指正!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。