白色洗衣机图像划痕检测:现有代码失效的解决方案咨询
问题描述
我有一组包含浅、深划痕的白色洗衣机图像数据集,用从StackOverflow拿到的代码检测时输出黑屏,完全识别不出划痕。现有两张测试图:
- 侧边裁剪并旋转的图像:

- 侧边裁剪未旋转的图像:

原代码如下:
import cv2 import numpy as np # load image img = cv2.imread('./detect-01.jpg') # convert to grayscale gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # adaptive threshold thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, -35) # apply morphology kernel = np.ones((3,30),np.uint8) morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) kernel = np.ones((3,35),np.uint8) morph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel) # get hough line segments threshold = 25 minLineLength = 10 maxLineGap = 20 lines = cv2.HoughLinesP(morph, 1, 30*np.pi/360, threshold, minLineLength, maxLineGap) # draw lines linear1 = np.zeros_like(thresh) linear2 = img.copy() for [line] in lines: x1 = line[0] y1 = line[1] x2 = line[2] y2 = line[3] cv2.line(linear1, (x1,y1), (x2,y2), 255, 1) cv2.line(linear2, (x1,y1), (x2,y2), (0,0,255), 1) print('number of lines:',len(lines)) # save resulting masked image cv2.imwrite('scratches_thresh.jpg', thresh) cv2.imwrite('scratches_morph.jpg', morph) cv2.imwrite('scratches_lines1.jpg', linear1) cv2.imwrite('scratches_lines2.jpg', linear2) # display result cv2.imshow("thresh", thresh) cv2.imshow("morph", morph) cv2.imshow("lines1", linear1) cv2.imshow("lines2", linear2) cv2.waitKey(0) cv2.destroyAllWindows()
原代码修改方案
原代码黑屏的核心问题是自适应阈值参数不匹配,加上形态学操作的kernel尺寸过大,直接把划痕特征抹掉了。针对白色洗衣机的划痕,调整如下:
修改后的代码
import cv2 import numpy as np # 加载图像 img = cv2.imread('./detect-01.jpg') if img is None: print("图像加载失败,请检查路径") exit() # 转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 高斯模糊降噪(针对浅划痕) blur = cv2.GaussianBlur(gray, (3,3), 0) # 调整自适应阈值:白色背景下,划痕是深色,用THRESH_BINARY_INV反转阈值 thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 21, 8) # 形态学操作:用小kernel增强划痕,避免过度腐蚀 kernel = np.ones((2,2), np.uint8) morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1) morph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel, iterations=1) # 霍夫线检测调整参数:适配划痕的长度和角度 threshold = 15 minLineLength = 20 maxLineGap = 5 lines = cv2.HoughLinesP(morph, 1, np.pi/180, threshold, minLineLength, maxLineGap) # 绘制检测结果 linear1 = np.zeros_like(thresh) linear2 = img.copy() if lines is not None: print('检测到的线条数:', len(lines)) for [line] in lines: x1, y1, x2, y2 = line cv2.line(linear1, (x1,y1), (x2,y2), 255, 1) cv2.line(linear2, (x1,y1), (x2,y2), (0,0,255), 2) else: print('未检测到线条') # 保存结果 cv2.imwrite('scratches_thresh.jpg', thresh) cv2.imwrite('scratches_morph.jpg', morph) cv2.imwrite('scratches_lines1.jpg', linear1) cv2.imwrite('scratches_lines2.jpg', linear2) # 显示窗口 cv2.imshow("gray", gray) cv2.imshow("thresh", thresh) cv2.imshow("morph", morph) cv2.imshow("lines", linear2) cv2.waitKey(0) cv2.destroyAllWindows()
修改要点说明
- 增加高斯模糊:过滤图像中的微小噪声,避免误检测,同时突出浅划痕的边缘。
- 反转阈值类型:白色背景下划痕是深色,用
THRESH_BINARY_INV让划痕变成白色,背景黑色,符合后续检测逻辑。 - 调整阈值参数:把blockSize改成21,C值改成8,适配洗衣机表面的明暗差异,能更好捕捉浅划痕。
- 缩小形态学kernel:原代码的大尺寸kernel会直接抹平细长划痕,换成(2,2)小kernel,只做轻微的闭开操作修复划痕断点。
- 优化霍夫线参数:降低阈值、调整最小线长和最大间隙,适配划痕的细长特征,避免检测无关短线条。
- 增加图像加载判断:避免因路径错误导致后续崩溃。
替代方案:边缘检测+轮廓提取
如果霍夫线检测效果仍不理想,可尝试用Canny边缘检测结合轮廓提取的方案,更适合不规则划痕:
import cv2 import numpy as np img = cv2.imread('./detect-01.jpg') if img is None: print("图像加载失败") exit() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0) # Canny边缘检测,调整高低阈值适配划痕 edges = cv2.Canny(blur, 30, 150) # 形态学膨胀增强边缘 kernel = np.ones((2,2), np.uint8) edges_dilated = cv2.dilate(edges, kernel, iterations=1) # 提取轮廓 contours, _ = cv2.findContours(edges_dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 过滤掉过小的轮廓,只保留疑似划痕的区域 result = img.copy() min_contour_length = 15 for cnt in contours: if cv2.arcLength(cnt, False) > min_contour_length: cv2.drawContours(result, [cnt], 0, (0,0,255), 1) cv2.imwrite('scratches_contours.jpg', result) cv2.imshow("contours", result) cv2.waitKey(0) cv2.destroyAllWindows()
方案优势
- 对不规则、非直线的划痕适配性更强,比如弯曲的浅划痕。
- 轮廓过滤可以有效排除灰尘、污渍等小干扰。
内容的提问来源于stack exchange,提问作者Lean Learner
相关产品推荐
相关产品推荐

