使用Python + OpenCV构建一个图形化金属划痕检测工具

在工业质检、金属材料检测中,表面划痕的识别是常见也是重要的环节。今天这篇文章,我们将用 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 技术。代码结构清晰、逻辑直观,是一个很好的图像处理项目实战案例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值