OpenCV --- 图像预处理(七)

OpenCV --- 图像预处理(七)


文章目录

  • [OpenCV --- 图像预处理(七)](#OpenCV --- 图像预处理(七))
  • 十七,图像轮廓特征查找
    • [17.1 外接矩形](#17.1 外接矩形)
    • [17.2 最小外接矩形](#17.2 最小外接矩形)
    • [17.3 最小外接圆](#17.3 最小外接圆)

十七,图像轮廓特征查找

  • 图像轮廓特征查找其实就是他的外接轮廓。
  • 应用:
    • 图像分割
    • 形状分析
    • 物体检测与识别
  • 根据轮廓点进行,所以要先找到轮廓。
    • 先灰度化、二值化。目标物体白色,非目标物体黑色,选择合适的儿值化方式。
  • 有了轮廓点就可以找到最上、最下、最左、最右的四个坐标, X m i n 、 X m a x 、 Y m i n 、 Y m a x X_{min}、X_{max}、Y_{min}、Y_{max} Xmin、Xmax、Ymin、Ymax。就可以绘制出矩形。

17.1 外接矩形

复制代码
boundingRect(轮廓点)
bash 复制代码
num = cv.imread('txycl/images/num.png')
# 灰度图
gray = cv.cvtColor(num, cv.COLOR_BGR2GRAY)
# 二值化处理
_,binary = cv.threshold(gray, 127, 255, cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
# 查找轮廓
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv.drawContours(num, contours, -1, (0, 0, 255), 2)
cv.imshow('num', num)
# cv.waitKey(0)
# cv.destroyAllWindows()
# 外接矩形x,y,w,h = cv.boundingRect(contours[0])轮廓点
for cnt in contours:
    x, y, w, h = cv.boundingRect(cnt)
    cv.rectangle(num, (x, y), (x + w, y + h), (0, 255, 0), 2)

# 显示效果
cv.imshow('num2', num)
cv.waitKey(0)
cv.destroyAllWindows()

17.2 最小外接矩形

  • 最小外接矩形就是在外接矩形的基础上基于凸包进行旋转卡壳法
  • 假如凸包如下
  • 以其中的一条边为起始边,然后按照逆时针方向计算每个凸包点与起始边的距离,并将距离最大的点记录下来。
  • 以a、b两点为起始边,并计算出e点离起始边最远,那么e到起始边的距离就是一个矩形的高度,因此我们只需要再找出矩形的宽度即可。对于矩形的最右边,以向量 a b ‾ \overline{{a b}} ab为基准,然后分别计算凸包点在向量 a b ‾ \overline{{a b}} ab上的投影的长度,投影最长的凸包点所在的垂直于起始边的直线就是矩形最右边所在的直线。

d点就是在向量 a b ‾ \overline{{a b}} ab上投影最长的凸包点,那么通过d点垂直于直线ab的直线就是矩形的右边界所在的直线。矩形的左边界的也是这么计算的,不同的是使用的向量不是 a b ‾ \overline{{a b}} ab而是 b a ‾ \overline{{b a}} ba

如上图所示,h点垂直于ab的直线就是以ab为起始边所计算出来的矩形所在的左边界所在的直线。其中矩形的高就是e点到直线ab的距离,矩形的宽是h点在向量上 b a ‾ \overline{{b a}} ba的投影加上d点在向量 a b ‾ \overline{{a b}} ab上的投影减去ab的长度,即:
w i d t h = ∣ b h ‾ ∣ × cos ⁡ a + ∣ a d ‾ ∣ × cos ⁡ θ − ∣ a b ‾ ∣ w i d t h=|\overline{{{b h}}}|\times\cos a+|\overline{{{a d}}}|\times\cos\theta-|\overline{{{a b}}}| width=∣bh∣×cosa+∣ad∣×cosθ−∣ab∣

于是我们就有了以ab为起始边所构成的外接矩形的宽和高,这样就可以得到该矩形的面积。然后再以bc为起始边,并计算其外接矩形的面积。也就是说凸多边形有几个边,就要构建几次外接矩形,然后找到其中面积最小的矩形作为该凸多边形的最小外接矩形

  • API

    contours, hierarchy = cv2.findContours(image_np_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

contours为二值图像上查找所有的外部轮廓

复制代码
rect = cv2.minAreaRect(cnt)

传入的cnt参数为contours中的轮廓,可以遍历contours中的所有轮廓,然后计算出每个轮廓的小面积外接矩形

  • rect 是计算轮廓最小面积外接矩形:rect 结构通常包含中心点坐标 (x, y)、宽度 width、高度 height 和旋转角度 angle

    cv2.boxPoints(rect).astype(int)

cv2.boxPoints(rect)返回 是一个形状为 4行2列的数组,每一行代表一个点的坐标(x, y),顺序按照逆时针或顺时针方向排列

将最小外接矩形转换为边界框的四个角点,并转换为整数坐标

复制代码
cv2.drawContours(image, contours, contourIdx, color, thickness)
  • image:原图像,一般为 numpy 数组,通常为灰度或彩色图像。
  • contours:一个包含多个轮廓的列表,可以用上一个api得到的 [box]
  • contourIdx :要绘制的轮廓索引。如果设置为 -1,则绘制所有轮廓。
  • color :轮廓的颜色,可以是 BGR 颜色格式的三元组,例如 (0, 0, 255) 表示红色。
  • thickness:轮廓线的粗细,如果是正数,则绘制实线;如果是 0,则绘制轮廓点;如果是负数,则填充轮廓内部区域。
bash 复制代码
#最小轮廓矩形
# 读取图像
num = cv.imread("txycl/images/num.png")
# 灰度化
gray = cv.cvtColor(num, cv.COLOR_BGR2GRAY)
# 二值化
thresh, binary = cv.threshold(gray, 127, 255, cv.THRESH_OTSU + cv.THRESH_BINARY_INV)
# 查找轮廓
cnts, h = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# 遍历每个轮廓
for cnt in cnts:
    # 获取外接矩形
    x, y, w, h = cv.boundingRect(cnt)
    # 绘制外接矩形
    cv.rectangle(num, (x, y), (x + w, y + h), (255, 0, 0), 2, cv.LINE_AA)
    # 获取凸包
    hull = cv.convexHull(cnt)
    # 绘制凸包
    cv.polylines(num, [hull], True, (0, 0, 255), 2, cv.LINE_AA)
    # 获取最小外接矩形
    rect = cv.minAreaRect(cnt)
    box = cv.boxPoints(rect).astype(np.int32)
    # 绘制最小外接矩形
    cv.drawContours(num, [box], -1, (0, 255, 0), 2, cv.LINE_AA)
# 显示图像
cv.imshow("num", num)
cv.waitKey(0)
cv.destroyAllWindows()

17.3 最小外接圆

寻找最小外接圆使用的算法是Welzl算法。Welzl算法基于一个定理:希尔伯特圆定理表明,对于平面上的任意三个不在同一直线上的点,存在一个唯一的圆同时通过这三个点,且该圆是最小面积的圆(即包含这三个点的圆中半径最小的圆,也称为最小覆盖圆

  • API

    cv2.minEnclosingCircle(points) -> (center, radius)

参数说明:

  • points:输入参数图片轮廓数据

返回值:

  • center:一个包含圆心坐标的二元组 (x, y)

  • radius:浮点数类型,表示计算得到的最小覆盖圆的半径。

    cv2.circle(img, center, radius, color, thickness)

  • img:输入图像,通常是一个numpy数组,代表要绘制圆形的图像。

  • center:一个二元组 (x, y),表示圆心的坐标位置。

  • radius:整型或浮点型数值,表示圆的半径长度。

  • color:颜色标识,可以是BGR格式的三元组 (B, G, R),例如 (255, 0, 0) 表示红色。

  • thickness:整数,表示圆边框的宽度。如果设置为 -1,则会填充整个圆。

bash 复制代码
#最小外接圆
# 读取图像
num = cv.imread("txycl/images/num.png")
# 灰度化
gray = cv.cvtColor(num, cv.COLOR_BGR2GRAY)
# 二值化
thresh, binary = cv.threshold(gray, 127, 255, cv.THRESH_OTSU + cv.THRESH_BINARY_INV)
# 查找轮廓
cnts, h = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# 遍历每个轮廓
for cnt in cnts:
    # 获取外接圆
    (x, y), radius = cv.minEnclosingCircle(cnt)
    # 绘制外接圆
    center = (int(x), int(y))
    radius = int(radius)
    cv.circle(num, center, radius, (255, 0, 0), 2, cv.LINE_AA)
    
#显示图像
cv.imshow("num", num)
cv.waitKey(0)
cv.destroyAllWindows()



相关推荐
deephub1 小时前
CLIMB自举框架:基于语义聚类的迭代数据混合优化及其在LLM预训练中的应用
人工智能·深度学习·大语言模型·聚类
思通数科AI全行业智能NLP系统2 小时前
AI视频技术赋能幼儿园安全——教师离岗报警系统的智慧守护
大数据·人工智能·安全·目标检测·目标跟踪·自然语言处理·ocr
struggle20253 小时前
deepseek-cli开源的强大命令行界面,用于与 DeepSeek 的 AI 模型进行交互
人工智能·开源·自动化·交互·deepseek
ocr_sinosecu14 小时前
OCR定制识别:解锁文字识别的无限可能
人工智能·机器学习·ocr
奋斗者1号4 小时前
分类数据处理全解析:从独热编码到高维特征优化
人工智能·机器学习·分类
契合qht53_shine4 小时前
深度学习 视觉处理(CNN) day_02
人工智能·深度学习·cnn
就叫飞六吧5 小时前
如何判断你的PyTorch是GPU版还是CPU版?
人工智能·pytorch·python
zsffuture5 小时前
opencv 读取3G大图失败,又不想重新编译opencv ,可以如下操作
人工智能·opencv·webpack
AntBlack5 小时前
别说了别说了 ,Trae 已经在不停优化迭代了
前端·人工智能·后端
訾博ZiBo5 小时前
AI日报 - 2025年04月28日
人工智能