4. 形态学操作去除噪声并增强缺陷
任务目标
本案例使用OpenCV对含噪声的工业零件表面图像执行形态学处理:先通过开运算去除背景椒盐噪声,再通过闭运算填补缺陷内部细小空洞,最终使划痕、凹坑等缺陷在二值图像中呈现为连续、完整的连通区域,便于后续缺陷检测与特征提取。
环境依赖
需要 Python 3.8+、OpenCV(pip install opencv-python)、NumPy。图像读取使用灰度模式。
关键完整代码
import cv2
import numpy as np
def enhance_defects(image_path, kernel_size=5):
"""
形态学去噪并增强缺陷
流程: 灰度化 -> 自适应阈值二值化 -> 开运算(去椒盐噪声) -> 闭运算(填补缺陷空洞)
返回: 增强后的二值图像(缺陷为白色前景)
"""
# 1. 读取灰度图
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
if img is None:
raise ValueError(f"无法读取图像: {image_path}")
# 2. 自适应阈值二值化(反色: 缺陷区域变为白色)
# 适用于光照不均的工业表面
binary = cv2.adaptiveThreshold(
img, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
blockSize=11, C=2
)
# 3. 定义结构元(矩形核)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_size, kernel_size))
# 4. 开运算: 先腐蚀后膨胀, 去除孤立噪点(椒盐噪声)
opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
# 5. 闭运算: 先膨胀后腐蚀, 填补缺陷内部细小空洞/断裂
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
return closed
def count_defects(binary_img, min_area=30):
"""
统计缺陷连通域数量(验证增强效果)
返回: (缺陷数量, 带轮廓标注的彩色图)
"""
contours, _ = cv2.findContours(
binary_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
valid = [c for c in contours if cv2.contourArea(c) >= min_area]
# 生成标注图(便于可视化验证)
vis = cv2.cvtColor(binary_img, cv2.COLOR_GRAY2BGR)
cv2.drawContours(vis, valid, -1, (0, 0, 255), 2)
return len(valid), vis
if __name__ == "__main__":
# 使用示例(请替换为实际图像路径)
INPUT_PATH = "surface_defect.png"
# 执行形态学增强
enhanced = enhance_defects(INPUT_PATH, kernel_size=5)
# 统计增强前后的缺陷连通域数量
raw_binary = cv2.adaptiveThreshold(
cv2.imread(INPUT_PATH, cv2.IMREAD_GRAYSCALE), 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2
)
before_cnt, _ = count_defects(raw_binary)
after_cnt, vis_result = count_defects(enhanced)
print(f"增强前缺陷连通域数量: {before_cnt}")
print(f"增强后缺陷连通域数量: {after_cnt}")
# 保存结果
cv2.imwrite("enhanced_result.png", enhanced)
cv2.imwrite("defect_contours.png", vis_result)
print("结果已保存: enhanced_result.png, defect_contours.png")
运行与验证
- 准备一张含划痕或凹坑的工业零件灰度图(或使用相机拍摄后转灰度),保存为
surface_defect.png。 - 运行脚本:
python morphology_enhance.py。 - 观察输出:
enhanced_result.png中缺陷区域应为白色连续块,背景噪声明显减少;defect_contours.png中红色轮廓应完整包围缺陷。
通过判定标准
- 增强后图像中孤立噪点(单像素或小团白点)数量显著少于增强前。
- 同一缺陷在增强前若断裂为多个小连通域,增强后应合并为更少的连通域(
after_cnt小于before_cnt),且每个连通域面积大于设定的min_area(30像素)。 - 若原始图像缺陷本身完整且无噪声,则增强前后连通域数量应保持一致(或仅因去噪而减少),不会出现缺陷消失的情况。
常见问题
- 核尺寸选择:
kernel_size=5适用于常见工业图像(分辨率约500×500)。若噪声颗粒较大,可增大到7或9;若缺陷细节细小,则保持3~5,避免过度腐蚀导致缺陷消失。 - 阈值方法:光照均匀时可将
adaptiveThreshold替换为全局cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU),效果更简洁。 - 验证逻辑:
count_defects中的min_area用于过滤残留小噪点,若增强后仍存在大量面积小于该值的连通域,说明开运算核尺寸偏小,需调大。