切換語言為:簡體
C# 使用OpenCvSharp在WinForms中實現輪廓匹配

C# 使用OpenCvSharp在WinForms中實現輪廓匹配

  • 爱糖宝
  • 2024-10-29
  • 2054
  • 0
  • 0

在本文中,我們將探討如何使用OpenCvSharp庫在C#的WinForms應用程式中實現輪廓匹配功能。輪廓匹配是計算機視覺中的一項重要技術,可用於識別和定點陣圖像中的特定形狀或物體。

應用程式概述

我們的WinForms應用程式允許使用者選擇兩張圖片:一張源影象和一張模板影象。程式會在源影象中查詢與模板影象最相似的輪廓,並在結果影象中高亮顯示匹配的輪廓。

主要功能包括:

  1. 選擇源影象和模板影象

  2. 顯示選擇的影象

  3. 執行輪廓匹配

  4. 顯示匹配結果和相似度

實現細節

C# 使用OpenCvSharp在WinForms中實現輪廓匹配

1. 影象選擇

我們使用OpenFileDialog來允許使用者選擇源影象和模板影象。選擇的影象路徑會顯示在文字框中,並在PictureBox控制元件中預覽影象。

private void btnSelectSource_Click(object sender, EventArgs e)
{
    using(OpenFileDialog openFileDialog = new OpenFileDialog())
    {
        openFileDialog.Filter = "Image files (*.png;*.jpg;*.jpeg)|*.png;*.jpg;*.jpeg|All files (*.*)|*.*";
        if(openFileDialog.ShowDialog() == DialogResult.OK)
        {
            sourcePath = openFileDialog.FileName;
            txtSourcePath.Text = sourcePath;
            pictureBoxSource.Image = System.Drawing.Image.FromFile(sourcePath);
        }
    }
}
private void btnSelectTemplate_Click(object sender, EventArgs e)
{
    using(OpenFileDialog openFileDialog = new OpenFileDialog())
    {
        openFileDialog.Filter = "Image files (*.png;*.jpg;*.jpeg)|*.png;*.jpg;*.jpeg|All files (*.*)|*.*";
        if(openFileDialog.ShowDialog() == DialogResult.OK)
        {
            templatePath = openFileDialog.FileName;
            txtTemplatePath.Text = templatePath;
            pictureBoxTemplate.Image = System.Drawing.Image.FromFile(templatePath);
        }
    }
}

2. 影象預處理

在進行輪廓匹配之前,我們需要對影象進行預處理。這包括將影象轉換為灰度圖,並應用二值化處理:

Cv2.Threshold(source, source, 127, 255, ThresholdTypes.Binary);
Cv2.Threshold(template, template, 127, 255, ThresholdTypes.Binary);

3. 輪廓檢測

使用Cv2.FindContours方法來檢測源影象和模板影象中的輪廓:

Cv2.FindContours(source, out Point[][] sourceContours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
Cv2.FindContours(template, out Point[][] templateContours, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

4. 輪廓匹配

我們使用Cv2.MatchShapes方法來比較模板輪廓與源影象中的每個輪廓的相似度:

double match = Cv2.MatchShapes(templateContours[0], sourceContours[i], ShapeMatchModes.I1, 0);

5. 結果顯示

如果找到匹配的輪廓(相似度高於閾值),我們會在結果影象中繪製該輪廓並顯示相似度:

if(bestMatchIndex != -1 && bestMatch < 0.1)
{
    using(Mat result = source.Clone())
    {
        Cv2.CvtColor(result, result, ColorConversionCodes.GRAY2BGR);
        Cv2.DrawContours(result, sourceContours, bestMatchIndex, Scalar.Red, 2);
        pictureBoxResult.Image = BitmapConverter.ToBitmap(result);
    }
    lblResult.Text = $ "Match found! Similarity: {1 - bestMatch:F4}";
}
else
{
    lblResult.Text = "No match found.";
}

6.匹配事件

private void btnMatch_Click(object sender, EventArgs e)
{
    if(string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(templatePath))
    {
        MessageBox.Show("Please select both source and template images.");
        return;
    }
    try
    {
        using(Mat source = Cv2.ImRead(sourcePath, ImreadModes.GrayScale)) using(Mat template = Cv2.ImRead(templatePath, ImreadModes.GrayScale))
        {
            Cv2.Threshold(source, source, 127, 255, ThresholdTypes.Binary);
            Cv2.Threshold(template, template, 127, 255, ThresholdTypes.Binary);
            Cv2.FindContours(source, out Point[][] sourceContours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            Cv2.FindContours(template, out Point[][] templateContours, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            double bestMatch = double.MaxValue;
            int bestMatchIndex = -1;
            for(int i = 0; i < sourceContours.Length; i++)
            {
                double match = Cv2.MatchShapes(templateContours[0], sourceContours[i], ShapeMatchModes.I1, 0);
                if(match < bestMatch)
                {
                    bestMatch = match;
                    bestMatchIndex = i;
                }
            }
            if(bestMatchIndex != -1 && bestMatch < 0.1)
            // 設定一個閾值            
            {
                using(Mat result = source.Clone())
                {
                    Cv2.CvtColor(result, result, ColorConversionCodes.GRAY2BGR);
                    Cv2.DrawContours(result, sourceContours, bestMatchIndex, Scalar.Red, 2);
                    pictureBoxResult.Image = BitmapConverter.ToBitmap(result);
                }
                lblResult.Text = $ "Match found! Similarity: {1 - bestMatch:F4}";
            }
            else
            {
                lblResult.Text = "No match found.";
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($ "An error occurred: {ex.Message}");
    }
}

注意事項

  1. 影象預處理:二值化閾值(127)可能需要根據實際影象調整以獲得最佳結果。

  2. 匹配閾值:當前程式碼中使用的閾值(0.1)可能需要根據具體應用場景進行調整。

  3. 錯誤處理:程式碼中包含了基本的錯誤處理,但在實際應用中可能需要更健壯的錯誤處理機制。

效能最佳化

對於大型影象或需要實時處理的應用,可以考慮以下最佳化方法:

  1. 影象縮放:在處理之前將大影象縮小到合適的尺寸。

  2. 並行處理:使用並行迴圈(Parallel.For)來加速輪廓匹配過程。

  3. ROI(感興趣區域):如果知道目標可能出現的大致位置,可以只在特定區域內搜尋。

結論

本文介紹瞭如何使用OpenCvSharp在C# WinForms應用程式中實現基本的輪廓匹配功能。透過結合OpenCV的強大影象處理能力和WinForms的用戶界面,我們建立了一個直觀的工具來演示輪廓匹配技術。

這個應用程式為更復雜的計算機視覺專案奠定了基礎。透過進一步的最佳化和功能擴充套件,它可以發展成為一個強大的影象分析工具,適用於各種實際應用場景,如質量控制、醫學影像分析或自動化視覺檢測系統。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.