第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 分水岭算法简介
分水岭算法是一种基于拓扑的图像分割方法,可分离相互接触的物体。简要步骤:
- 通过距离变换获取“种子”区域(前景标记)。
- 生成未知区域,使用
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)