自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C# 使用OpenCvSharp實(shí)現(xiàn)模板差異檢測(cè)

開(kāi)發(fā) 前端
本文詳細(xì)介紹了使用OpenCvSharp實(shí)現(xiàn)模板差異檢測(cè)的完整方案。通過(guò)合適的圖像處理和計(jì)算機(jī)視覺(jué)技術(shù),可以有效地檢測(cè)出兩張圖像之間的差異。

本文將詳細(xì)介紹如何使用OpenCvSharp來(lái)實(shí)現(xiàn)模板圖像與待檢測(cè)圖像之間的差異檢測(cè)。這種技術(shù)常用于產(chǎn)品質(zhì)量檢測(cè)、PCB板檢測(cè)等場(chǎng)景。上面的示意圖展示了一個(gè)簡(jiǎn)單的例子,左邊是完整的模板圖像,右邊是缺少部分元件的待檢測(cè)圖像。

環(huán)境準(zhǔn)備

// 需要安裝的NuGet包
// Install-Package OpenCvSharp4
// Install-Package OpenCvSharp4.runtime.win

using OpenCvSharp;
using System;
using System.Collections.Generic;

完整代碼實(shí)現(xiàn)

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

namespace OpenCv082902
{
    public class TemplateDifferenceDetector
    {
        /// <summary>  
        /// 檢測(cè)結(jié)果類  
        /// </summary>  
        public class DetectionResult
        {
            public Point Location { get; set; }
            public double Difference { get; set; }
            public Rect Region { get; set; }
        }

        /// <summary>  
        /// PCB圖像差異檢測(cè)的配置參數(shù)  
        /// </summary>  
        public class DetectionConfig
        {
            public double Threshold { get; set; } = 0.5;          // 差異閾值  
            public double MinArea { get; set; } = 10;            // 最小檢測(cè)面積  
            public int BlurSize { get; set; } = 3;               // 高斯模糊核大小  
            public int MorphSize { get; set; } = 3;              // 形態(tài)學(xué)操作核大小  
            public bool EnableHistEqualization { get; set; } = true;  // 是否啟用直方圖均衡化  
            public bool EnableNoiseReduction { get; set; } = true;    // 是否啟用降噪  
        }

        /// <summary>  
        /// 執(zhí)行差異檢測(cè)  
        /// </summary>  
        /// <param name="templatePath">模板圖像路徑</param>  
        /// <param name="targetPath">待檢測(cè)圖像路徑</param>  
        /// <param name="config">檢測(cè)配置參數(shù)</param>  
        /// <returns>檢測(cè)結(jié)果列表</returns>  
        public static List<DetectionResult> DetectDifferences(
            string templatePath,
            string targetPath,
            DetectionConfig config = null)
        {
            config ??= new DetectionConfig();

            // 讀取圖像  
            using var template = Cv2.ImRead(templatePath);
            using var target = Cv2.ImRead(targetPath);

            // 確保圖像成功加載  
            if (template.Empty() || target.Empty())
            {
                throw new Exception("無(wú)法加載圖像");
            }

            // 預(yù)處理圖像  
            using var processedTemplate = PreprocessImage(template, config);
            using var processedTarget = PreprocessImage(target, config);

            // 計(jì)算差異圖  
            using var diff = new Mat();
            Cv2.Absdiff(processedTemplate, processedTarget, diff);

            // 應(yīng)用閾值處理  
            using var thresholdMat = new Mat();
            Cv2.Threshold(diff, thresholdMat, config.Threshold * 255, 255, ThresholdTypes.Binary);

            // 應(yīng)用形態(tài)學(xué)操作來(lái)減少噪聲  
            if (config.EnableNoiseReduction)
            {
                var kernel = Cv2.GetStructuringElement(
                    MorphShapes.Rect,
                    new Size(config.MorphSize, config.MorphSize)
                );

                Cv2.MorphologyEx(
                    thresholdMat,
                    thresholdMat,
                    MorphTypes.Open,
                    kernel
                );
            }

            // 尋找輪廓  
            Cv2.FindContours(
                thresholdMat,
                out Point[][] contours,
                out HierarchyIndex[] hierarchy,
                RetrievalModes.External,
                ContourApproximationModes.ApproxSimple
            );

            // 分析差異區(qū)域  
            var results = new List<DetectionResult>();
            foreach (var contour in contours)
            {
                // 計(jì)算輪廓面積,過(guò)濾掉太小的區(qū)域  
                double area = Cv2.ContourArea(contour);
                if (area < config.MinArea)
                    continue;

                // 獲取邊界矩形  
                var boundingRect = Cv2.BoundingRect(contour);

                // 計(jì)算該區(qū)域的平均差異值  
                using var roi = new Mat(diff, boundingRect);
                Scalar meanDiff = Cv2.Mean(roi);

                results.Add(new DetectionResult
                {
                    Location = new Point(boundingRect.X, boundingRect.Y),
                    Difference = meanDiff.Val0 / 255.0, // 歸一化差異值  
                    Region = boundingRect
                });
            }

            return results;
        }

