OpenCV+OpenCvSharp實現圖片特征向量提取與相似度計算

来源:https://www.cnblogs.com/anech/archive/2023/10/27/17792133.html
-Advertisement-
Play Games

圖片特征向量是一種用於描述圖片內容的數學表示,它可以反映圖片的顏色、紋理、形狀等信息。圖片特征向量可以用於做很多事情,比如圖片檢索、分類、識別等。 本文將介紹圖片特征向量的提取以及相似度的計算,並使用C#來實現它們。 文章開始前,我們先來簡單瞭解一下 OpenCV 和 OpenCvSharp4,這兩 ...


圖片特征向量是一種用於描述圖片內容的數學表示,它可以反映圖片的顏色、紋理、形狀等信息。圖片特征向量可以用於做很多事情,比如圖片檢索、分類、識別等。

本文將介紹圖片特征向量的提取以及相似度的計算,並使用C#來實現它們。

文章開始前,我們先來簡單瞭解一下 OpenCV 和 OpenCvSharp4,這兩個庫是本文的核心。

什麼是OpenCV

OpenCV(Open Source Computer Vision Library)是一個基於開源發行的跨平臺電腦視覺和機器學習軟體庫,它支持多種編程語言,包含了數百種圖像處理和電腦視覺演算法。

什麼是OpenCvSharp4

OpenCvSharp4 是一個基於 OpenCV 開發的跨平臺圖像處理庫,它支持 .NET Framework 4.8+和 .NET Core 2.0+。它提供了豐富而易用的 API,可以實現各種圖像處理功能。OpenCvSharp4 只包含核心的托管庫,所以還需要另外安裝對應操作系統的原生綁定包(OpenCvSharp4.runtime.*)。

圖片特征向量提取

提取圖片特征向量的方法有很多,本文將採用 SIFT 和 SURF 兩種常用的演算法。

SIFT演算法

SIFT(Scale Invariant Feature Transform)演算法是一種尺度不變的特征提取方法,它能夠在不同的尺度空間中檢測出穩定的關鍵點,並生成具有唯一性和不變性的描述符。SIFT 演算法的主要優點是:

  • 尺度不變性:SIFT 演算法使用了高斯金字塔來構建不同尺度的圖像,併在每個尺度上進行極值點檢測,從而實現了對尺度變化的不敏感。
  • 旋轉不變性:SIFT 演算法使用了梯度方向直方圖來生成描述符,並根據關鍵點的主方向進行旋轉歸一化,從而實現了對旋轉變化的不敏感。
  • 鑒別性強:SIFT 演算法能夠生成具有高維度和高信息量的描述符,使得每個關鍵點都具有唯一性和區分性,提高了匹配的可靠性。

使用 OpenCvSharp4 實現 SIFT 演算法很簡單,只需要調用SIFT.Create方法創建一個SIFT對象,然後調用DetectAndCompute方法從圖片中提取特征點和描述符。下麵是代碼示例:

// 載入圖片
Mat image1 = Cv2.ImRead("image1.jpg", ImreadModes.Grayscale);
Mat image2 = Cv2.ImRead("image2.jpg", ImreadModes.Grayscale);
​
// 創建SIFT對象
SIFT sift = SIFT.Create();
​
// 提取特征點和描述符
Mat descriptors1 = new Mat();
Mat descriptors2 = new Mat();
sift.DetectAndCompute(image1, null, out _, descriptors1);
sift.DetectAndCompute(image2, null, out _, descriptors2);

SURF演算法

SURF(Speeded Up Robust Features)演算法是一種快速而穩健的特征提取方法,它基於Harris角點檢測和尺度不變特征變換(SIFT)演算法改進而來。SURF 演算法的主要優點是:

  • 速度快:SURF 演算法使用了積分圖和哈爾小波來加速特征點檢測和描述符生成,比SIFT演算法快幾倍。
  • 穩健性高:SURF 演算法對於旋轉、縮放、亮度變化等干擾具有較好的魯棒性,能夠在不同的場景中保持穩定的性能。
  • 精度高:SURF 演算法能夠提取出高質量的特征點和描述符,提高了匹配的準確率。

使用 OpenCvSharp4 實現 SURF 演算法也非常簡單,只需要調用SURF.Create方法創建一個SURF對象,然後調用DetectAndCompute方法從圖片中提取特征點和描述符。下麵是代碼示例:

