opencv-python 轮廓线的最小面积的外接旋转矩形 和 旋转
一、函数原型
python
rect = cv2.minAreaRect(points)
输入值:
points:一个形状为 [-1, 1, 2] 的 NumPy 数组,表示轮廓上的点集。这通常是通过 cv2.findContours 函数从二值图像中检测到的轮廓。
返回值
cv2.minAreaRect 返回一个 Box2D 对象,该对象包含最小外接矩形的以下信息:
中心点坐标(center):矩形的中心点 (cx, cy)。
宽高(size):矩形的宽度和高度 (width, height)。注意,这里的宽度不一定总是小于高度;矩形的方向是根据其最小面积自动确定的。
旋转角度(angle):矩形边width顺时针旋转此角度,然后平行于水平轴 X(以度为单位)。角度的范围是 [-90, 0),其中 0 度表示矩形没有旋转(即,与图像的水平轴对齐)。
为了深刻理解,做如下测试:
min_rect =((0, 0), (100, 50), -0) box_points = cv2.boxPoints(min_rect) print(box_points, type(box_points))
#[[-50. 25.]
#[-50. -25.]
#[ 50. -25.]
#[ 50. 25.]] <class 'numpy.ndarray'>
min_rect =((0, 0), (100, 50), -3) box_points = cv2.boxPoints(min_rect) # 左下点,右下点,右上点,左下点 print(box_points, type(box_points)) import math print(( math.cos(-30*3.1415926/180)*50+math.sin(-30*3.1415926/180)*100)/2) print(( math.cos(-120*3.1415926/180)*100+math.sin(-120*3.1415926/180)*50)/2)
二、将旋转矩阵 旋转,第一边长对应的边(可长可宽)与水平轴重合
# -*- coding: utf-8 -*- import cv2 import numpy as np # 读取图像 img = cv2.imread('D:\Python_OpenCV\SC_vantage\part_temp1.png') cv2.imshow("Original image", img) # 应用 Canny 边缘检测 edge_output = cv2.Canny(img, 220, 250) # 应用高斯模糊 #blurred = cv2.GaussianBlur(img, (3, 3), 0) # 查找轮廓(根据 OpenCV 版本调整返回值) # 如果您使用的是 OpenCV 4.x,则应该只接收两个返回值 if cv2.__version__.startswith('4.'): contours, hierarchy = cv2.findContours(edge_output, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) else: _, contours, hierarchy = cv2.findContours(edge_output, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #print(contours[0]) # 绘制轮廓 draw_img = img.copy() #画出原始图像的轮廓 rect_img = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2) for contour in contours:# 取出单个的轮廓值 # 根据坐标在图像上画出旋转矩形 rect = cv2.minAreaRect(contour) # 获取最小外接矩阵,中心点坐标,宽高,旋转角度 # **********旋转************* M = cv2.getRotationMatrix2D( rect[0],rect[2]+180,1) #print(M) # 获取矩形四个顶点,浮点型 box = cv2.boxPoints(rect) # 创建一个与原始数组行数相同、全为1的列 ones_column = np.ones((box.shape[0], 1)) # 将原始数组与全1列水平拼接 new_box = np.hstack((box, ones_column)) # 旋转方式移动坐标点 new_box = np.dot( new_box,np.transpose(M) ) print(new_box ) print(new_box[:,0:2]) rect_img = cv2.drawContours(rect_img,[np.int0(new_box )],0,(0,255,0),2) # **********旋转************* M = cv2.getRotationMatrix2D(rect[0], rect[2] + 180, 1) # 创建一个与原始数组行数相同、全为1的列 print(contour.shape) # 使用 numpy.squeeze() 去除单维度条目 contour= np.squeeze(contour, axis=1) # 你可以指定要去除的轴,但在这里不指定也可以 ones_column = np.ones((contour.shape[0], 1)) # 将原始数组与全1列水平拼接 _contour = np.hstack((contour, ones_column)) # 旋转方式移动坐标点 _contour = np.dot( _contour, np.transpose(M)) print(_contour) min_rect = cv2.drawContours(rect_img,[np.int0(_contour) ],0,(255,255,0),2) cv2.imshow('Rectangles', rect_img) cv2.imwrite('D:/Python_OpenCV/SC_vantage/box2.png', rect_img) cv2.waitKey(0) cv2.destroyAllWindows()
三 (120, 2) 的数组 和 (120,1,2) 的数组 互换
import numpy as np # 假设您有一个形状为 (120, 2) 的数组 array = np.random.rand(120, 2) # 使用 numpy.expand_dims() 在第二个维度(轴1)上增加一个新的大小为1的维度 # 注意:这里的 axis=1 表示我们想要在原始数组的第二个维度上增加新维度 # 因为 NumPy 的轴编号是从0开始的,所以 axis=0 是第一个维度,axis=1 是第二个维度,以此类推 expanded_array = np.expand_dims(array, axis=1) # 打印转换后的数组形状以进行验证 print(expanded_array.shape) # 输出应该是 (120, 1, 2)
import numpy as np # 假设你有一个形状为 (120, 1, 2) 的数组 array = np.random.rand(120, 1, 2) # 使用索引去除单维度条目 indexed_array = array[:, 0, :] # 这里我们取第二个维度(轴1)上的第一个元素(索引为0) # 注意:这种方法会返回一个新的数组,其形状为 (120, 2) print(indexed_array.shape) # 输出应该是 (120, 2)
import numpy as np # 假设你有一个形状为 (120, 1, 2) 的数组 array = np.random.rand(120, 1, 2) # 使用 numpy.squeeze() 去除单维度条目 squeezed_array = np.squeeze(array, axis=1) # 你可以指定要去除的轴,但在这里不指定也可以 # 或者不指定轴,NumPy 会自动去除所有单维度条目 # squeezed_array = np.squeeze(array) print(squeezed_array.shape) # 输出应该是 (120, 2)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步