22.OpenCV輪廓匹配原理介紹與使用

OpenCV輪廓匹配原理介紹與使用

1. 輪廓匹配的基本概念

輪廓匹配(Contour Matching)是計算機視覺中的一種重要方法,主要用于比較兩個輪廓的相似性。它廣泛應用于目標識別、形狀分析、手勢識別等領域。

在 OpenCV 中,輪廓匹配主要基于形狀匹配算法,其中 matchShapes 是核心函數。該函數用于計算兩個輪廓之間的相似度,返回一個數值,該數值越小表示兩個輪廓越相似。

2. 輪廓匹配的算法原理

Hu矩(Hu Moments)是由Ming-Kuei Hu在1962年提出。OpenCV 采用 Hu 矩(Hu Moments)進行輪廓匹配。Hu 矩是一組不變矩,可以用于描述圖像的形狀特征,并且具有旋轉、縮放和平移不變性。Hu矩是通過對圖像的歸一化中心矩進行特定的線性組合得到的。具體而言,它們是基于二階和三階的歸一化中心矩計算的。

Hu 矩由 7 個不變矩組成:

I 1 = η 20 + η 02 I 2 = ( η 20 ? η 02 ) 2 + 4 η 11 2 I 3 = ( η 30 ? 3 η 12 ) 2 + ( 3 η 21 ? η 03 ) 2 I 4 = ( η 30 + η 12 ) 2 + ( η 21 + η 03 ) 2 I 5 = ( η 30 ? 3 η 12 ) ( η 30 + η 12 ) [ ( η 30 + η 12 ) 2 ? 3 ( η 21 + η 03 ) 2 ] + ( 3 η 21 ? η 03 ) ( η 21 + η 03 ) [ 3 ( η 30 + η 12 ) 2 ? ( η 21 + η 03 ) 2 ] I 6 = ( η 20 ? η 02 ) [ ( η 30 + η 12 ) 2 ? ( η 21 + η 03 ) 2 ] + 4 η 11 ( η 30 + η 12 ) ( η 21 + η 03 ) I 7 = ( 3 η 21 ? η 03 ) ( η 30 + η 12 ) [ ( η 30 + η 12 ) 2 ? 3 ( η 21 + η 03 ) 2 ] ? ( η 30 ? 3 η 12 ) ( η 21 + η 03 ) [ 3 ( η 30 + η 12 ) 2 ? ( η 21 + η 03 ) 2 ] \begin{align*}I_1 &= \eta_{20} + \eta_{02} \\I_2 &= (\eta_{20} - \eta_{02})^2 + 4\eta_{11}^2 \\I_3 &= (\eta_{30} - 3\eta_{12})^2 + (3\eta_{21} - \eta_{03})^2 \\I_4 &= (\eta_{30} + \eta_{12})^2 + (\eta_{21} + \eta_{03})^2 \\I_5 &= (\eta_{30} - 3\eta_{12})(\eta_{30} + \eta_{12})\left[(\eta_{30} + \eta_{12})^2 - 3(\eta_{21} + \eta_{03})^2\right] \\&\quad + (3\eta_{21} - \eta_{03})(\eta_{21} + \eta_{03})\left[3(\eta_{30} + \eta_{12})^2 - (\eta_{21} + \eta_{03})^2\right] \\I_6 &= (\eta_{20} - \eta_{02})\left[(\eta_{30} + \eta_{12})^2 - (\eta_{21} + \eta_{03})^2\right] \\&\quad + 4\eta_{11}(\eta_{30} + \eta_{12})(\eta_{21} + \eta_{03}) \\I_7 &= (3\eta_{21} - \eta_{03})(\eta_{30} + \eta_{12})\left[(\eta_{30} + \eta_{12})^2 - 3(\eta_{21} + \eta_{03})^2\right] \\&\quad - (\eta_{30} - 3\eta_{12})(\eta_{21} + \eta_{03})\left[3(\eta_{30} + \eta_{12})^2 - (\eta_{21} + \eta_{03})^2\right]\end{align*} I1?I2?I3?I4?I5?I6?I7??=η20?+η02?=(η20??η02?)2+4η112?=(η30??3η12?)2+(3η21??η03?)2=(η30?+η12?)2+(η21?+η03?)2=(η30??3η12?)(η30?+η12?)[(η30?+η12?)2?3(η21?+η03?)2]+(3η21??η03?)(η21?+η03?)[3(η30?+η12?)2?(η21?+η03?)2]=(η20??η02?)[(η30?+η12?)2?(η21?+η03?)2]+4η11?(η30?+η12?)(η21?+η03?)=(3η21??η03?)(η30?+η12?)[(η30?+η12?)2?3(η21?+η03?)2]?(η30??3η12?)(η21?+η03?)[3(η30?+η12?)2?(η21?+η03?)2]?

