圖片特征向量是一種用於描述圖片內容的數學表示,它可以反映圖片的顏色、紋理、形狀等信息。圖片特征向量可以用於做很多事情,比如圖片檢索、分類、識別等。 本文將介紹圖片特征向量的提取以及相似度的計算,並使用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實現高性能全文搜索
寫作不易,轉載請註明博文地址,否則禁轉!!!