【OpenCV学习笔记】二十八、轮廓特征属性及应用(五)——最小外接矩形

轮廓特征属性及应用(五)——最小外接矩形

1.轮廓最小外接矩形——minAreaRect()

2.完成了三个应用:轮廓最小外接矩形的绘制 、粗略计算物体像素长宽、倾斜物体矫正提取

先上ppt:

【OpenCV学习笔记】二十八、轮廓特征属性及应用(五)——最小外接矩形_第1张图片


【OpenCV学习笔记】二十八、轮廓特征属性及应用(五)——最小外接矩形_第2张图片


【OpenCV学习笔记】二十八、轮廓特征属性及应用(五)——最小外接矩形_第3张图片

代码:1.轮廓最小外接矩形的绘制 

///轮廓最小外接矩形的绘制 
#include "opencv2/opencv.hpp"  
using namespace cv;
#include   
using namespace std;
int main()
{
	//1.查找轮廓  
	//1.1查找轮廓前的预处理(灰度图,阈值化)  
	Mat srcImg = imread("10.png", CV_LOAD_IMAGE_COLOR);
	imshow("srcImg", srcImg);
	Mat copyImg = srcImg.clone();
	cvtColor(srcImg, srcImg, CV_BGR2GRAY);
	threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
	imshow("threshold", srcImg);
	vector > contours;
	vector hierarcy;//没用到  
	//1.2查找轮廓  
	findContours(srcImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//最外层轮廓  
	//1.3绘制所有轮廓  
	drawContours(copyImg, contours, -1, Scalar(0, 255, 0), 1, 8);
	//*2.由轮廓确定正外接矩形及最小外接矩形 
	//2.1 定义Rect类型的vector容器boundRect存放正外接矩形,初始化大小为contours.size()即轮廓个数  
	vector boundRect(contours.size());
	//*2.2 定义Rect类型的vector容器roRect存放最小外接矩形,初始化大小为contours.size()即轮廓个数  
	vector roRect(contours.size());
	//2.3 遍历每个轮廓  
	for (int i = 0; i < contours.size(); i++)
	{
		//2.4 由轮廓(点集)确定出正外接矩形并绘制
		boundRect[i] = boundingRect(Mat(contours[i]));
		//2.4.1获得正外接矩形的左上角坐标及宽高  
		int width = boundRect[i].width;
		int height = boundRect[i].height;
		int x = boundRect[i].x;
		int y = boundRect[i].y;
		//2.4.2用画矩形方法绘制正外接矩形  
		rectangle(copyImg, Rect(x, y, width, height), Scalar(255, 0, 0), 2, 8);
		//*2.5 由轮廓(点集)确定出最小外接矩形并绘制
		roRect[i] = minAreaRect(Mat(contours[i]));
		//*2.5.1 旋转矩形类RotatedRect中有Point()方法,参数Point2f* pts,将旋转矩形的四个端点存储进pts.
		Point2f pts[4] = { 0 };
		roRect[i].points(pts);
		//*2.5.2 用line方法,根据旋转矩形的四个角点画出矩形
		line(copyImg, pts[0], pts[1], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[0], pts[3], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[2], pts[1], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[2], pts[3], Scalar(0, 0, 255), 2, 8);
	}
	imshow("轮廓和正外接矩形和最小外接矩形", copyImg);
	waitKey(0);
	return 0;
}

运行结果:

【OpenCV学习笔记】二十八、轮廓特征属性及应用(五)——最小外接矩形_第4张图片

代码:2.粗略计算物体像素长宽

///粗略计算物体像素长宽
#include "opencv2/opencv.hpp"  
using namespace cv;
#include   
using namespace std;
int main()
{
	//1.查找轮廓  
	//1.1查找轮廓前的预处理(灰度图,阈值化)  
	Mat srcImg = imread("cup.jpg", CV_LOAD_IMAGE_COLOR);
	imshow("srcImg", srcImg);
	Mat copyImg = srcImg.clone();
	cvtColor(srcImg, srcImg, CV_BGR2GRAY);
	threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY_INV); //要保证黑中找白
	imshow("threshold", srcImg);
	vector > contours;
	vector hierarcy;//没用到  
	//1.2查找轮廓  
	findContours(srcImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//最外层轮廓  
	//1.3绘制所有轮廓  
	drawContours(copyImg, contours, -1, Scalar(0, 255, 0), 1, 8);
	//2.由轮廓确定正外接矩形及最小外接矩形 
	//2.1 定义Rect类型的vector容器boundRect存放正外接矩形,初始化大小为contours.size()即轮廓个数  
	vector boundRect(contours.size());
	//2.2 定义Rect类型的vector容器roRect存放最小外接矩形,初始化大小为contours.size()即轮廓个数  
	vector roRect(contours.size());
	//2.3 遍历每个轮廓  
	for (int i = 0; i < contours.size(); i++)
	{
		//2.4 由轮廓(点集)确定出正外接矩形并绘制
		boundRect[i] = boundingRect(Mat(contours[i]));
		//2.4.1获得正外接矩形的左上角坐标及宽高  
		int width = boundRect[i].width;
		int height = boundRect[i].height;
		int x = boundRect[i].x;
		int y = boundRect[i].y;
		//2.4.2用画矩形方法绘制正外接矩形  
		rectangle(copyImg, Rect(x, y, width, height), Scalar(255, 0, 0), 2, 8);
		//2.5 由轮廓(点集)确定出最小外接矩形并绘制
		//旋转矩形主要成员有center、size、 angle、points()
		roRect[i] = minAreaRect(Mat(contours[i]));
		//2.5.1 旋转矩形类RotatedRect中有Point()方法,参数Point2f* pts,将旋转矩形的四个端点存储进pts.
		Point2f pts[4] = { 0 };
		roRect[i].points(pts);
		//2.5.2 用line方法,根据旋转矩形的四个角点画出矩形
		line(copyImg, pts[0], pts[1], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[0], pts[3], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[2], pts[1], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[2], pts[3], Scalar(0, 0, 255), 2, 8);
		//*2.5.3 由旋转矩形的center成员得出中心点
		Point center = roRect[i].center;
		//*2.5.4 用circle方法画出中心点center
		circle(copyImg, center, 5, Scalar(0, 255, 0), -1, 8);
		//*2.5.5 由旋转矩形的size成员得出宽和高
		double widthRotated = roRect[i].size.width;
		double heightRotated = roRect[i].size.height;
		char widthStr[20] = { 0 };
		char heightStr[20] = { 0 };
		sprintf(widthStr, "width:%.2f", widthRotated);
		sprintf(heightStr, "height:%.2f", heightRotated);
		//*2.5.6 用putText方法将最小外接矩形的宽高显示在图像上
		putText(copyImg,widthStr,Point(center.x,center.y+50),CV_FONT_HERSHEY_PLAIN,1,Scalar(64,64,255),1,8);
		putText(copyImg, heightStr, Point(center.x, center.y + 80), CV_FONT_HERSHEY_PLAIN, 1, Scalar(64,64,255), 1, 8);
	}
	imshow("粗略计算物体像素长宽", copyImg);
	waitKey(0);
	return 0;
}

运行结果:

【OpenCV学习笔记】二十八、轮廓特征属性及应用(五)——最小外接矩形_第5张图片

代码:3.倾斜物体矫正提取

///倾斜物体矫正提取
#include "opencv2/opencv.hpp"  
using namespace cv;
#include   
using namespace std;
int main()
{
	//1.查找轮廓  
	//1.1查找轮廓前的预处理(二值化(Canny边缘检测))  
	Mat srcImg = imread("qrcode.jpg", CV_LOAD_IMAGE_COLOR);
	imshow("srcImg", srcImg);
	Mat copyImg = srcImg.clone();
	cvtColor(srcImg, srcImg, CV_BGR2GRAY);
	Canny(srcImg,srcImg,100,200);
	Mat kernel = getStructuringElement(MORPH_RECT,Size(5,5),Point(-1,-1));
	dilate(srcImg,srcImg,kernel,Point(-1,-1));
	erode(srcImg,srcImg,kernel,Point(-1,-1));
	imshow("预处理", srcImg);
	vector > contours;
	vector hierarcy;//没用到  
	//1.2查找轮廓  
	findContours(srcImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//最外层轮廓  
	//1.3绘制所有轮廓  
	drawContours(copyImg, contours, -1, Scalar(0, 255, 0), 1, 8);
	//2.由轮廓确定正外接矩形及最小外接矩形 
	//2.1 定义Rect类型的vector容器boundRect存放正外接矩形,初始化大小为contours.size()即轮廓个数  
	vector boundRect(contours.size());
	//2.2 定义Rect类型的vector容器roRect存放最小外接矩形,初始化大小为contours.size()即轮廓个数  
	vector roRect(contours.size());
	//2.3 遍历每个轮廓  
	for (int i = 0; i < contours.size(); i++)
	{
		//2.4 由轮廓(点集)确定出正外接矩形并绘制
		boundRect[i] = boundingRect(Mat(contours[i]));
		//2.4.1 获得正外接矩形的左上角坐标及宽高  
		int width = boundRect[i].width;
		int height = boundRect[i].height;
		int x = boundRect[i].x;
		int y = boundRect[i].y;
		//*2.4.2 通过正外接矩形的宽高,进行一次筛选,小的直接滤过
		if (width < 100 || height < 100)
			continue;
		//2.4.3 用画矩形方法绘制正外接矩形  
		rectangle(copyImg, Rect(x, y, width, height), Scalar(255, 0, 0), 2, 8);
		//2.5 由轮廓(点集)确定出最小外接矩形并绘制
		//旋转矩形主要成员有center、size、 angle、points()
		roRect[i] = minAreaRect(Mat(contours[i]));
		//2.5.1 旋转矩形类RotatedRect中有Point()方法,参数Point2f* pts,将旋转矩形的四个端点存储进pts.
		Point2f pts[4] = { 0 };
		roRect[i].points(pts);
		//2.5.2 用line方法,根据旋转矩形的四个角点画出矩形
		line(copyImg, pts[0], pts[1], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[0], pts[3], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[2], pts[1], Scalar(0, 0, 255), 2, 8);
		line(copyImg, pts[2], pts[3], Scalar(0, 0, 255), 2, 8);
		//2.5.3 由旋转矩形的center成员得出中心点
		Point center = roRect[i].center;
		//2.5.4 用circle方法画出中心点center
		circle(copyImg, center, 5, Scalar(0, 255, 0), -1, 8);
		double angle = roRect[i].angle;
		//*2.6 通过仿射变换旋转图像
		//2.6.1对角度的处理(经验值)
		if (0 < abs(angle) && abs(angle) <= 45)  //逆时针
			angle = angle;
		else if (45 < abs(angle) && abs(angle) < 90) //顺时针
			angle = 90 - abs(angle);
		Mat M = getRotationMatrix2D(center,angle,1);
		warpAffine(copyImg,copyImg,M,copyImg.size());
		//*2.7定义ROI,将矫正后的二维码保存到本地
		double roWidth = roRect[i].size.width;
		double roHeight = roRect[i].size.height;
		Mat ROI = copyImg(Rect(center.x-roWidth/2,center.y-roHeight/2,roWidth,roHeight));
		imshow("ROI",ROI);
		imwrite("E:\\temp\\ROI.jpg",ROI);
	}
	imshow("倾斜物体矫正", copyImg);
	waitKey(0);
	return 0;
}

运行结果:

【OpenCV学习笔记】二十八、轮廓特征属性及应用(五)——最小外接矩形_第6张图片



你可能感兴趣的:(OpenCV学习笔记)