通過計算 Hu 矩的值,OpenCV 使用 matchShapes 進行輪廓匹配.

需要注意的是,雖然Hu矩對常見的幾何變換具有不變性,但在實際應用中,噪聲、遮擋和分割質量等因素可能影響其穩定性。因此,在處理實際問題時,需綜合考慮這些因素對Hu矩計算的影響。

3. matchShapes 函數介紹

3.1 函數原型

double matchShapes(InputArray contour1, InputArray contour2, int method, double parameter);

3.2 參數說明

  • contour1:第一個輪廓(vector<Point> 格式)。
  • contour2:第二個輪廓(vector<Point> 格式)。
  • method:匹配方法,可選值:
    • CONTOURS_MATCH_I1 d ( I ) = ∑ ∣ 1 I i ( 1 ) ? 1 I i ( 2 ) ∣ d(I)=\sum\begin{vmatrix} \frac{1}{I_i^{(1)}}-\frac{1}{I_i^{(2)}} \end{vmatrix} d(I)= ?Ii(1)?1??Ii(2)?1?? ?
    • CONTOURS_MATCH_I2 d ( I ) = ∣ I i ( 1 ) ? I i ( 2 ) ∣ d(I)=\begin{vmatrix}I_i^{(1)}-I_i^{(2)}\end{vmatrix} d(I)= ?Ii(1)??Ii(2)?? ?
    • CONTOURS_MATCH_I3 d ( I ) = ∑ ∣ 1 i 1 ( 1 ) ? 1 i i ( 2 ) ∣ d(I)=\sum\begin{vmatrix} \frac{1}{i_1^{(1)}}-\frac{1}{i_i^{(2)}} \end{vmatrix} d(I)= ?i1(1)?1??ii(2)?1?? ?
  • parameter:該參數在當前版本未使用,通常填 0

3.3 返回值

返回兩個輪廓之間的相似性分數,數值越小,輪廓越相似

4. 輪廓匹配

4.1示例代碼1:直接匹配

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>using namespace cv;
using namespace std;int main() 
{// 1. 讀取輸入圖像和模板圖像,并轉換為灰度圖Mat inputImg = imread("E:/image/pic1.png");Mat templateImg = imread("E:/image/templ.png");if (inputImg.empty() || templateImg.empty()) {cerr << "圖像加載失敗!" << endl;return -1;}Mat grayInput, grayTemplate;cvtColor(inputImg, grayInput, COLOR_BGR2GRAY);cvtColor(templateImg, grayTemplate, COLOR_BGR2GRAY);// 2. 對圖像應用閾值處理得到二值圖像Mat binaryInput, binaryTemplate;threshold(grayInput, binaryInput, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);threshold(grayTemplate, binaryTemplate, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);// 3. 檢測輪廓vector<vector<Point>> contoursInput, contoursTemplate;vector<Vec4i> hierarchy;findContours(binaryInput, contoursInput, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);findContours(binaryTemplate, contoursTemplate, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);// 4. 假設模板圖像只包含一個主要輪廓,取第一個輪廓作為模板if (contoursTemplate.empty()) {cerr << "模板輪廓檢測失敗!" << endl;return -1;}cout << contoursTemplate.size();vector<Point> templateContour = contoursTemplate[0];// 5. 遍歷輸入圖像中的所有輪廓,計算與模板輪廓的匹配度for (size_t i = 0; i < contoursInput.size(); i++) {double matchScore = matchShapes(templateContour, contoursInput[i], CONTOURS_MATCH_I1, 0);cout << "輪廓 " << i << " 匹配分數: " << matchScore << endl;// 在輸入圖像上繪制輪廓并標注匹配分數if (matchScore<0.05){drawContours(inputImg, contoursInput, static_cast<int>(i), Scalar(0, 255, 0), 2);}Moments m = moments(contoursInput[i]);int cx = static_cast<int>(m.m10 / m.m00);int cy = static_cast<int>(m.m01 / m.m00);putText(inputImg, format("%.2f", matchScore), Point(cx, cy), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);}//6. 顯示結果\n   imshow("輸入圖像輪廓匹配", inputImg);imshow("模板圖像", templateImg);waitKey(0);return 0;
}

