二值图像分析—轮廓最小外接矩形

本文介绍如何使用OpenCV的minAreaRect函数来查找包含输入二维点集的最小旋转矩形,提供了两个实际应用案例,一是画出图像中的最小外接矩形,二是进行倾斜物体的矫正提取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OpenCV中最小外接矩形

  • 说明
    brief Finds a rotated rectangle of the minimum area enclosing the input 2D point set.
    查找包含输入二维点集的最小区域的旋转矩形。

    该函数计算并返回指定点集的最小区域边界矩形(可能已旋转)。开发人员应记住,当数据接近包含Mat元素的边界时,返回的RotatedRect可以包含负索引。
    在这里插入图片描述

  • 声明

    RotatedRect minAreaRect( InputArray points );
    
  • 参数
    points: 输入的存储在std::vector<>或Mat中的二维向量点。

    返回值: RotatedRect类矩形对象,外接旋转矩形主要成员有:center、size、angle、points

应用

  • 应用1——画出最小外接矩形
void minBinaryImgAreaRect(Mat &src) {
	//1.查找轮廓
	//1.1转化成灰度图像
	Mat dst, gray, binary;
	imshow("src", src);
	cvtColor(src, gray, COLOR_BGR2GRAY);
	imshow("gray", gray);
	//1.2转化成二值图像
	threshold(gray, binary, 100, 255, THRESH_BINARY | THRESH_OTSU);
	imshow("binary", binary);
	//1.3 查找所有轮廓
	vector<vector<Point>> contours;
	findContours(binary, contours, RETR_LIST, CHAIN_APPROX_NONE);



	//2.确定最小外接矩形
	//2.1 定义RotatedRect类型的vector容器rotatedRects存放最小外接矩形,初始化大小为轮廓的个数。
	vector<RotatedRect> rotatedRects(contours.size());
	int x = 0;
	int y = 0;
	int w = 0;
	int h = 0;
	//2.2遍历每一个轮廓
	for (int i = 0; i < contours.size(); i++)
	{

		//2.3 由轮廓(点集)确定出最小外接矩形
		rotatedRects[i] = minAreaRect(contours[i]);
		//2.31 旋转矩形类RotatedRect中有Point()方法,参数Point2f* pts,将旋转矩形的四个端点存储进pts.
		Point2f pts[4] = { Point(0,0) };
		rotatedRects[i].points(pts);


		//2.4 画出最小外接矩形
		RNG rng(time(0)); 
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
	
		//rectangle(src, pts[0],pts[2], color, 2);
		
		line(src, pts[0], pts[1], color, 2, 8);
		line(src, pts[1], pts[2], color, 2, 8);
		line(src, pts[2], pts[3], color, 2, 8);
		line(src, pts[3], pts[0], color, 2, 8);
		
	}
	imshow("dst", src);
	
}

int main() {
	Mat src = imread("D:/test/huahua.png");	
	minBinaryImgAreaRect(src);

	waitKey(0);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


  • 应用2——倾斜物体矫正提取

    知识点:

  1. 使用Canny算法在输入图像中找到边缘,并在输出地图边缘中对其进行标记。
    OpenCV–035: Canny边缘检测器

  2. 形态学操作

void minBinaryImgAreaRect(Mat &src) {
	//1.查找轮廓
	//1.1转化成灰度图像
	Mat dst,binary;
	dst = src.clone();
	imshow("src", src);
	cvtColor(src, src, COLOR_BGR2GRAY);
	Canny(src, src, 100, 200);
	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
	dilate(src, src, kernel, Point(-1, -1));
	erode(src, src, kernel, Point(-1, -1));
	imshow("预处理", src);

	
	//threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
	//imshow("binary", binary);
	//1. 查找所有轮廓
	vector<vector<Point>> contours;
	findContours(src, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

	//2.确定最小外接矩形
	//2.1.1 定义Rect类型的vector容器boundRect存放正外接矩形,初始化大小为contours.size()即轮廓个数  
	vector<Rect> boundRect(contours.size());
	//2.1.2 定义RotatedRect类型的vector容器rotatedRects存放最小外接矩形,初始化大小为轮廓的个数。
	vector<RotatedRect> rotatedRects(contours.size());
	int x = 0;
	int y = 0;
	int w = 0;
	int h = 0;
	//2.2遍历每一个轮廓
	for (int i = 0; i < contours.size(); i++)
	{
		//2.3 由轮廓(点集)确定出正外接矩形并绘制
		boundRect[i] = boundingRect(Mat(contours[i]));
		//2.3.1 获得正外接矩形的左上角坐标及宽高  
		w = boundRect[i].width;
		h = boundRect[i].height;
        x = boundRect[i].x;
		y = boundRect[i].y;
		//2.3.2 通过正外接矩形的宽高,进行一次筛选,小的直接滤过
		if (w < 100 || h < 100)
			continue;
		//2.3.3 画出正外接矩形
		rectangle(dst, Rect(x, y, w, h), Scalar(255, 0, 0), 2, 8);
	    //2.4 由轮廓(点集)确定出最小外接矩形
		rotatedRects[i] = minAreaRect(contours[i]);
		//2.4.1 旋转矩形类RotatedRect中有Point()方法,参数Point2f* pts,将旋转矩形的四个端点存储进pts.
		Point2f pts[4] = { Point(0,0) };
		rotatedRects[i].points(pts);


		//2.5 画出最小外接矩形
		RNG rng(time(0)); 
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
	
		//rectangle(src, pts[0],pts[2], color, 2);
		line(dst, pts[0], pts[1], color, 2, 8);
		line(dst, pts[1], pts[2], color, 2, 8);
		line(dst, pts[2], pts[3], color, 2, 8);
		line(dst, pts[3], pts[0], color, 2, 8);

		//3. 通过仿射变换变换图像
		//3.1 求出最小外接矩形的中心点并画出中心点
		Point center=rotatedRects[i].center;
		circle(src, center, 5, color, -1);
		//3.2 求出图形的旋转角度
		double angle = rotatedRects[i].angle;
		//3.3 通过仿射变换旋转图像
		//3.31 对角度进行处理
		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(dst, dst, m, src.size());
		//3.4 
		double w = rotatedRects[i].size.width;
		double h = rotatedRects[i].size.height;
		Mat roi = dst(Rect(center.x - w / 2, center.y - h / 2, w, h));
		String name="";
		name += i;
		cout << "name=" << name << endl;
	    imshow(name, roi);		
	}
	imshow("dst", dst);
	
}

在这里插入图片描述
canny:
在这里插入图片描述
预处理:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

学习:
opencv绘制轮廓的外接矩形和圆

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

C++ OpenCV案例实战—卡片截取

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值