Opencv绘制最小外接矩形、最小外接圆

本文介绍如何使用Opencv的minAreaRect和minEnclosingCircle方法求点集的最小外接矩形和最小外接圆。通过具体代码示例展示了从图像预处理到轮廓检测,再到最小外接矩形和圆的绘制全过程。


Opencv中求点集的最小外结矩使用方法minAreaRect,求点集的最小外接圆使用方法minEnclosingCircle。


minAreaRect方法原型:

RotatedRect minAreaRect( InputArray points );


输入参数points是所要求最小外结矩的 点集数组或向量


minEnclosingCircle方法原型:

void minEnclosingCircle( InputArray points,
                                      CV_OUT Point2f& center, CV_OUT float& radius );


第一个参数points是所要求最小外结圆的点集数组或向量;

第二个参数Point2f类型的center是求得的最小外接圆的中心坐标;

第三个参数float类型的radius是求得的最小外接圆的半径;



使用minAreaRect和minEnclosingCircle方法分别求最小外接矩和圆:


<span style="font-size:18px;">#include "core/core.hpp"  
#include "highgui/highgui.hpp"  
#include "imgproc/imgproc.hpp"  
#include "iostream"

using namespace std; 
using namespace cv;  

int main(int argc,char *argv[])  
{
	Mat imageSource=imread(argv[1],0);
	imshow("Source Image",imageSource);
	Mat image;
	blur(imageSource,image,Size(3,3));
	threshold(image,image,0,255,CV_THRESH_OTSU);	
	imshow("Threshold Image",image);

	//寻找最外层轮廓
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(image,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_NONE,Point());

	Mat imageContours=Mat::zeros(image.size(),CV_8UC1);	//最小外接矩形画布
	Mat imageContours1=Mat::zeros(image.size(),CV_8UC1); //最小外结圆画布
	for(int i=0;i<contours.size();i++)
	{		
		//绘制轮廓
		drawContours(imageContours,contours,i,Scalar(255),1,8,hierarchy);
		drawContours(imageContours1,contours,i,Scalar(255),1,8,hierarchy);


		//绘制轮廓的最小外结矩形
		RotatedRect rect=minAreaRect(contours[i]);
		Point2f P[4];
		rect.points(P);
		for(int j=0;j<=3;j++)
		{
			line(imageContours,P[j],P[(j+1)%4],Scalar(255),2);
		}

		//绘制轮廓的最小外结圆
		Point2f center; float radius;
		minEnclosingCircle(contours[i],center,radius);
		circle(imageContours1,center,radius,Scalar(255),2);

	}
	imshow("MinAreaRect",imageContours);	
	imshow("MinAreaCircle",imageContours1);	
	waitKey(0);
	return 0;
}</span>


作图步骤:

1. 对原始图像均值滤波并二值化;

2. 求图像的最外层轮廓;

3.  使用minAreaRect方法求轮廓的最小外接矩形,转化求得矩形的四个顶点坐标,并绘制矩形;

4.  使用minEnclosingCircle方法求轮廓的最小外接圆,获取圆心和半径信息,并绘制圆;


原始图像:



最小外接矩:



最小外接圆:


### 如何使用 OpenCV 计算椭圆的外接矩形 在 OpenCV 中,可以通过 `cv2.fitEllipse` 函数拟合一个椭圆到一组点上,并返回该椭圆的相关参数。为了获取这个椭圆的外接矩形,可以利用这些参数进一步计算其边界框。 以下是具体实现方法: #### 1. 拟合椭圆并提取参数 函数 `cv2.fitEllipse(points)` 可以用于拟合椭圆,其中输入是一个二维点集数组。它会返回一个元组 `(center, axes, angle)`,分别表示椭圆中心坐标、轴长度以及旋转角度[^1]。 ```python import numpy as np import cv2 # 假设 points 是一组轮廓点 points = np.array([[x1, y1], [x2, y2], ...]) # 替换为实际数据 ellipse = cv2.fitEllipse(points) (center, (width, height), angle) = ellipse ``` #### 2. 构造外接矩形 一旦得到了椭圆的信息,就可以通过构造一个围绕它的最小面积矩形来获得外接矩形。这一步可以直接调用 `cv2.boundingRect()` 或者更精确地使用 `cv2.minAreaRect()` 来得到旋转后的矩形。 对于非旋转版本(直角矩形),可采用以下代码: ```python rect = cv2.boundingRect(np.int32([points])) (x, y, w, h) = rect print(f"Bounding Rectangle: Top-left corner ({x}, {y}), Width={w}, Height={h}") ``` 如果需要考虑旋转情况,则应改用 `cv2.minAreaRect()` 方法: ```python rotated_rect = cv2.minAreaRect(points) box_points = cv2.boxPoints(rotated_rect) box_points = np.int0(box_points) print("Rotated Bounding Box Points:", box_points) ``` 上述两部分结合起来能够满足不同场景下对外接矩形的需求。 #### 完整示例代码 下面提供了一个完整的例子展示如何从给定的一系列点出发找到它们所形成形状的最佳匹配椭圆及其对应的外接矩形。 ```python import cv2 import numpy as np def draw_ellipse_and_bounding_box(image_path): img = cv2.imread(image_path, 0) _, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2:] if not contours: print("No contours detected.") return None cnt = max(contours, key=cv2.contourArea) ellipse = cv2.fitEllipse(cnt) center, axes, angle = ellipse result_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) cv2.ellipse(result_img, ellipse, (0, 255, 0), 2) # Draw fitted ellipse rotated_rect = cv2.minAreaRect(cnt) box_points = cv2.boxPoints(rotated_rect) box_points = np.int0(box_points) cv2.drawContours(result_img,[box_points],0,(255,0,0),2) # Draw min area rectangle straight_rect = cv2.boundingRect(cnt) x,y,w,h = straight_rect cv2.rectangle(result_img,(x,y),(x+w,y+h),(0,0,255),2) # Draw bounding rectangle return result_img result = draw_ellipse_and_bounding_box('your_image.png') if result is not None: cv2.imshow('Result', result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 此脚本读入一幅灰度图,在二值化之后查找最大连通域作为目标对象,接着绘制出相应的椭圆与两种类型的包围盒。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值