在這里插入圖片描述

綠色為找到的輪廓

4. 2示例代碼2:hu距匹配

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>using namespace cv;
using namespace std;int main()
{// 1. 讀取輸入圖像和模板圖像,并轉換為灰度圖Mat inputImg = imread("E:/image/pic1.png");Mat templateImg = imread("E:/image/templ.png");if (inputImg.empty() || templateImg.empty()) {cerr << "圖像加載失敗!" << endl;return -1;}Mat grayInput, grayTemplate;cvtColor(inputImg, grayInput, COLOR_BGR2GRAY);cvtColor(templateImg, grayTemplate, COLOR_BGR2GRAY);// 2. 對圖像應用閾值處理得到二值圖像Mat binaryInput, binaryTemplate;threshold(grayInput, binaryInput, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);threshold(grayTemplate, binaryTemplate, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);// 3. 檢測輪廓vector<vector<Point>> contoursInput, contoursTemplate;vector<Vec4i> hierarchy;findContours(binaryInput, contoursInput, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);findContours(binaryTemplate, contoursTemplate, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);// 4. 假設模板圖像只包含一個主要輪廓,取第一個輪廓作為模板if (contoursTemplate.empty()) {cerr << "模板輪廓檢測失敗!" << endl;return -1;}cout << contoursTemplate.size();vector<Point> templateContour = contoursTemplate[0];Moments mTemplate = moments(contoursTemplate[0]);Mat huTemplate;HuMoments(mTemplate, huTemplate);// 5. 遍歷輸入圖像中的所有輪廓,計算與模板輪廓的匹配度for (size_t i = 0; i < contoursInput.size(); i++) {// 在輸入圖像上繪制輪廓并標注匹配分數Moments m = moments(contoursInput[i]);Mat hu;HuMoments(m, hu);double matchScore = matchShapes(hu, huTemplate, CONTOURS_MATCH_I1, 0);cout << "輪廓 " << i << " 匹配分數: " << matchScore << endl;if (matchScore < 0.005){drawContours(inputImg, contoursInput, static_cast<int>(i), Scalar(0, 255, 0), 2);}int cx = static_cast<int>(m.m10 / m.m00);int cy = static_cast<int>(m.m01 / m.m00);putText(inputImg, format("%.2f", matchScore), Point(cx, cy), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);}//6. 顯示結果\n   imshow("輸入圖像輪廓匹配", inputImg);imshow("模板圖像", templateImg);waitKey(0);return 0;
}

在這里插入圖片描述

5. 輪廓匹配的應用場景

OpenCV 的 matchShapes 通過 Hu 矩計算輪廓的相似性,是一種高效的輪廓匹配方法。適用于各種形狀分析任務,在實際應用中,可以結合其他特征進一步優化匹配結果。
常用場景

  1. 目標識別:如手寫字符識別、手勢識別,車牌識別等。
  2. 工業檢測:用于檢測物品形狀偏差。
  3. 醫學影像分析:對比醫學影像中的病變輪廓。
  4. 形狀檢索:在數據庫中尋找相似形狀的對象。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/900507.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900507.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900507.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

oracle 快速創建表結構

