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)
复制代码

 

posted @   辛河  阅读(42)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示