在工业质检、金属材料检测中,表面划痕的识别是常见也是重要的环节。今天这篇文章,我们将用 Python 实现一个带图形界面的金属划痕检测工具,支持单张图像检测、批量处理、检测结果展示以及划痕数量统计导出为 CSV 文件。
📌 本项目基于 OpenCV 图像处理和 Tkinter 图形界面开发,适合初中级图像处理开发者参考学习。
功能预览
加载图像并检测划痕
自动统计划痕数量
保存检测结果图像
批量检测文件夹中的所有图像
导出划痕统计报告(CSV)
支持每张图像显示延时(可调)
界面如下👇:
划痕检测算法原理
我们采用一种简单直观的图像增强 + 轮廓提取策略:
中值滤波去除小颗粒噪声;
图像差分提取细节(划痕部分);
灰度化+阈值分割将划痕区域突出;
轮廓提取并根据面积筛选有效区域;
绘制红框标注划痕区域。
def detect_scratch(img):
"""检测划痕,返回处理后图像和划痕数量"""
minThres = 6
# 中值滤波
img1 = cv2.medianBlur(img, 15)
# 图像差分
diff = cv2.absdiff(img, img1)
gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
# 二值化
_, thres = cv2.threshold(gray, minThres, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, hierarchy = cv2.findContours(thres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
result = img.copy()
for i in range(0, len(contours)):
length = cv2.arcLength(contours[i], True)
# 通过轮廓长度筛选
if length > 20:
cv2.drawContours(img1, contours[i], -1, (0, 0, 255), 2)
count = 0
for cnt in contours:
area = cv2.contourArea(cnt)
if 20 < area < 5000: # 可调范围
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(result, (x, y), (x+w, y+h), (0, 0, 255), 2)
count += 1
return result, count
图形界面功能实现(Tkinter)
整个程序界面非常简洁,包含以下按钮和控件:
加载图像:选择图片,自动检测划痕;
保存结果:保存当前结果图;
批量处理文件夹:自动处理整个文件夹下所有图片;
延时滑块:控制每张图像显示时间,便于人工确认;
class ScratchDetectorApp:
def __init__(self, root):
self.root = root
self.root.title("金属划痕检测工具")
self.root.geometry("900x650")
self.root.configure(bg="#2c3e50")
self.image_panel = tk.Label(root)
self.image_panel.pack(pady=10)
self.label_result = tk.Label(root, text="请加载图像...", fg="white", bg="#2c3e50", font=("微软雅黑", 14))
self.label_result.pack(pady=10)
btn_frame = tk.Frame(root, bg="#2c3e50")
btn_frame.pack()
tk.Button(btn_frame, text="加载图像", command=self.load_image, width=15).pack(side=tk.LEFT, padx=10)
tk.Button(btn_frame, text="保存结果", command=self.save_image, width=15).pack(side=tk.LEFT, padx=10)
tk.Button(btn_frame, text="批量处理文件夹", command=self.batch_process, width=20).pack(side=tk.LEFT, padx=10)
# 延迟滑块
self.delay_var = tk.IntVar(value=1)
tk.Scale(btn_frame, from_=0, to=5, orient=tk.HORIZONTAL, label="每图延迟(秒)", variable=self.delay_var).pack(side=tk.LEFT, padx=10)
self.original_img = None
self.result_img = None
批量检测与报告导出
批量处理不仅能自动检测所有图片,还支持保存检测图像、导出统计表
批量处理:
def batch_process(self):
folder = filedialog.askdirectory(title="选择图像文件夹")
if not folder:
return
save_dir = os.path.join(folder, "results")
os.makedirs(save_dir, exist_ok=True)
supported_ext = [".jpg", ".jpeg", ".png", ".bmp"]
files = [f for f in os.listdir(folder) if os.path.splitext(f)[1].lower() in supported_ext]
result_list = []
total_count = 0
skipped = []
for idx, filename in enumerate(files):
filepath = os.path.join(folder, filename)
img = cv2.imread(filepath)
if img is None:
skipped.append(filename)
continue
result_img, count = detect_scratch(img)
total_count += count
result_list.append((filename, count))
out_path = os.path.join(save_dir, f"{os.path.splitext(filename)[0]}_result.jpg")
cv2.imwrite(out_path, result_img)
self.label_result.config(text=f"处理 {idx+1}/{len(files)} 张图像:{filename},划痕:{count}")
self.show_image(result_img)
self.root.update_idletasks()
time.sleep(self.delay_var.get())
生成结果文件夹
save_dir = os.path.join(folder, “results”)
os.makedirs(save_dir, exist_ok=True)
生成CSV报告
report_path = os.path.join(save_dir, "detection_report.csv")
with open(report_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(["文件名", "划痕数量"])
for filename, count in result_list:
writer.writerow([filename, count])
环境依赖
请确保已安装以下 Python 库:
pip install opencv-python Pillow numpy
效果展示
加载图像(图是别人的博客里找到的)后,自动框选划痕区域,并显示总数👇
总结
本项目是一个适用于初学者和工业质检的划痕检测工具,结合了图像处理与桌面 GUI 技术。代码结构清晰、逻辑直观,是一个很好的图像处理项目实战案例。