在 Oracle 中快速創建表結構&#xff08;僅復制表結構&#xff0c;不復制數據&#xff09;可以通過以下方法實現&#xff0c;適用于需要快速復制表定義或生成空表的場景 1. 使用 CREATE TABLE AS SELECT (CTAS) 方法 -- 復制源表的全部列和數據類型&#xff0c;但不復制數據 C…

若依原理筆記

代碼生成器 源碼分析 查詢數據庫列表 導入表結構 生成代碼 修改generator.yml配置文件 代碼生成器增強 Velocity模版引擎 基礎語法-變量 Lombok集成 E:\javaProject\dkd-parent\dkd-generator\src\main\resources\vm\java\domain.java.vm package ${packageName}.domain;#fo…

Ansible的使用

##### Ansible使用環境 - 控制節點 - 安裝Ansible軟件 - Python環境支持&#xff1a;Python>2.6 - 必要的模塊&#xff1a;如PyYAML等 - 被控節點 - 啟用SSH服務 - 允許控制節點登錄&#xff0c;通常設置免密登錄 - Python環境支持 http://www.ansible.com/ …

C++ 提高編程:模板與 STL 深度剖析

摘要&#xff1a;本文深入探討 C 提高編程中的模板編程與標準模板庫&#xff08;STL&#xff09;相關內容。詳細闡述模板編程中函數模板和類模板的概念、語法、特性及應用案例&#xff1b;對 STL 的誕生背景、基本概念、六大組件進行剖析&#xff0c;并對常用容器、函數對象、常…

C++(類模板的運用)

使用vector實現一個簡單的本地注冊登錄系統 注冊&#xff1a;將賬號密碼存入vector里面&#xff0c;注意防重復判斷 登錄&#xff1a;判斷登錄的賬號密碼是否正確 #include <iostream> #include <vector> #include <fstream> #include <sstream> usi…

【大模型】DeepSeek+藍耕MaaS平臺+海螺AI生成高質量視頻實戰詳解

目錄 一、前言 二、藍耘智能云MaaS平臺介紹 2.1 藍耘智算平臺是什么 2.2 平臺優勢 2.3 平臺核心能力 三、海螺AI視頻介紹 3.1 海螺AI視頻是什么 3.2 海螺AI視頻主要功能 3.3 海螺AI視頻應用場景 3.4 海螺AI視頻核心優勢 3.5 項目git地址 四、藍耘MaaS平臺DeepSeek海…

接口自動化學習二:session自動管理cookie

session自動管理cookie&#xff1a; cookie中的數據&#xff0c;都是session提供的 實現步驟&#xff1a; 1.創建session對象&#xff1b;my_sessionrequests.Session() 2.使用session實例&#xff0c;調用get方法&#xff0c;發送獲取驗證碼請求&#xff08;不需要提取cookie&…

C++類型轉換詳解

目錄 一、內置 轉 內置 二、內置 轉 自定義 三、自定義 轉 內置 四、自定義 轉 自定義 五、類型轉換規范化 1.static_case 2.reinterpret_cast 3.const_cast 4.dynamic_cast 六、RTTI 一、內置 轉 內置 C兼容C語言&#xff0c;在內置類型之間轉換規則和C語言一樣的&am…

QEMU源碼全解析 —— 塊設備虛擬化(17)

接前一篇文章:QEMU源碼全解析 —— 塊設備虛擬化(16) 本文內容參考: 《趣談Linux操作系統》 —— 劉超,極客時間 《QEMU/KVM源碼解析與應用》 —— 李強,機械工業出版社 《KVM實戰 —— 原理、進階與性能調優》—— 任永杰 程舟,機械工業出版社

mac 卸載流氓軟件安全助手

之前個人電腦在公司使用過一段時間&#xff0c;為了使用網線聯網安裝了公司指定的 聯軟上網助手&#xff0c;誰知安裝容易卸載難&#xff0c;后來找運維來卸載&#xff0c;輸入管理員密碼后&#xff0c;也無反應&#xff0c;最后不了了之了&#xff0c;這個毒瘤軟件長期在后臺駐…

