OpenCV 从入门到精通教程-第5章 形态学操作

第5章 形态学操作

形态学操作基于形状,通常作用于二值图像,也可用于灰度图。

5.1 腐蚀与膨胀

  • 腐蚀(Erosion):减小前景物体,消除细小噪声。
  • 膨胀(Dilation):扩大前景区域,填充空洞。

python

kernel = np.ones((5,5), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
dilation = cv2.dilate(img, kernel, iterations=1)

5.2 开运算、闭运算、形态学梯度、顶帽、黑帽

  • 开运算 = 先腐蚀再膨胀 → 消除小物体、分离连接区域。
  • 闭运算 = 先膨胀再腐蚀 → 填充前景物体内部的小孔、连接邻近区域。
  • 形态学梯度 = 膨胀图 – 腐蚀图 → 提取边缘。
  • 顶帽(Top Hat) = 原图 – 开运算 → 提取比周围亮的区域。
  • 黑帽(Black Hat) = 闭运算 – 原图 → 提取比周围暗的区域。

python

opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

5.3 应用实例

提取物体边界 = 膨胀图 – 腐蚀图,或者使用形态学梯度。
去除小噪声:先开运算去掉白点,如果噪声是黑点则可使用闭运算。


第6章 图像阈值与分割

6.1 全局阈值与自适应阈值

阈值处理是将灰度图转换为二值图的基本操作。

python

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 全局固定阈值 (阈值, 最大值, 类型)
_, thresh_binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
_, thresh_inv = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)

自适应阈值:根据像素邻域局部计算阈值,适合光照不均的图像。

python

adaptive = cv2.adaptiveThreshold(gray, 255, 
                cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                cv2.THRESH_BINARY, 11, 2)   # 块大小11,常数C=2

6.2 Otsu 二值化

Otsu 方法自动计算最佳阈值,适用于双峰直方图图像。

python

_, otsu = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

不必手动指定阈值,算法自动寻找最小化类内方差的阈值。

6.3 分水岭算法简介

分水岭算法是一种基于拓扑的图像分割方法,可分离相互接触的物体。简要步骤:

  1. 通过距离变换获取“种子”区域(前景标记)。
  2. 生成未知区域,使用 cv2.watershed

python

# 简单示例(需要预处理)
ret, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown==255] = 0
markers = cv2.watershed(img, markers)
img[markers == -1] = [0,0,255]   # 边界标注为红色

分水岭算法对噪声较敏感,通常需要预处理降噪。


第7章 轮廓分析

轮廓是图像中连续点的集合,常用于形状分析、目标检测。

7.1 查找与绘制轮廓

python

# 使用二值图像查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制所有轮廓(-1 表示所有轮廓, (0,255,0) 为绿色, 线宽2)
cv2.drawContours(img, contours, -1, (0,255,0), 2)

7.2 轮廓特征

对于每个轮廓,可以计算诸多特征:

python

cnt = contours[0]
area = cv2.contourArea(cnt)               # 面积
perimeter = cv2.arcLength(cnt, True)      # 周长(True表示闭合)
x, y, w, h = cv2.boundingRect(cnt)        # 直边界矩形
rect = cv2.minAreaRect(cnt)               # 最小外接旋转矩形
box = cv2.boxPoints(rect)                 # 获取四个顶点坐标(float)
box = np.int0(box)                        # 取整
(x_c,y_c), radius = cv2.minEnclosingCircle(cnt)  # 最小外接圆

获取矩(moments)可计算质心:

python

M = cv2.moments(cnt)
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])

7.3 轮廓近似与凸包

轮廓近似(Douglas-Peucker 算法):

python

epsilon = 0.01 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)

可用于形状识别,例如一个四边形 approx 长度为4。

凸包(Convex Hull):

python

hull = cv2.convexHull(cnt)

用于凸缺陷检测。

7.4 形状匹配

使用 cv2.matchShapes 基于 Hu 矩比较形状相似度,返回值越小越相似。

python

ret = cv2.matchShapes(cnt1, cnt2, cv2.CONTOURS_MATCH_I2, 0.0)

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注