轮廓外接框
使用findcontours找到轮廓后,由于物体轮廓基本不规则,因此我们一般用规则的框来框取检测到的轮廓
常见的有矩形、圆形、椭圆等。
基本函数
1、寻找包括点集的最小圆
C++: void minEnclosingCircle(InputArray points, Point2f& center, float& radius)
- InputArray points:输入的二维点集
- Point2f& center:表示输出的圆形的中心坐标,是float型
- float& radius:输出的最小圆的半径,是float型
2、最小矩形【带角度】
cv::RotatedRect minAreaRect(InputArray points)
- points:输入信息,可以为包含点的容器(vector)或是Mat。输入的一般为findcontours找到的轮廓
- 返回包覆输入信息的最小斜矩形。即为该矩形的中心点和四个端点
3、外界矩形【不带角度】
C++:Rect boundingRect(InputArray points)
- 输入:同上
- 输出:返回矩形参数,起始点x,y,矩形宽度和高度
调用代码:
(1)绘制两种矩形
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void main()
{
Mat srcImage = imread("F:\\opencv_re_learn\\flash.jpg");
if (!srcImage.data){
cout << "failed to read" << endl;
system("pause");
return;
}
Mat srcGray, srcThresh;
cvtColor(srcImage, srcGray, CV_BGR2GRAY);//灰度图
imshow("gray", srcGray);
threshold(srcGray, srcThresh, 200, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);//二值化
imshow("thresh", srcThresh);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(srcThresh, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
vector<Rect> boundRect(contours.size()); //定义外接矩形集合
vector<RotatedRect> box(contours.size()); //定义最小外接矩形集合
Point2f rect[4];
for (int i = 0; i < contours.size(); i++){//对找到的每个轮廓遍历
box[i] = minAreaRect(Mat(contours[i])); //计算每个轮廓最小外接矩形
boundRect[i] = boundingRect(Mat(contours[i]));//普通矩形
//绘制
circle(srcImage, Point(box[i].center.x, box[i].center.y), 5, Scalar(0, 255, 0), -1, 8); //绘制最小外接矩形的中心点
box[i].points(rect); //把最小外接矩形四个端点复制给rect数组
rectangle(srcImage, Point(boundRect[i].x, boundRect[i].y),
Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8);
for (int j = 0; j < 4; j++){
line(srcImage, rect[j], rect[(j + 1) % 4], Scalar(0, 0, 255), 2, 8); //绘制最小外接矩形每条边
}
}
imshow("src", srcImage);
waitKey(0);
}
(2)外接圆
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void main()
{
Mat srcImage = imread("F:\\opencv_re_learn\\flash.jpg");
if (!srcImage.data){
cout << "failed to read" << endl;
system("pause");
return;
}
Mat srcGray, srcThresh;
cvtColor(srcImage, srcGray, CV_BGR2GRAY);//灰度图
imshow("gray", srcGray);
threshold(srcGray, srcThresh, 200, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);//二值化
imshow("thresh", srcThresh);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(srcThresh, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
vector<Point2f>center(contours.size());
vector<float>radius(contours.size());
for (int i = 0; i < contours.size(); i++){//对找到的每个轮廓遍历
circle(srcImage, center[i], cvRound(radius[i]), Scalar(0, 100, 255),
1, CV_AA);
}
imshow("src", srcImage);
waitKey(0);
}
关于minAreaRect返回角度的讨论
一张图可以让你看懂
关于详细的讨论,参考博客:
https://blog.csdn.net/qq_24237837/article/details/77850496
https://blog.csdn.net/u010403272/article/details/78890410
https://blog.csdn.net/vola9527/article/details/81093805
以上博客描述可能有出入,但是说的都是一回事。