// 載入圖片
Mat image1 = Cv2.ImRead("image1.jpg", ImreadModes.Grayscale);
Mat image2 = Cv2.ImRead("image2.jpg", ImreadModes.Grayscale);
​
// 創建SURF對象
SURF surf = SURF.Create(500); // 500是閾值參數,表示特征點的最小響應值
​
// 提取特征點和描述符
Mat descriptors1 = new Mat();
Mat descriptors2 = new Mat();
surf.DetectAndCompute(image1, null, out _, descriptors1);
surf.DetectAndCompute(image2, null, out _, descriptors2);

圖片相似度計算

提取了圖片的特征向量後,我們就可以計算圖片的相似度了。圖片相似度的計算方法有很多,本文將介紹兩種常用的方法:BFMatcher 和 FlannBasedMatcher,它們都是基於特征點匹配的方法,但是有一些區別。

BFMatcher

BFMatcher 是一種暴力匹配方法,它的原理是對於第一張圖片中的每個特征點,都遍歷第二張圖片中的所有特征點,找出最接近的一個或多個特征點作為匹配結果。BFMatcher 的優點是簡單直觀,缺點是效率低,時間複雜度為 O(n^2),其中n是特征點的數量。

使用 OpenCvSharp4 實現 BFMatcher 也非常簡單,只需要調用BFMatcher類的構造函數創建一個BFMatcher對象,然後調用Match方法進行匹配。下麵是代碼示例:

// 創建BFMatcher對象
BFMatcher bfMatcher = new BFMatcher(NormTypes.L2, false); // NormTypes.L2表示使用歐式距離作為相似度度量,false表示不交叉匹配
​
// 進行匹配
DMatch[] bfMatches = bfMatcher.Match(descriptors1, descriptors2); // bfMatches是一個數組,每個元素是一個DMatch對象,表示一對匹配結果

FlannBasedMatcher

FlannBasedMatcher 是一種近似最近鄰匹配方法,它的原理是使用一種快速的索引結構來加速特征點的查找,從而降低時間複雜度。FlannBasedMatcher 的優點是效率高,缺點是精度略低,可能會出現一些錯誤的匹配。

使用 OpenCvSharp4 實現 FlannBasedMatcher 也非常簡單,只需要調用FlannBasedMatcher類的構造函數創建一個FlannBasedMatcher對象,然後調用Match方法進行匹配。下麵是代碼示例:

// 創建FlannBasedMatcher對象
FlannBasedMatcher flannMatcher = new FlannBasedMatcher();
​
// 進行匹配
DMatch[] flannMatches = flannMatcher.Match(descriptors1, descriptors2); // flannMatches是一個數組,每個元素是一個DMatch對象,表示一對匹配結果

相似度得分

相似度得分的計算方法有很多,這裡使用一種簡單的方法:首先計算出每個匹配對的距離。然後對所有的距離求平均值,得到一個相似度得分,得分越小表示越相似。

我們對 BFMatcher 和 FlannBasedMatcher 的匹配結果都做了這個計算。

// 計算並顯示BFMatcher和FlannBasedMatcher的相似度得分,得分越低越相似
Console.WriteLine("The score using BFMatcher is {0}", bfMatches.Average(m => m.Distance));
Console.WriteLine("The score using FlannBasedMatcher is {0}", flannMatches.Average(m => m.Distance));

這樣,圖片特征向量提取和相似度計算就實現了。完整代碼可在公眾號查看。

結果對比

接下來我們運行程式,從四種情況去查看結果。

1、兩張完全不同的圖片對比

這種情況下,我們可以預期得到很高的相似度得分,表示兩張圖片幾乎沒有相似之處。如圖所示:

卡通人物

中度可信度描述已自動生成

SURF演算法
The score using BFMatcher is 0.77414566
The score using FlannBasedMatcher is 0.77414566
SIFT演算法
The score using BFMatcher is 366.84616
The score using FlannBasedMatcher is 372.25107

2、兩張完全相同的圖片對比

這種情況下,我們可以預期得到很低的相似度得分,表示兩張圖片完全一致。如圖所示:

SURF演算法
The score using BFMatcher is 0
The score using FlannBasedMatcher is 0
SIFT演算法
The score using BFMatcher is 0
The score using FlannBasedMatcher is 0

