LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

【C#】OpenCvSharp实现PCB板拍照对比缺陷检测详解

admin
2025年3月1日 22:21 本文热度 333

PCB板缺陷检测是工业视觉检测中的重要应用。本文将详细介绍如何使用OpenCvSharp实现PCB板的缺陷检测,包括缺陷、断路、短路等问题的识别。

环境准备

// NuGet包引用
// Install-Package OpenCvSharp4
// Install-Package OpenCvSharp4.runtime.win
using OpenCvSharp;
using System;

完整代码实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace AppPcb
{
    publicclass PCBDefectDetection
    {

        private Mat templateImage; // 模板图像
        private Mat testImage;     // 待测试图像

        public PCBDefectDetection(string templatePath, string testPath)
        
{
            // 读取图像
            templateImage = Cv2.ImRead(templatePath, ImreadModes.Color);
            testImage = Cv2.ImRead(testPath, ImreadModes.Color);

            // 确保图像加载成功
            if (templateImage.Empty() || testImage.Empty())
            {
                thrownew Exception("图像加载失败!");
            }
        }

        public void DetectDefects()
        
{
            // 1. 图像预处理
            Mat templateGray = PreprocessImage(templateImage);
            Mat testGray = PreprocessImage(testImage);

            // 2. 图像对齐
            Mat alignedTest = AlignImages(templateGray, testGray);

            // 3. 差异检测
            Mat diffMask = DetectDifferences(templateGray, alignedTest);

            // 4. 缺陷分析
            AnalyzeDefects(diffMask);

            // 5. 显示结果
            ShowResults(diffMask);
        }

        private Mat PreprocessImage(Mat input)
        
{
            Mat result = new Mat();

            // 转换为灰度图
            Cv2.CvtColor(input, result, ColorConversionCodes.BGR2GRAY);

            // 高斯模糊去噪
            Cv2.GaussianBlur(result, result, new Size(77), 0);

            // 自适应二值化
            Cv2.AdaptiveThreshold(
                result,
                result,
                255,
                AdaptiveThresholdTypes.GaussianC,
                ThresholdTypes.Binary,
                13,
                2
            );

            return result;
        }

        private Mat AlignImages(Mat template, Mat test)
        
{
            // 特征点检测和匹配
            var orb = ORB.Create();

            // 检测关键点和描述符
            KeyPoint[] templateKeyPoints, testKeyPoints;
            Mat templateDescriptors = new Mat();
            Mat testDescriptors = new Mat();

            orb.DetectAndCompute(
                template,
                null,
                out templateKeyPoints,
                templateDescriptors
            );

            orb.DetectAndCompute(
                test,
                null,
                out testKeyPoints,
                testDescriptors
            );

            // 特征匹配
            var matcher = new BFMatcher(NormTypes.Hamming, crossCheck: true);
            DMatch[] matches = matcher.Match(templateDescriptors, testDescriptors);

            // 提取匹配点对
            Point2f[] templatePoints = matches.Select(m => templateKeyPoints[m.QueryIdx].Pt).ToArray();
            Point2f[] testPoints = matches.Select(m => testKeyPoints[m.TrainIdx].Pt).ToArray();

            // 计算变换矩阵
            Mat homography = Cv2.FindHomography(
                InputArray.Create(testPoints),
                InputArray.Create(templatePoints),
                HomographyMethods.Ransac
            );

            // 应用变换
            Mat alignedTest = new Mat();
            Cv2.WarpPerspective(
                test,
                alignedTest,
                homography,
                template.Size()
            );

            return alignedTest;
        }

        private Mat DetectDifferences(Mat template, Mat test)
        
{
            Mat diff = new Mat();
            Mat diffMask = new Mat();

            // 计算差异
            Cv2.Absdiff(template, test, diff);

            // 二值化差异图
            Cv2.Threshold(
                diff,
                diffMask,
                30,
                255,
                ThresholdTypes.Binary
            );

            // 形态学操作,去除噪点
            Mat kernel = Cv2.GetStructuringElement(
                MorphShapes.Rect,
                new Size(33)
            );

            Cv2.MorphologyEx(
                diffMask,
                diffMask,
                MorphTypes.Open,
                kernel,
                iterations: 2
            );

            return diffMask;
        }

        private void AnalyzeDefects(Mat diffMask)
        
{
            // 查找轮廓
            Point[][] contours;
            HierarchyIndex[] hierarchy;

            Cv2.FindContours(
                diffMask,
                out contours,
                out hierarchy,
                RetrievalModes.External,
                ContourApproximationModes.ApproxSimple
            );

            // 分析每个缺陷区域
            foreach (var contour in contours)
            {
                // 计算缺陷面积
                double area = Cv2.ContourArea(contour);

                // 获取缺陷边界框
                Rect boundingRect = Cv2.BoundingRect(contour);

                // 判断缺陷类型
                if (area >= 20// 面积阈值可调整
                {
                    Console.WriteLine($"发现缺陷:");
                    Console.WriteLine($"位置: X={boundingRect.X}, Y={boundingRect.Y}");
                    Console.WriteLine($"大小: {area:F2}平方像素");

                    // 在原图上标记缺陷
                    Cv2.Rectangle(
                        testImage,
                        boundingRect,
                        Scalar.Red,
                        2
                    );

                    Cv2.PutText(
                        testImage,
                        $"Defect: {area:F0}px",
                        new Point(boundingRect.X, boundingRect.Y - 5),
                        HersheyFonts.HersheySimplex,
                        0.5,
                        Scalar.Red,
                        1
                    );
                }
            }
        }

        private void ShowResults(Mat diffMask)
        
{
            // 显示结果
            using (new Window("Template", templateImage))
            using (new Window("Test Image", testImage))
            using (new Window("Differences", diffMask))
            {
                Cv2.WaitKey();
            }
        }
    }

}

代码详解

图像预处理

高斯模糊(Gaussian Blur)

Cv2.GaussianBlur(result, result, new Size(77), 0);
  • result
    : 输入图像,经过模糊处理的输出图像(可覆盖)。
  • new Size(7, 7)
    : 高斯核的大小,必须是正奇数(例如:3, 5, 7 等)。越大则模糊效果越明显。
  • 0
    : 标准差 σ。在 X 和 Y 方向上的标准差。如果设为0,函数会根据核大小自动计算。

自适应二值化(Adaptive Thresholding)

Cv2.AdaptiveThreshold(
    result,
    result,
    255,
    AdaptiveThresholdTypes.GaussianC,
    ThresholdTypes.Binary,
    13,
    2
);
  • result
    : 输入图像,经过二值化处理的输出图像(可覆盖)。
  • 255
    : 阈值的最大值。当像素值超过该值时,将其赋为最大值。
  • AdaptiveThresholdTypes.GaussianC
    : 自适应阈值的计算方法,这里使用“Gaussian”方法来计算局部阈值。
  • ThresholdTypes.Binary
    : 阈值类型。在这里使用的是简单的二值化(黑和白)。
  • 13
    : 领域大小,即考虑的邻域像素的尺寸(必须为奇数)。
  • 2
    : 从每个计算得到的阈值中减去的常量C,用于调整二值化效果。

图像对齐

使用ORB特征检测和匹配实现图像对齐:

  1. 检测特征点和描述符
  2. 特征点匹配
  3. 计算单应性矩阵
  4. 透视变换实现图像对齐

差异检测

二值化差异图(Thresholding)

Cv2.Threshold(
    diff,
    diffMask,
    30,
    255,
    ThresholdTypes.Binary
);
  • diff
    : 输入图像,通常是差异图(例如两张图像之间的差异)。
  • diffMask
    : 输出图像,即二值化处理后的结果。
  • 30
    : 阈值。像素值高于此值将被赋值为最大值(255),低于此值将被赋值为0。
  • 255
    : 阈值的最大值。当像素值超过30时,输出结果将设为255。
  • ThresholdTypes.Binary
    : 阈值类型。在这里使用的是简单的二值化,结果只有两种值(0和255)。

形态学操作(Morphological Operations)

Mat kernel = Cv2.GetStructuringElement(
    MorphShapes.Rect,
    new Size(33)
);
  • Cv2.GetStructuringElement
    : 用于创建结构元素,用于形态学处理。
  • MorphShapes.Rect
    : 指定结构元素的形状为矩形(也可使用其他形状,如椭圆或十字形)。
  • new Size(3, 3)
    : 结构元素的大小,这里为3x3像素。
Cv2.MorphologyEx(
    diffMask,
    diffMask,
    MorphTypes.Open,
    kernel,
    iterations: 2
);
  • diffMask
    : 输入图像,通常是经过二值化处理的图像。
  • diffMask
    : 输出图像,表示形态学处理后的结果(可覆盖)。
  • MorphTypes.Open
    : 形态学运算类型为开运算(去除小物体的噪点)。
  • kernel
    : 用于形态学操作的结构元素。
  • iterations: 2
    : 操作的迭代次数。设置为2意味着将在图像上执行两次开运算。

缺陷分析

分析检测到的缺陷:

  1. 轮廓检测
  2. 计算缺陷面积
  3. 获取缺陷位置
  4. 在原图上标记缺陷位置

总结

本文详细介绍了使用OpenCvSharp实现PCB板缺陷检测的完整流程。该方法具有以下特点:

  • 自动化程度高
  • 检测精度可靠
  • 代码可扩展性强
  • 实现相对简单

通过调整参数和优化算法,可以根据具体应用场景提高检测效果。


阅读原文:原文链接


该文章在 2025/3/3 16:00:11 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved