21.OpenCV獲取圖像輪廓信息

OpenCV獲取圖像輪廓信息

在計算機視覺領域,識別和分析圖像中的對象形狀是一項基本任務。OpenCV 庫提供了一個強大的工具——輪廓檢測(Contour Detection),它能夠幫助我們精確地定位對象的邊界。這篇博文將帶你入門 OpenCV 的輪廓檢測,理解其原理,并學會如何在 C++ 中使用它。

1.什么是輪廓?

簡單來說,輪廓可以看作是一條連接所有具有相同顏色或灰度值的連續點(沿著邊界)的曲線。

更準確地說,輪廓是圖像中強度或顏色發生顯著變化的區域的邊界。在 OpenCV 中,輪廓檢測通常作用于二值圖像(只有黑色和白色像素的圖像)。算法會尋找白色(或非零)區域的邊界,并將這些邊界表示為一系列點的坐標。

通過檢測輪廓,我們可以實現目標分割、形狀分析、物體計數、特征提取及對象檢測和識別等任務。

輪廓介紹

如上圖1,2,3 輪廓還有層次,有最外的輪廓1依次往里包括2,3輪廓。

2. OpenCV 輪廓檢測函數

2.1 findContours 函數

findContours 是 OpenCV 中最常用的輪廓檢測函數,其函數原型如下:

void findContours(InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy,int mode, int method, Point offset = Point());
  • image:輸入的二值圖像(非零值表示前景)。
  • contours:輸出輪廓,存儲為 std::vector<std::vector<Point>>
  • hierarchy:輸出輪廓的層級信息,描述輪廓之間的嵌套關系。
  • mode:輪廓檢索模式,如 RETR_EXTERNAL(只檢測最外層輪廓)、RETR_LIST(檢測所有輪廓但不建立層級關系)、RETR_TREE(檢測所有輪廓并重構完整的層級結構)。
  • method:輪廓近似方法,如 CHAIN_APPROX_SIMPLE(壓縮水平、垂直和對角冗余點)和 CHAIN_APPROX_NONE(存儲所有點)。
  • offset:可選參數,用于給輸出輪廓的所有點加上偏移值。

2.3 drawContours 函數

drawContours 函數用于在圖像上繪制檢測到的輪廓。它可以幫助直觀展示輪廓檢測和形狀分析的結果。函數原型如下:

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx,const Scalar& color, int thickness = 1, int lineType = LINE_8,InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point());
  • image:輸入輸出圖像,即在該圖像上繪制輪廓。
  • contours:輪廓集合,通常由 findContours 得到,類型為 std::vector<std::vector<Point>>
  • contourIdx:指定繪制哪一個輪廓;若設為 -1,則繪制所有輪廓。
  • color:繪制輪廓的顏色,如 Scalar(0,255,0) 表示綠色。
  • thickness:輪廓線的粗細;若為負值,則填充輪廓內部。
  • lineType:線型,默認 LINE_8
  • hierarchy:輪廓的層級信息,可選。
  • maxLevel:繪制輪廓的最大層級,默認 INT_MAX
  • offset:繪制時添加的偏移量。

drawContours 常用于可視化輪廓檢測結果,結合 findContours 使用可以將檢測到的目標區域在圖像上直觀標記出來。

2.3 輪廓檢測的基本步驟

使用 OpenCV C++ 進行輪廓檢測通常遵循以下步驟:

  1. 讀取圖像 (Read Image): 使用 cv::imread 加載你想要處理的源圖像到 cv::Mat 對象。
  2. 轉換為灰度圖 (Convert to Grayscale): 使用 cv::cvtColor 將彩色圖像轉換為灰度圖,以簡化圖像信息。
  3. 二值化 (Thresholding): 使用 cv::threshold 將灰度圖像轉換為二值圖像。這是輪廓檢測的關鍵步驟,因為 findContours 函數通常需要二值圖像作為輸入。
  4. 查找輪廓 (Find Contours): 使用 cv::findContours() 函數來檢測圖像中的所有輪廓。
  5. 繪制輪廓 (Draw Contours): (可選)使用 cv::drawContours() 函數將檢測到的輪廓繪制在原始圖像或新的畫布上,以便可視化。

2.4 參考代碼

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;int main() {// 讀取灰度圖像Mat src = imread("E:/image/test.png");if (src.empty()) {cerr << "圖像加載失敗!" << endl;return -1;}Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);GaussianBlur(gray, gray, Size(5, 5), 0);Mat binary;double otsu_thresh_val = threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);cout << "Otsu 自動選擇的閾值為:" << otsu_thresh_val << endl;imshow("原始灰度圖像", gray);imshow("otsu 二值化", binary);//查找輪廓vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);cout << hierarchy.size();//繪制所有輪廓Mat contourImage = src.clone();drawContours(contourImage, contours, -1, Scalar(0, 0, 255), 1);imshow("contour", contourImage);waitKey(0);destroyAllWindows();return 0;
}

輪廓檢測結果

如果只想要最外面的輪廓只需要把參數RETR_TREE改為**RETR_EXTERNAL**

3. 計算并繪制輪廓幾何特征

在檢測到輪廓后,我們可以計算并繪制輪廓的幾何特征,例如:

  • 面積 (contourArea)
  • 周長 (arcLength)
  • 重心
  • 最小外接矩形 (boundingRect)
  • 最小外接圓 (minEnclosingCircle)

3.1 參考代碼

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {// 讀取圖像并轉換為灰度圖Mat src = imread("E:/image/test1.png");if (src.empty()) {cerr << "圖像加載失敗!" << endl;return -1;}Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);// 應用閾值處理得到二值圖像Mat binary;threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);// 檢測輪廓vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);// 創建用于顯示輪廓的圖像Mat contourImage = src.clone();for (size_t i = 0; i < contours.size(); i++) {// 繪制輪廓drawContours(contourImage, contours, static_cast<int>(i), Scalar(0, 255, 0), 2);// 計算輪廓面積和周長double area = contourArea(contours[i]);double perimeter = arcLength(contours[i], true);if (area < 500) continue;// 計算重心Moments M = moments(contours[i]);int cx = static_cast<int>(M.m10 / M.m00);int cy = static_cast<int>(M.m01 / M.m00);circle(contourImage, Point(cx, cy), 5, Scalar(255, 0, 0), -1);// 計算外接矩形Rect boundingBox = boundingRect(contours[i]);rectangle(contourImage, boundingBox, Scalar(0, 0, 255), 2);//最小外接矩形RotatedRect box2 = minAreaRect(contours[i]);Point2f vertices[4];box2.points(vertices);for (int j = 0; j < 4; j++) {line(contourImage, vertices[j], vertices[(j + 1) % 4], Scalar(0, 255, 255), 1);}// 計算最小外接圓Point2f center;float radius;minEnclosingCircle(contours[i], center, radius);circle(contourImage, center, static_cast<int>(radius), Scalar(255, 255, 0), 2);// 在圖像上標注幾何特征putText(contourImage, "Area: " + to_string(static_cast<int>(area)),Point(boundingBox.x, boundingBox.y - 10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 255), 1);putText(contourImage, "Perimeter: " + to_string(static_cast<int>(perimeter)),Point(boundingBox.x, boundingBox.y + boundingBox.height + 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 255), 1);}// 顯示結果imshow("輪廓檢測與幾何特征", contourImage);waitKey(0);return 0;
}

代碼簡介

  1. 輪廓檢測:使用 findContours 提取二值圖像中的所有輪廓。
  2. 繪制輪廓:使用 drawContours 繪制檢測到的輪廓。
  3. 計算幾何特征
    • 面積和周長:使用 contourAreaarcLength 計算。
    • 重心:通過 moments 計算輪廓的中心點,并用 circle 繪制。
    • 最小外接矩形:使用 boundingRect 計算,并用 rectangle 繪制。
    • 最小外接圓:使用 minEnclosingCircle 計算,并用 circle 繪制。
  4. 標注特征信息:使用 putText 在圖像上顯示面積和周長。
  5. 面積篩選:代碼中過濾不顯示面積小于500的輪廓
    獲取輪廓信息

4. 應用場景

輪廓檢測技術在多個領域都有廣泛應用,包括但不限于:

  • 目標分割和計數

    利用輪廓檢測可以分割圖像中的獨立目標,并統計數量,如細胞計數、車牌識別等。

  • 形狀分析

    分析輪廓的幾何特征(如周長、面積、凸包、旋轉角度等),用于目標識別和匹配。

  • 運動跟蹤

    在視頻處理中,通過檢測運動目標的輪廓,進一步實現對象跟蹤和行為分析。

  • OCR 前處理

    對文檔圖像進行輪廓檢測,提取文字區域,為光學字符識別(OCR)提供準備工作。

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

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

相關文章

LETTERS(DFS)

【題目描述】 給出一個rowcolrowcol的大寫字母矩陣&#xff0c;一開始的位置為左上角&#xff0c;你可以向上下左右四個方向移動&#xff0c;并且不能移向曾經經過的字母。問最多可以經過幾個字母。 【輸入】 第一行&#xff0c;輸入字母矩陣行數RR和列數SS&#xff0c;1≤R,S≤…

Day2-2:前端項目uniapp壁紙實戰

再在wallpaper新建一個目錄components 在components下新建組件common-title 記得點擊創建同名目錄 在index加 <view class"select"><common-title></common-title></view> 圖片換了下&#xff0c;原來的有點丑&#xff0c;圖片可按自己喜歡…

其他 vector 操作詳解(四十)

介紹 除去向 vector 添加元素&#xff08;如 push_back&#xff09;之外&#xff0c;vector 還提供了許多其他操作&#xff0c;這些操作大多與 string 的操作類似。通過掌握這些操作&#xff0c;我們可以方便地查詢、修改和比較 vector 中的元素&#xff0c;從而構建靈活、高效…

【Leetcode 每日一題】368. 最大整除子集

問題背景 給你一個由 無重復 正整數組成的集合 n u m s nums nums&#xff0c;請你找出并返回其中最大的整除子集 a n s w e r answer answer&#xff0c;子集中每一元素對 ( a n s w e r [ i ] , a n s w e r [ j ] ) (answer[i], answer[j]) (answer[i],answer[j]) 都應當…

python基礎-13-處理excel電子表格

文章目錄 【README】【13】處理Excel電子表格【13.1】Excel文檔【13.2】安裝openpyxl模塊【13.3】讀取Excel文檔【13.3.1】使用openpyxl模塊打開excel文檔【13.3.2】從工作簿取得工作表【13.3.3】從工作表sheet獲取單元格cell【13.3.5】從表中獲取行和列【13.3.6】工作簿、工作…

ABS函數c++

簡介&#xff1a; abs 函數用于計算一個數的絕對值&#xff0c;在 C 中它繼承自 C 語言的標準庫&#xff0c;其歷史可以追溯到早期的 C 語言發展歷程&#xff0c;以下是詳細介紹&#xff1a; 早期編程語言的需求 在計算機編程的早期階段&#xff0c;處理數學運算就是一項基本…

閉環SOTA!北航DiffAD:基于擴散模型實現端到端自動駕駛「多任務閉環統一」

端到端自動駕駛目前是有望實現完全自動駕駛的一條有前景的途徑。然而&#xff0c;現有的端到端自動駕駛系統通常采用主干網絡與多任務頭結合的方式&#xff0c;但是它們存在任務協調和系統復雜度高的問題。為此&#xff0c;本文提出了DiffAD&#xff0c;它統一了各種駕駛目標并…

整車CAN網絡和CANoe

車載網絡中主要包含有Can網絡,Lin網絡,FlexRay,Most,以太網。 500kbps:500波特率,表示的數據傳輸的速度。表示的是最大的網速傳輸速度。也就是每秒 500kb BodyCan車身Can InfoCan娛樂信息Can 車身CAN主要連接的是ESB電動安全帶 ADB自適應遠光燈等 PTCan動力Can 底盤Can

實戰設計模式之迭代器模式

概述 與上一篇介紹的解釋器模式一樣&#xff0c;迭代器模式也是一種行為設計模式。它提供了一種方法來順序訪問一個聚合對象中的各個元素&#xff0c;而無需暴露該對象的內部表示。簡而言之&#xff0c;迭代器模式允許我們遍歷集合數據結構中的元素&#xff0c;而不必了解這些集…

JVM 垃圾回收器是如何判斷一個對象是否要回收?