3、某一張圖片和它的部分截圖進行對比

這種情況下,我們可以預期得到中等的相似度得分,表示兩張圖片有部分重合。如圖所示:

SURF演算法
The score using BFMatcher is 0.22462595
The score using FlannBasedMatcher is 0.23025486
SIFT演算法
The score using BFMatcher is 105.93032
The score using FlannBasedMatcher is 108.3307

4、兩張相似的圖片進行對比

這種情況下,我們可以預期得到較低的相似度得分,表示兩張圖片有很多共同的特征。例如,我們可以使用兩張不同角度拍攝的同一物體的圖片進行對比。如圖所示:

 

SURF演算法
The score using BFMatcher is 0.37855583
The score using FlannBasedMatcher is 0.38878053
SIFT演算法
The score using BFMatcher is 239.1525
The score using FlannBasedMatcher is 248.43388

從上面的結果可以看出,SURF 和 SIFT 演算法都可以提取圖片特征向量,同時,BFMatcher 和 FlannBasedMatcher 也有區別。因此,在選演算法時,需要根據具體的應用場景和需求進行權衡。

如果你對此感興趣,還可以進一步探究,將圖片特征向量存儲到向量資料庫中,實現更多的功能需求。比如,你可以使用 Redis 或  Elasticsearch,它們都支持對向量數據進行增、刪、改、查等操作。

以下是相關推薦閱讀:

1、ChatGPT Embeddings與Redis強強結合實現文本相似度分析與搜索

2、利用Redis實現向量相似度搜索:解決文本、圖像和音頻之間的相似度匹配問題

3、C#+Redis Search:如何用Redis實現高性能全文搜索

寫作不易,轉載請註明博文地址,否則禁轉!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 作者:hinotoyk 鏈接:https://juejin.cn/post/6910215219822362632 背景:某日在公司中擼代碼的時候,在一個常用的controller中添加一個方法,測試時突然報錯說註入的service為null,搗鼓一陣發現後是方法修飾符寫成private,修改成pu ...
  • BeautifulSoup庫用於從HTML或XML文件中提取數據。它可以自動將複雜的HTML文檔轉換為樹形結構,並提供簡單的方法來搜索文檔中的節點,使得我們可以輕鬆地遍歷和修改HTML文檔的內容。廣泛用於Web爬蟲和數據抽取應用程式中。 ...
  • `Shiro`許可權框架認證失敗預設是重定向頁面的,這對於前後端分離的項目及其不友好,可能會造成請求404的問題。現在我們自定義過濾器實現認證失敗返回json數據。 ...
  • 1 引言 小團隊一般 10 人左右,其中常常是技術最牛的人做架構師(或TL)。所以,架構師在廣大碼農中的占比大概平均不到 10%。而架構師也可以分為初級、中級、高級三檔,江湖上真正高水平的軟體架構師就更少了。 所以,大部分(超過九成的)碼農幹上許多年,還是做不了架構師,這是什麼原因造成的呢? 2 說 ...
  • 我們都知道java中,如果char類型和int類型做加減法,那麼char類型會被精度提升至int類型然後參與運算,返回的也是int類型的數據。 那麼如果表達式中參與運算的均為char類型,那麼表達式返回的類型是什麼呢? 'A' - 'a' 經過簡單測試,是int類型。 char c = 'w'; s ...
  • 雷達圖(Radar Chart),也被稱為蛛網圖或星型圖,是一種用於可視化多個變數之間關係的圖表形式。雷達圖是一種顯示多變數數據的圖形方法。通常從同一中心點開始等角度間隔地射出三個以上的軸,每個軸代表一個定量變數,各軸上的點依次連接成線或幾何圖形。 雷達圖可以用來在變數間進行對比,或者查看變數中有沒 ...
  • 不想裝golang,不想裝IDE,還想有個流暢的運行環境,最重要的是一分錢都不想花,嗯嗯,GitHub雲開發環境全部滿足你,一切操作盡在本文 ...
  • 什麼是快捷代碼段:例如: 只需要輸入mst後按一下TAB就會自動生成代碼memset(str, 0, sizeof(str));,只需要輸入Pow就可以自動生成一個快速冪函數等等,非常方便快捷,一定程度提高了編寫代碼的效率 Visual Studio 設置自定義代碼段方法:①新建文件XXX.snip ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...