        /// <summary>  
        /// 圖像預(yù)處理  
        /// </summary>  
        private static Mat PreprocessImage(Mat input, DetectionConfig config)
        {
            // 轉(zhuǎn)換為灰度圖  
            var processed = input.CvtColor(ColorConversionCodes.BGR2GRAY);

            // 應(yīng)用高斯模糊減少噪聲  
            if (config.EnableNoiseReduction)
            {
                Cv2.GaussianBlur(
                    processed,
                    processed,
                    new Size(config.BlurSize, config.BlurSize),
                    0
                );
            }

            // 直方圖均衡化增強(qiáng)對(duì)比度  
            if (config.EnableHistEqualization)
            {
                Cv2.EqualizeHist(processed, processed);
            }

            return processed;
        }

        /// <summary>  
        /// 可視化檢測(cè)結(jié)果  
        /// </summary>  
        public static void VisualizeResults(
            string templatePath,
            string targetPath,
            string outputPath,
            List<DetectionResult> results)
        {
            using var target = Cv2.ImRead(targetPath);
            using var output = target.Clone();

            // 在圖像上標(biāo)注差異區(qū)域  
            foreach (var result in results)
            {
                // 繪制矩形框  
                Cv2.Rectangle(
                    output,
                    result.Region,
                    new Scalar(0, 0, 255), // 紅色  
                    2
                );

                // 添加差異值標(biāo)注  
                string text = $"Diff: {result.Difference:F2}";
                Cv2.PutText(
                    output,
                    text,
                    new Point(result.Location.X, result.Location.Y - 5),
                    HersheyFonts.HersheySimplex,
                    0.5,
                    new Scalar(0, 0, 255),
                    1
                );
            }

            // 創(chuàng)建對(duì)比圖  
            using var comparison = new Mat();
            using var targetResized = target.Resize(new Size(target.Width / 2, target.Height));
            using var outputResized = output.Resize(new Size(output.Width / 2, output.Height));
            Cv2.HConcat(new[] { targetResized, outputResized }, comparison);

            // 添加標(biāo)題  
            Cv2.PutText(
                comparison,
                "Original",
                new Point(target.Width / 4 - 40, 30),
                HersheyFonts.HersheySimplex,
                1,
                new Scalar(0, 255, 0),
                2
            );

            Cv2.PutText(
                comparison,
                "Detected Differences",
                new Point(target.Width * 3 / 4 - 100, 30),
                HersheyFonts.HersheySimplex,
                1,
                new Scalar(0, 255, 0),
                2
            );

            // 保存結(jié)果圖像  
            comparison.SaveImage(outputPath);

        }

        /// <summary>  
        /// 使用示例  
        /// </summary>  
        public static void Example()
        {
            var config = new DetectionConfig
            {
                Threshold = 0.3,             // 降低閾值使檢測(cè)更敏感  
                MinArea = 5,                 // 降低最小面積閾值  
                BlurSize = 3,                // 適當(dāng)?shù)哪:舜笮? 
                MorphSize = 2,               // 較小的形態(tài)學(xué)操作核心  
                EnableHistEqualization = true,
                EnableNoiseReduction = true
            };

            var results = DetectDifferences(
                "template.jpg",
                "target.jpg",
                config
            );

            VisualizeResults(
                "template.jpg",
                "target.jpg",
                "output.jpg",
                results
            );

            Console.WriteLine($"Found {results.Count} differences");
            foreach (var result in results)
            {
                Console.WriteLine($"Difference at ({result.Location.X}, {result.Location.Y}) " +
                                $"with difference value: {result.Difference:F2}");
            }
        }
    }
}

使用示例

using OpenCv082902;
using OpenCvSharp;
using System;
using System.Collections.Generic;

class Program
{

    static void Main(string[] args)
    {
        // 使用自定義配置  
        var config = new TemplateDifferenceDetector.DetectionConfig
        {
            Threshold = 0.3,
            MinArea = 5,
            BlurSize = 3,
            MorphSize = 2,
            EnableHistEqualization = true,
            EnableNoiseReduction = true
        };

        var results = TemplateDifferenceDetector.DetectDifferences("pcb_layout.png", "pcb_layout1.jpg", config);

        // 可視化結(jié)果  
        TemplateDifferenceDetector.VisualizeResults("pcb_layout.png", "pcb_layout1.jpg", "output.jpg", results);

        Console.ReadKey();
    }

}

圖片圖片

檢測(cè)失敗的可能原因:

  1. 圖像對(duì)齊問(wèn)題 - 兩張圖像可能有微小的偏移或旋轉(zhuǎn)
  2. 閾值設(shè)置過(guò)高 - 導(dǎo)致小的差異被忽略
  3. 最小面積設(shè)置過(guò)大 - 導(dǎo)致小的差異區(qū)域被過(guò)濾
  4. 圖像質(zhì)量問(wèn)題 - 如噪聲、模糊等影響檢測(cè)效果

總結(jié)

本文詳細(xì)介紹了使用OpenCvSharp實(shí)現(xiàn)模板差異檢測(cè)的完整方案。通過(guò)合適的圖像處理和計(jì)算機(jī)視覺(jué)技術(shù),可以有效地檢測(cè)出兩張圖像之間的差異。代碼實(shí)現(xiàn)了基本功能,并提供了良好的擴(kuò)展性。在實(shí)際應(yīng)用中,可以根據(jù)具體需求調(diào)整參數(shù)和添加其他功能。

責(zé)任編輯:武曉燕 來(lái)源: 技術(shù)老小子
相關(guān)推薦

2009-08-14 15:02:24

Service模板C#創(chuàng)建

2009-03-12 13:49:30

DataTemplatWPFC#

2009-08-21 10:28:21

C#異步方法C#同步方法

2025-04-03 07:08:05

2009-08-31 15:55:17

C#實(shí)現(xiàn)Strateg

2009-08-19 17:00:07

C#實(shí)現(xiàn)PrintPa

2009-08-20 14:22:17

C#實(shí)現(xiàn) Contro

2009-08-25 17:55:52

C#實(shí)現(xiàn)Strateg

2009-08-26 09:54:45

C#打印預(yù)覽C#打印

2009-09-01 18:29:10

C#繼承C#多態(tài)

2009-08-19 14:26:58

C# JavaScri

2009-08-18 17:29:02

C#使用指針

2009-08-20 13:23:28

C#使用Crystal

2009-09-01 09:16:57

C#使用SharpZi

2009-08-31 16:12:02

C#使用Singlet

2009-08-25 16:49:44

C#使用if語(yǔ)句

2009-08-14 15:23:10

C#使用ErrorPr

2009-07-15 18:25:52

ASP.NET控件數(shù)組

2009-03-27 10:10:13

c#遠(yuǎn)程啟動(dòng)遠(yuǎn)程管理

2009-06-18 13:06:59

C#位運(yùn)算權(quán)限管理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)