JVM 垃圾回收器&#xff08;Garbage Collector&#xff09;需要判斷哪些對象是“垃圾”&#xff0c;即不再被程序使用的對象&#xff0c;以便回收它們占用的內存。JVM 主要使用以下兩種方法來判斷對象是否是垃圾&#xff1a; 1. 引用計數算法 (Reference Counting): 原理&…

kali——httrack

目錄 前言 使用教程 前言 HTTrack 是一款運行于 Kali Linux 系統中的開源網站鏡像工具&#xff0c;它能將網站的頁面、圖片、鏈接等資源完整地下載到本地&#xff0c;構建出一個和原網站結構相似的離線副本。 使用教程 apt install httrack //安裝httrack工具 httrac…

kotlin函數類型

一 函數類型定義 1 定義 函數類型就是 (Int, Int) -> Int 函數類型其實就是將函數的 “參數類型” 和 “返回值類型” 抽象出來 2 示例 &#xff1a; (Int, Int) -> Int 表示接收兩個 Int 參數并返回 Int 的函數類型&#xff1b; (String) -> Unit 表示接收 Strin…

C# Winform 入門(9)之如何封裝并調用dll

封裝dll 首先創建 .Net平臺 類庫 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace _09.Encapsulation_dll {public class Program{/// <summary>/// 求兩個double類型的數值的和/// &l…

前后端分離下,Spring Boot 請求從發起到響應的完整執行流程

以下是前后端分離架構下&#xff0c;Spring Boot 請求從發起到響應的完整執行流程&#xff0c;結合你提出的所有問題&#xff0c;按真實執行順序和職責鏈條重新整理所有核心概念、結構、關鍵類、數據轉換點和典型代碼示例&#xff1a; 一、前端發起請求&#xff08;步驟1-2&…

基于sklearn實現文本摘要思考

和各位小伙伴分享一下使用sklearn進行文本摘要的思考。 第一版本 原理 提取式文本摘要的基本原理是&#xff1a; 將文本分割成句子 計算每個句子的重要性(權重) 選擇權重最高的幾個句子組成摘要 常用的句子權重計算方法&#xff1a; TF-IDF&#xff1a;基于詞頻-逆文檔頻…

OpenHarmony子系統開發 - DFX(三)

OpenHarmony子系統開發 - DFX&#xff08;三&#xff09; 五、HiTraceMeter開發指導 HiTraceMeter概述 簡介 HiTraceMeter在OpenHarmony中&#xff0c;為開發者提供業務流程調用鏈跟蹤的維測接口。通過使用該接口所提供的功能&#xff0c;可以幫助開發者迅速獲取指定業務流…

2025年 能夠有效提升AI的生成質量和邏輯嚴謹性 的通用型系統提示

以下是三個經過精心設計的通用型系統提示&#xff08;System Prompt&#xff09;&#xff0c;能夠有效提升AI的生成質量和邏輯嚴謹性&#xff0c;適用于各類對話、分析和創作場景&#xff1a; Prompt 1 - 專家級分步驗證模式 你是一個具備跨領域知識整合能力的超級AI&#xff…

python爬蟲:小程序逆向實戰教程

根據我之前發表的文章&#xff0c;我們進行延伸實戰https://blog.csdn.net/weixin_64809364/article/details/146981598?spm1001.2014.3001.5501 1. 想要爬取什么小程序&#xff0c;我們進行搜索 2. 找到我們vx小程序的文件地址&#xff0c;我們就可以進行破解 破解步驟強看…

C語言變長數組(VLA)詳解:靈活處理動態數據的利器

引言 在C語言中&#xff0c;傳統的數組大小必須在編譯時確定&#xff0c;這限制了程序處理動態數據的靈活性。C99標準引入的變長數組&#xff08;Variable-Length Array, VLA&#xff09; 打破了這一限制&#xff0c;允許數組長度在運行時動態確定。本文將深入解析VLA的語法、…

串口數據轉換為IP數據

串口數據轉換為IP數據是一種常見的通信技術,用于將傳統的串行設備(如傳感器、控制器等)接入現代的IP網絡。以下是詳細介紹: 1. 轉換原理 串口數據轉換為IP數據的過程涉及硬件和軟件的結合,核心是將串行數據封裝為TCP/IP或UDP/IP數據包,通過網絡傳輸。具體步驟如下: 硬…