当前位置: 首页 > news >正文

【图像轮廓特征查找】图像处理(OpenCV) -part8

17 图像轮廓特征查找

图像轮廓特征查找其实就是他的外接轮廓。

应用:

        图像分割

        形状分析

        物体检测与识别

根据轮廓点进行,所以要先找到轮廓。

先灰度化、二值化。目标物体白色,非目标物体黑色,选择合适的儿值化方式。

有了轮廓点就可以找到最上、最下、最左、最右的四个坐标,X_{min}、X_{max}、Y_{min}、Y_{max}。就可以绘制出矩形。

17.1 外接矩形

boundingRect(轮廓点)

形状的外接矩形有两种,如下图,绿色的叫外接矩形,表示不考虑旋转并且能包含整个轮廓的矩形。其中,外接矩形可根据获得到的轮廓坐标中最上、最下、最左、最右的点的坐标来绘制外接矩形,也就是下图中的绿色矩形。蓝色的是最小外接矩形,会考虑面积。

cv.boundingRect 函数用于计算一组点(通常是轮廓)的最小外接矩形。这个矩形是一个 轴对齐的矩形,也就是说,它的边与图像坐标轴平行。

作用

快速获取一个能够包含目标轮廓的矩形边界。

简单直观地定位目标轮廓的大致区域。

返回参数

x:外接矩形左上角的 x 坐标。

y:外接矩形左上角的 y 坐标。

w:外接矩形的宽度。

h:外接矩形的高度。


import cv2 as cv
import numpy as np
img = cv.imread('images/ikun4.jpg')
#灰度图
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
#二值化处理,阈值法 因为目标是白色我们需要白色
ret, binary = cv.threshold(gray, 200, 255, cv.THRESH_BINARY_INV)
#查找轮廓
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):#查找凸包hull = cv.convexHull(contours[i])#绘制凸包cv.polylines(img, [hull], True, (100, 100, 255), 3)
#画出外接矩形
for i in range(len(contours)):x, y, w, h = cv.boundingRect(contours[i])cv.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2)
cv.imshow('1', img)
# cv.imshow('2', binary)
cv.waitKey(0)
cv.destroyAllWindows()

获取方式

在代码中,通过循环遍历查找到的轮廓 contours,对每个轮廓调用 cv.boundingRect 函数来获取其外接矩形的位置和大小参数,包括左上角顶点坐标(x,y)、宽度 w 和高度 h。

绘制目的

使用 cv.rectangle 函数在原图上绘制出这些外接矩形,通过矩形的边界将目标轮廓大致框选出来,便于更直观地观察和分析目标在图像中的分布情况,以及与其他图像元素的相对位置关系。

17.2 最小外接矩形

定义与原理

最小外接矩形 是能够完全包含目标轮廓的最小面积的矩形,它允许矩形相对于图像坐标轴旋转,因此可以更好地贴合轮廓的形状,相比普通外接矩形(轴对齐的外接矩形),它可以更精确地描述轮廓的形状和方向。

其基本原理是通过计算轮廓点集的最小面积矩形,这个矩形的边不一定与图像坐标轴对齐。它需要找到一组四个点,使得这四个点构成的矩形能够包含所有轮廓点,并且面积是所有可能的包含该轮廓的矩形中最小的。

计算方法

从轮廓点集出发,利用几何算法来确定最小外接矩形的边界。

一种常见的方法是基于旋转卡壳(Rotating Calipers)算法,它通过旋转两条平行的切线来寻找能够包含整个点集的最小矩形。具体步骤为:首先找到点集的凸包;然后在凸包上选择两个点作为初始两个的顶点,这两点确定一条边;接着,寻找与该边相对的另一条边,使得这两条边之间的距离最大,从而形成一个初始的矩形;最后,逐步旋转这两条边,找到使矩形面积最小的那一对边,从而确定最小外接矩形。

在 OpenCV 中,可以通过 cv.minAreaRect 函数获取轮廓的最小外接矩形,该函数返回一个包含中心坐标、长宽以及旋转角度的元组,利用这些参数可以绘制出最小外接矩形。

需要使用到的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,则绘制轮廓点;如果是负数,则填充轮廓内部区域。


#最小外接矩形 旋转卡壳法
#读取图像
img = cv.imread('images/feiwu.png')
gary = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
#二值化
ret, binary = cv.threshold(gary, 200, 255, cv.THRESH_BINARY_INV)
#查找轮廓
contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):#最小外接矩形 rect = (center(x,y), (width, height), angle)rect = cv.minAreaRect(contours[i])box = cv.boxPoints(rect).astype(np.int32)cv.drawContours(img, [box], -1, (0, 0, 255), 2,cv.LINE_AA)
#画出外接矩形
for i in range(len(contours)):x, y, w, h = cv.boundingRect(contours[i])cv.rectangle(img, (x, y), (x + w, y + h), (0, 0, 0), 2)
cv.imshow("1", img)
cv.waitKey(0)
cv.destroyAllWindows()