Java 大視界 -- Java 大數據機器學習模型在智能客服多輪對話系統中的優化策略(179)

&#x1f496;親愛的朋友們&#xff0c;熱烈歡迎來到 青云交的博客&#xff01;能與諸位在此相逢&#xff0c;我倍感榮幸。在這飛速更迭的時代&#xff0c;我們都渴望一方心靈凈土&#xff0c;而 我的博客 正是這樣溫暖的所在。這里為你呈上趣味與實用兼具的知識&#xff0c;也…

極氪汽車云原生架構落地實踐

云原生架構落地實踐的背景 隨著極氪數字業務的飛速發展&#xff0c;背后的 IT 技術也在不斷更新迭代。極氪極為重視客戶對服務的體驗&#xff0c;并將系統穩定性、業務功能的迭代效率、問題的快速定位和解決視為構建核心競爭力的基石。 為快速響應用戶的需求&#xff0c;例如…

Python?判斷循環

????˙?˙? ? 判斷??常用的判斷符號(比較運算符)andor括號notin 和 not inif-elif-else循環??計數循環 forrange()函數簡易倒計時enumerate()函數zip()函數遍歷列表遍歷元組遍歷字符串遍歷字典條件循環 while提前跳轉 continue跳出循環 break能量站??判斷?? …

FreeRTOS與RT-Thread深度對比:從入門到精通的全面解析

FreeRTOS與RT-Thread深度對比&#xff1a;從入門到精通的全面解析 在嵌入式系統開發領域&#xff0c;實時操作系統(RTOS)扮演著至關重要的角色。FreeRTOS和RT-Thread作為兩款主流的開源RTOS&#xff0c;各有特色&#xff0c;適用于不同的應用場景。本文將從小白到大神的角度&a…

OpenCV 圖形API(18)用于執行兩個矩陣(或數組)的逐元素減法操作函數sub()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 描述 計算兩個矩陣之間的逐元素差值。 sub 函數計算兩個矩陣之間的差值&#xff0c;要求這兩個矩陣具有相同的尺寸和通道數&#xff1a; dst ( I ) src…

LeetCode刷題SQL筆記

系列博客目錄 文章目錄 系列博客目錄1.distinct關鍵字 去除重復2.char_length()3.group by 與 count()連用4.date類型有個函數datediff()5.mod 函數6.join和left join的區別1. **JOIN&#xff08;內連接&#xff0c;INNER JOIN&#xff09;**示例&#xff1a; 2. **LEFT JOIN&a…

其他合成方式介紹

在 SurfaceFlinger 的 Layer 處理邏輯中&#xff0c;除了常見的 Client Composition&#xff08;GPU合成&#xff09; 和 Device Composition&#xff08;HWC合成&#xff09;&#xff0c;還存在一些特殊的合成方式&#xff0c;比如 Sideband、Solid Color 和 Display Decorati…

GraphRAG與知識圖譜

一、GraphRAG介紹 1.1 什么是 Graph RAG&#xff1f; Graph RAG&#xff08;Retrieval-Augmented Generation&#xff09;&#xff0c;是一種基于知識圖譜的檢索增強技術&#xff0c; 通過構建圖模型的知識表達&#xff0c;將實體和關系之間的聯系用圖的形式進行展示&#xff…

一個開源的 VS Code 大模型聊天插件:Light-at

這篇文章是一個開發雜談。對于有經驗的開發者來說&#xff0c;可能這個項目并不算特別復雜或者高技術&#xff0c;只是對我個人來說算一個里程碑&#xff0c;因此寫篇雜談文章記錄一下。也許也能給起步者一些參考。 項目地址&#xff1a;https://github.com/HiMeditator/light-…

SQL121 創建索引

-- 普通索引 CREATE INDEX idx_duration ON examination_info(duration);-- 唯一索引 CREATE UNIQUE INDEX uniq_idx_exam_id ON examination_info(exam_id);-- 全文索引 CREATE FULLTEXT INDEX full_idx_tag ON examination_info(tag);描述 現有一張試卷信息表examination_in…