Opencv2.4学习::轮廓外接框

轮廓外接框


使用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

以上博客描述可能有出入,但是说的都是一回事。 

猜你喜欢

转载自blog.csdn.net/dieju8330/article/details/83062793
今日推荐