绘制外接矩形和最小外接矩形是有区别的

17.3 最小外接圆

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

进一步推广到任意 n 个不在同一圆上的点,总存在一个唯一的最小覆盖圆包含这 n 个点。

若已经存在平面上互不共线(或共圆)的 n 个点,并确定了它们的最小覆盖圆,那么添加第 n+1 个点,并且要求这个点不在原来的最小覆盖圆内(即在圆外),为了使新的包含 n+1 个点的最小覆盖圆的半径增大,新加入的点必须位于由原 n 个点确定的最小覆盖圆的边界上(即圆周上)。这是因为,如果新点在原最小覆盖圆的内部,显然不会影响最小覆盖圆;如果新点在原最小覆盖圆之外但不在圆周上,那么通过新点和至少两个原有圆上的点可以构造出一个更大的圆,这个圆必然比原最小覆盖圆更大,因此不是包含所有 n+1 个点的最小覆盖圆。所以,按照这一逻辑,当第 n+1 个点在原 n 个点的最小覆盖圆外时,确实这个点会位于包含所有 n+1 个点的新最小覆盖圆的圆周上。

有了这个定理,就可以先取3个点建立一个圆(不共线的三个点即可确定一个圆,如果共线就取距离最远的两个点作为直径建立圆),然后遍历剩下的所有点,对于遍历到的点P来说:

如果该点在圆内,那么最小覆盖圆不变。

如果该点在圆外,根据上述定理,该点一定在想要求得的最小覆盖圆的圆周上,又因为三个点才能确定一个圆,所以需要枚举P点之前的点来找其余的两个点。当找到与P点组成的圆能够将所有点都包含在圆内或圆上,该圆就是这些点的最小外接圆。

在OpenCV中,可以直接使用cv2.minEnclosingCircle()来获取最小外接圆,该函数只需要输入一个参数,就是要绘制最小外接圆的点集的坐标,然后会返回最小外接圆的圆心坐标与半径。通过该函数返回的内容信息即可绘制某点集的最小外接圆。如下图所示:

需要使用的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,则会填充整个圆。

img = cv.imread('images/haimbb.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 100, 255, cv.THRESH_BINARY_INV)
#查找轮廓
contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):#绘制外接圆(x, y), radius = cv.minEnclosingCircle(contours[i])center = (int(x), int(y))radius = int(radius)cv.circle(img, center, radius, (128, 128, 128), 2)#绘制外接矩形rect = cv.minAreaRect(contours[i])box = cv.boxPoints(rect)
cv.imshow("1", img)
cv.imshow("2", binary)
cv.waitKey(0)
cv.destroyAllWindows()

18 直方图均衡化

相关文章:

  • PyTorch 线性回归详解:模型定义、保存、加载与网络结构
  • 动态LOD策略细节层级控制:根据视角距离动态简化远距量子态渲染
  • Vue的模板编译过程
  • 【漏洞复现】CVE-2024-38856(ApacheOfbiz RCE)
  • 毕设 - 数字孪生智慧农场(vue+高德地图)项目分享
  • 记一次 .NET某旅行社酒店管理系统 卡死分析
  • SystemWeaver详解:从入门到精通的深度实战指南
  • 足球 AI 智能体技术解析:从数据采集到比赛预测的全链路架构
  • 【Maven基础】
  • 基于单片机的BMS热管理功能设计
  • 突破网页数据集获取难题:Web Unlocker API 助力 AI 训练与微调数据集全方位解决方案
  • Oracle EBS R12.2 安装 -- Step by Step
  • android studio sdk unavailable和Android 安装时报错:SDK emulator directory is missing
  • 计算机视觉——利用AI幻觉检测图像是否是生成式算生成的图像
  • 2025年最新服务器、中间件安全(面试题)
  • 系统架构设计(二):基于架构的软件设计方法ABSD
  • Java BIO、NIO、AIO、Netty面试题(已整理全套PDF版本)
  • 链表与文件
  • 日志的实现
  • 强化学习笔记(三)——表格型方法(蒙特卡洛、时序差分)
  • 夸大事实拍视频发网络,镇雄两名网红勒索两千元删帖费被拘
  • 教育部召开全国中小学幼儿园安全工作视频会议:加强校园安防建设
  • 成都市政府秘书长王忠诚调任遂宁市委副书记
  • 重点并不在于设计更聪明的机器,而在于开发宇宙技术的多样性
  • 广西柳州23年的蝶变:从“酸雨之城”到“文明之城”
  • 航行警告!南海部分水域进行军事训练,禁止驶入