Files
琉璃月光 df7c0730f5 bushu
2025-10-21 14:11:52 +08:00

101 lines
4.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import cv2
import numpy as np
# 读取图像(以灰度模式加载)
# 作用:将 '1.jpg' 图像读入内存,转换为单通道灰度图,便于后续图像处理
# 注意如果路径错误或文件不存在image 将为 None导致后续报错
image = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE)
# 检查图像是否成功加载
if image is None:
raise FileNotFoundError("无法读取图像,请检查文件路径是否正确:'1.jpg'")
# 均值滤波滤波核大小为7x7
# 作用:对图像进行平滑处理,去除高频噪声(如随机噪点)
# 原理用每个像素周围7x7邻域的平均值替换该像素值使图像更“柔和”
blurred = cv2.blur(image, (7, 7))
# 使用局部自适应阈值进行图像分割
# 作用:将图像二值化,突出比局部背景更暗的区域(如划痕、凹坑等缺陷)
# 参数说明:
# - cv2.ADAPTIVE_THRESH_MEAN_C阈值基于局部邻域的平均值
# - 11邻域大小奇数决定局部范围
# - 2从均值中减去的常数用于微调灵敏度
# - cv2.THRESH_BINARY_INV反转结果缺陷区域为白色255背景为黑色0
thresholded = cv2.adaptiveThreshold(
blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 11, 2
)
# 查找图像中的轮廓
# 作用:检测二值图像中所有连通的白色区域(即潜在缺陷)
# 返回值:
# - contours: 所有轮廓的坐标点列表
# - _ : 轮廓的层级关系(此处不需要)
# 方法选择:
# - cv2.RETR_LIST提取所有轮廓不建立层级
# - cv2.CHAIN_APPROX_SIMPLE压缩水平/垂直/对角线方向的轮廓点,节省内存
contours, _ = cv2.findContours(thresholded, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# 创建一个彩色图像用于结果显示
# 作用将原始灰度图转换为BGR三通道图像以便用不同颜色绘制检测结果
output_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
# 对每个检测到的轮廓进行面积筛选
# 作用:过滤掉太小(可能是噪声)或太大(可能是背景干扰)的区域
# 设置面积阈值范围250 ~ 1000 像素
min_area, max_area = 250, 1000
for contour in contours:
area = cv2.contourArea(contour) # 计算轮廓包围的面积
if min_area < area < max_area:
# 绘制符合条件的轮廓
# 颜色:绿色 (0, 255, 0)线宽2
cv2.drawContours(output_image, [contour], -1, (0, 255, 0), 2)
# 形态学膨胀操作
# 作用:扩大二值图像中的白色区域,连接邻近的断裂缺陷(如断开的划痕)
# 结构元素椭圆形模拟圆形大小为7x7
# iterations=1执行一次膨胀
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
dilated = cv2.dilate(thresholded, kernel, iterations=1)
# 骨架化处理(细化为单像素宽的中心线)
# 作用:将膨胀后的缺陷区域“细线化”,便于分析划痕的路径和长度
# 注意OpenCV 无内置骨架化函数这里使用经典的Zhang-Suen细化算法简化版
def thinning(img):
skel = np.zeros(img.shape, np.uint8) # 存储骨架结果
size = np.size(img)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) # 3x3十字结构元
done = False
while not done:
# 重复执行:腐蚀 → 膨胀 → 差分 → 累加到骨架
eroded = cv2.erode(img, element) # 腐蚀:缩小区域
temp = cv2.dilate(eroded, element) # 膨胀回来
temp = cv2.subtract(img, temp) # 得到最外层轮廓(即“剥皮”一层)
skel = cv2.bitwise_or(skel, temp) # 累加到骨架图像
img = eroded.copy() # 更新图像为腐蚀后的结果
# 当图像完全变黑(无非零像素)时停止
zeros = size - cv2.countNonZero(img)
if zeros == size:
done = True
return skel
# 执行骨架化
skeleton = thinning(dilated)
# 显示所有中间结果和最终检测图
# 作用:可视化每一步的处理效果,便于调试和分析
cv2.imshow("Original Image", image) # 原始灰度图
cv2.imshow("Thresholded Image", thresholded) # 自适应阈值分割结果
cv2.imshow("Dilated Image", dilated) # 膨胀后结果
cv2.imshow("Skeletonized Image", skeleton) # 骨架化结果(细线)
cv2.imshow("Detected Regions", output_image) # 最终检测结果(绿色轮廓)
# 等待按键后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()