2. 织物瑕疵检测中的纹理分析
任务目标
本案例使用灰度共生矩阵(GLCM)提取织物图像的纹理特征,通过对比无瑕疵区域与待检测区域的纹理差异,定位瑕疵区域并在原图上标记。输入为单张织物灰度图像,输出为标记了瑕疵边界框的结果图像及瑕疵数量。
实现方案
将图像划分为固定大小的重叠窗口,对每个窗口计算GLCM的对比度(contrast)和能量(energy)作为纹理特征。以图像中心区域(假设无瑕疵)的特征均值为基准,当窗口特征与基准的偏差超过阈值时判定为瑕疵窗口。相邻瑕疵窗口合并为连通域,绘制边界框。
依赖环境
- Python 3.8+
- OpenCV(
pip install opencv-python) - NumPy(
pip install numpy) - scikit-image(
pip install scikit-image)
关键完整代码
import cv2
import numpy as np
from skimage.feature import graycomatrix, graycoprops
def compute_glcm_features(gray_patch):
"""计算单窗口的GLCM对比度和能量"""
glcm = graycomatrix(gray_patch, distances=[1], angles=[0, np.pi/4, np.pi/2, 3*np.pi/4],
levels=256, symmetric=True, normed=True)
contrast = np.mean([graycoprops(glcm, 'contrast')[0, 0] for _ in range(4)])
energy = np.mean([graycoprops(glcm, 'energy')[0, 0] for _ in range(4)])
return contrast, energy
def detect_defects(image_path, win_size=32, step=16, threshold_mult=2.0):
# 读取并转为灰度
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h, w = gray.shape
# 以图像中心区域作为无瑕疵基准
ch, cw = h // 2, w // 2
ref_size = min(win_size * 3, ch, cw)
ref_patch = gray[ch - ref_size//2:ch + ref_size//2, cw - ref_size//2:cw + ref_size//2]
ref_contrast, ref_energy = compute_glcm_features(ref_patch)
# 滑窗检测
defect_mask = np.zeros((h, w), dtype=np.uint8)
for y in range(0, h - win_size + 1, step):
for x in range(0, w - win_size + 1, step):
patch = gray[y:y + win_size, x:x + win_size]
contrast, energy = compute_glcm_features(patch)
# 偏差判定:对比度偏离或能量偏离均视为瑕疵
if (abs(contrast - ref_contrast) > threshold_mult * ref_contrast or
abs(energy - ref_energy) > threshold_mult * ref_energy):
defect_mask[y:y + win_size, x:x + win_size] = 255
# 形态学闭运算连接邻近瑕疵窗口
kernel = np.ones((win_size, win_size), np.uint8)
defect_mask = cv2.morphologyEx(defect_mask, cv2.MORPH_CLOSE, kernel)
# 找连通域并画框
contours, _ = cv2.findContours(defect_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
result = img.copy()
for cnt in contours:
x, y, bw, bh = cv2.boundingRect(cnt)
cv2.rectangle(result, (x, y), (x + bw, y + bh), (0, 0, 255), 2)
return result, len(contours)
if __name__ == "__main__":
# 使用示例:替换为实际图像路径
out_img, num_defects = detect_defects("fabric.jpg")
print(f"检测到瑕疵数量: {num_defects}")
cv2.imwrite("result.jpg", out_img)
运行方式
- 将待检测织物图像命名为
fabric.jpg放在脚本同目录; - 运行
python fabric_defect_detection.py; - 查看输出文件
result.jpg和控制台打印的瑕疵数量。
验证方法
选择一张包含明显瑕疵(如破洞、污渍、织纹异常)的织物图像进行测试。通过标准:
- 输出图像中瑕疵区域被红色矩形框标记,且框的位置与瑕疵实际位置基本吻合;
- 无瑕疵的均匀织物图像检测到的瑕疵数量为0或极少(仅边缘噪声);
- 调整
threshold_mult参数(建议范围1.5~3.0)可控制检测灵敏度,数值越小越敏感。
常见问题
- 检测结果噪声多:增大
threshold_mult或增大win_size降低分辨率; - 漏检小瑕疵:减小
step至8或4,但会增加计算时间; - 基准区域本身有瑕疵:可改为手动指定无瑕疵区域坐标,或使用整幅图像的纹理统计中位数作为基准。