OpenCV的輪廓檢測

1. 輪廓檢測的基本概念

輪廓是圖像中連續的、閉合的曲線段,代表物體的邊界(如圓形的輪廓是一條閉合曲線)。OpenCV 的輪廓檢測通過?cv2.findContours()?實現,可用于形狀識別、物體計數、圖像分割等場景。

2. 核心函數與參數

(1)cv2.findContours():檢測輪廓

contours, hierarchy = cv2.findContours(image,      # 輸入圖像(必須為二值圖,需提前灰度化+二值化)mode,       # 輪廓檢索模式(如RETR_EXTERNAL、RETR_TREE)method      # 輪廓逼近方法(如CHAIN_APPROX_SIMPLE、CHAIN_APPROX_NONE)
)

返回值

contours:檢測到的輪廓列表,每個輪廓是一個點的集合(ndarray?類型)。

hierarchy:輪廓的層次結構(如嵌套關系),若無需層次可忽略。

  • 參數說明mode(輪廓檢索模式):
    • 模式含義
      RETR_EXTERNAL僅檢測最外層輪廓(忽略內部嵌套的輪廓,適合簡單物體計數)。
      RETR_LIST檢測所有輪廓,但不建立層次關系(最快,適合無需嵌套分析的場景)。
      RETR_CCOMP檢測所有輪廓,組織為兩級結構(外層為連通域,內層為孔洞)。
      RETR_TREE檢測所有輪廓,并建立完整的樹狀層次(適合嵌套輪廓,如 “矩形內的圓形”)。
    • method(輪廓逼近方法):

      方法含義
      CHAIN_APPROX_NONE存儲輪廓的所有像素點(最詳細,速度慢、占用內存大)。
      CHAIN_APPROX_SIMPLE壓縮輪廓,僅保留關鍵頂點(如矩形僅存 4 個角點,速度快、內存小)。
      CHAIN_APPROX_TC89_L1使用 Teh-Chin 鏈逼近算法(適合曲線輪廓)。

(2)cv2.drawContours():繪制輪廓

cv2.drawContours(image,       # 要繪制輪廓的目標圖像contours,    # 輪廓列表(來自findContours的輸出)contourIdx,  # 要繪制的輪廓索引(-1表示繪制所有輪廓)color,       # 輪廓顏色(如(0,255,0)表示綠色)thickness=2, # 輪廓線寬度(-1表示“填充輪廓”)
)

3. 完整流程:從預處理到輪廓檢測

輪廓檢測對圖像質量敏感,需先進行預處理(灰度化、二值化、降噪)。以下是完整代碼示例:

import cv2
import numpy as np# 1. 讀取并預處理圖像
img = cv2.imread("shape.jpg")                # 讀取彩色圖像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度化
blur = cv2.GaussianBlur(gray, (5,5), 0)       # 高斯降噪(可選,視情況而定)
_, binary = cv2.threshold(blur, 127, 255, cv2.THRESH_BINARY)  # 二值化(>127設為255,否則0)# 2. 檢測輪廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE,       # 檢測所有輪廓并建立樹狀層次cv2.CHAIN_APPROX_SIMPLE  # 壓縮輪廓,保留關鍵頂點
)# 3. 繪制輪廓(綠色,線寬2)
cv2.drawContours(img, contours, -1, (0,255,0), 2)  # 4. 顯示結果
cv2.imshow("Contours", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 關鍵注意事項

預處理必須到位
輪廓檢測要求輸入為二值圖像(僅有黑 / 白)。若原圖是彩色,需先轉灰度(cv2.COLOR_BGR2GRAY),再二值化(cv2.threshold);若有噪聲,可先高斯模糊(cv2.GaussianBlur)。

版本兼容性:

OpenCV 2 返回?(contours, hierarchy)(2 個值);

OpenCV 3/4 返回?(img, contours, hierarchy)(3 個值)。

若代碼需兼容多版本,可按以下方式處理:

ret = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if len(ret) == 3:img, contours, hierarchy = ret  # OpenCV 3/4
else:contours, hierarchy = ret       # OpenCV 2

輪廓篩選與分析

若需篩選特定輪廓(如面積最大的輪廓),可遍歷?contours?并計算面積:

max_area = 0
max_contour = None
for cnt in contours:area = cv2.contourArea(cnt)if area > max_area:max_area = areamax_contour = cnt

5. 應用場景形狀識別

通過輪廓的周長、面積、近似多邊形(cv2.approxPolyDP)判斷形狀(如矩形、圓形)。

物體計數:統計圖像中輪廓的數量(需配合RETR_EXTERNAL排除內部孔洞)。

圖像分割:用輪廓包圍區域,提取目標物體。

6.實例:

import cv2
phone =cv2.imread('phone.png')#波收頗圖
phone_gray =cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)
cv2.imshow('phone_gray',phone_gray)
cv2.waitKey(0)
ret, phone_binary= cv2.threshold(phone_gray, 120, 255,cv2.THRESH_BINARY)
cv2.imshow( 'phone_binary',phone_binary)
cv2.waitKey(0)
_,contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)image_copy = phone.copy()
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1,color=(0,255,0),thickness=4)
cv2.imshow('Contours_show',image_copy)
cv2.waitKey(0)# cv2.contourArea(contour[, oriented]) -> retval  輪廓面積
# oriented: 定向區域標志,默認值為 False,返回面積的絕對值,True 時則根據輪廓方向返回帶符號的數值area_0 = cv2.contourArea(contours[0])
print(area_0)
area_1 = cv2.contourArea(contours[1])
print(area_1)# arcLength(InputArray curve, bool closed)  輪廓周長
# curve: 輸入的二維點集(輪廓頂點),可以是 vector 或 Mat 類型。
# closed: 用于指示曲線是否封閉。length = cv2.arcLength(contours[0], closed=True)
print(length)# 根據面積篩選顯示輪廓
a_list = []
for i in contours:if cv2.contourArea(i) > 10000:a_list.append(i)image_copy = phone.copy()
image_copy = cv2.drawContours(image=image_copy, contours=a_list, contourIdx=-1, color=(0, 255, 0), thickness=3)
cv2.imshow('Contours_show_10000', image_copy)
cv2.waitKey(0)# '''輪廓定位方法 根據輪廓面積進行排序'''
sortcnt = sorted(contours, key=cv2.contourArea, reverse=True)[0]  # 選取最大面積的輪廓
image_contours = cv2.drawContours(phone.copy(), contours=[sortcnt], contourIdx=-1, color=(0, 0, 255), thickness=3) # 繪制輪廓
cv2.imshow('image_contours', image_contours)
cv2.waitKey(0)

這段代碼是基于 OpenCV 的圖像輪廓檢測與分析示例,主要實現了從圖像讀取、預處理到輪廓提取、篩選和排序的完整流程。以下是代碼解析:

1. 導入庫與讀取圖像

import cv2
phone = cv2.imread('phone.png')  # 讀取原始圖像(假設為手機相關圖像)

導入 OpenCV 庫(cv2),用于圖像處理。

使用cv2.imread()讀取本地圖像phone.png,返回的phone是 BGR 格式的彩色圖像(OpenCV 默認讀取格式)。

2. 圖像預處理(灰度化與二值化)

# 灰度化:將彩色圖像轉為單通道灰度圖
phone_gray = cv2.cvtColor(phone, cv2.COLOR_BGR2GRAY)
cv2.imshow('phone_gray', phone_gray)  # 顯示灰度圖
cv2.waitKey(0)  # 等待用戶按鍵(0表示無限等待)# 二值化:將灰度圖轉為黑白二值圖(輪廓檢測的前提)
ret, phone_binary = cv2.threshold(phone_gray, 120, 255, cv2.THRESH_BINARY)
cv2.imshow('phone_binary', phone_binary)  # 顯示二值圖
cv2.waitKey(0)

灰度化:通過cv2.cvtColor()將 BGR 彩色圖轉為灰度圖(單通道),減少計算量,為后續處理簡化圖像。

二值化:使用cv2.threshold()將灰度圖轉為黑白二值圖:

閾值設為 120,即灰度值 > 120 的像素設為 255(白色),≤120 的設為 0(黑色)。cv2.THRESH_BINARY是二值化模式,返回ret(閾值)和二值化結果phone_binary

cv2.imshow()cv2.waitKey(0)用于顯示圖像并暫停,等待用戶確認后繼續。

3. 輪廓檢測與繪制

# 檢測輪廓(OpenCV 3/4版本返回3個值,用_忽略第一個)
_, contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# 復制原始圖像,在副本上繪制所有輪廓
image_copy = phone.copy()
cv2.drawContours(image=image_copy, contours=contours,  # 輪廓列表contourIdx=-1,      # -1表示繪制所有輪廓color=(0,255,0),    # 輪廓顏色(綠色,BGR格式)thickness=4         # 輪廓線寬
)
cv2.imshow('Contours_show', image_copy)  # 顯示所有輪廓
cv2.waitKey(0)

輪廓檢測cv2.findContours()從二值圖中提取輪廓:

輸入:二值圖phone_binary(背景為黑,目標為白)。

參數cv2.RETR_TREE:檢測所有輪廓,并保留完整的層次關系(如嵌套輪廓的父子關系)。

參數cv2.CHAIN_APPROX_NONE:存儲輪廓的所有像素點(不壓縮,最完整但內存占用大)。

返回:contours(輪廓列表,每個輪廓是像素坐標的數組)、hierarchy(輪廓層次信息)。

繪制輪廓cv2.drawContours()在圖像副本上繪制輪廓,避免修改原圖。

4. 輪廓特征計算(面積與周長)

# 計算輪廓面積(第一個和第二個輪廓)
area_0 = cv2.contourArea(contours[0])
print(area_0)  # 打印第一個輪廓的面積
area_1 = cv2.contourArea(contours[1])
print(area_1)  # 打印第二個輪廓的面積# 計算輪廓周長(第一個輪廓,閉合輪廓)
length = cv2.arcLength(contours[0], closed=True)
print(length)  # 打印第一個輪廓的周長

輪廓面積cv2.contourArea(contour)計算單個輪廓的面積(單位:像素 2)。

輪廓周長cv2.arcLength(curve, closed)計算輪廓周長:closed=True表示輪廓是閉合的(如圓形、矩形)。

5. 按面積篩選輪廓

# 篩選面積>10000的輪廓(去除小面積噪聲)
a_list = []
for i in contours:if cv2.contourArea(i) > 10000:a_list.append(i)# 繪制篩選后的輪廓
image_copy = phone.copy()
image_copy = cv2.drawContours(image=image_copy, contours=a_list,  # 僅包含大面積輪廓的列表contourIdx=-1, color=(0, 255, 0), thickness=3
)
cv2.imshow('Contours_show_10000', image_copy)  # 顯示篩選結果
cv2.waitKey(0)

實際場景中,檢測到的輪廓可能包含噪聲(如小斑點),通過面積閾值(10000)篩選出有意義的大輪廓。

遍歷所有輪廓,將面積大于 10000 的輪廓存入a_list,再繪制這些輪廓。

6. 按面積排序并提取最大輪廓

# 按面積降序排序輪廓,取最大面積的輪廓
sortcnt = sorted(contours, key=cv2.contourArea, reverse=True)[0]# 繪制最大面積的輪廓(紅色)
image_contours = cv2.drawContours(phone.copy(), contours=[sortcnt],  # 注意:contours參數需傳入列表,這里用[sortcnt]包裝contourIdx=-1, color=(0, 0, 255),  # 紅色(BGR格式)thickness=3
)
cv2.imshow('image_contours', image_contours)  # 顯示最大輪廓
cv2.waitKey(0)

sorted(contours, key=cv2.contourArea, reverse=True):按輪廓面積降序排序,reverse=True表示從大到小。

[0]取排序后的第一個元素(面積最大的輪廓)。

繪制時,contours參數需傳入列表,因此用[sortcnt]包裝單個輪廓。

總結

這段代碼完整演示了輪廓檢測的典型流程:
讀取圖像 → 灰度化 → 二值化 → 檢測輪廓 → 分析輪廓特征(面積、周長) → 篩選 / 排序輪廓 → 可視化結果
核心目的是從圖像中提取目標的邊界(輪廓),并通過面積等特征篩選出感興趣的目標)。

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

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

相關文章

亞信安全亮相鴻蒙生態大會2025 攜手鴻蒙生態繪就萬物智聯新藍圖

8 月30 日,以 “新場景?新體驗” 為主題的鴻蒙生態大會 2025 在深圳福田會展中心隆重開幕。本次大會由全球智慧物聯網聯盟(GIIC)主辦、鴻蒙生態服務(深圳)有限公司承辦,旨在搭建全球鴻蒙生態伙伴的高層次交…

Linux內核進程管理子系統有什么第四十回 —— 進程主結構詳解(36)

接前一篇文章:Linux內核進程管理子系統有什么第三十九回 —— 進程主結構詳解(35) 本文內容參考: Linux內核進程管理專題報告_linux rseq-CSDN博客 《趣談Linux操作系統 核心原理篇:第三部分 進程管理》—— 劉超 《…

面試問題:進程和線程,編譯步驟,const,map和unordered_map,深入理解unordered_map

目錄 進程和線程的區別 const修飾指針(左邊內容,右邊指向) 1. const 修飾指針指向的內容(指向常量) 2. const 修飾指針本身(常量指針) 3. const 同時修飾指針本身和指向的內容(指向常量的常量指針&…

利用棒棒糖圖探索Office (US)的IMDB評分

利用棒棒糖圖探索Office (US)的IMDB評分 import numpy as np import pandas as pd import matplotlib.colors as mc import matplotlib.image as image import matplotlib.pyplot as pltfrom matplotlib.cm import ScalarMappable from matplotlib.lines import Line2D from m…

Zephyr如何注冊設備實例

設備樹 → 編譯期生成 → 運行時訪問 流程圖&#xff1a;Zephyr dev->config 工作流程設備樹 (.dts) ───────────────────────────── anx745139 {compatible "analogix,anx7451";reg <0x39>;reset-gpios <&gpio1 5 …

Spring Boot 日志框架選擇指南:Logback vs Log4j2

在 Spring Boot 應用中&#xff0c;您需要明確選擇一個日志框架 - ??不能同時使用兩種日志實現??。以下是關于 spring-boot-starter-log4j2和 spring-boot-starter-logging的全面比較和選擇建議&#xff1a;核心區別特性spring-boot-starter-log4j2(Log4j2)spring-boot-sta…

Axure科技感可視化原型案例:賦能設計與研發的寶藏資源

在當今數字化浪潮中&#xff0c;數據可視化已成為企業洞察市場、優化運營、快速決策不可或缺的工具。Axure&#xff0c;作為原型設計領域的領航者&#xff0c;憑借其強大的功能和豐富的資源&#xff0c;為數據可視化大屏的設計注入了科技活力與創新元素。本文將深入探討Axure科…

跨境電商賬號風控核心:IP純凈度與瀏覽器指紋的防護策略

對跨境電商從業者而言&#xff0c;賬號突然被封是常見卻令人頭痛的問題。即便嚴格遵守平臺規則、使用代理IP&#xff0c;賬號仍可能因風控策略而受限。這背后&#xff0c;IP純凈度與瀏覽器指紋識別是兩大常被忽視卻至關重要的技術因素。本文將從技術角度解析其原理&#xff0c;…

daily notes[7]

文章目錄perl notereferencesperl note A hash in perl can be initialized with array,for example: my %numbers ("one", 1, "two", 2); print $fruit_color{"one"}; it is wonderful that the hash can be sliced to result in an array …

WPF遷移avalonia之圖像處理(一)

從WPF遷移到avalonia中&#xff0c;對于圖像處理部分&#xff0c;在WPF常用System.Windows.Drawing中圖像處理元素&#xff0c;但是在開發avalonia應用時考慮跨平臺特性&#xff0c;則必須有對應的跨平臺替換方案。主要考慮Avalonia.Media.Imaging.Bitmap和SkiaSharp.SKBitmap …

242. 有效的字母異位詞| 349. 兩個數組的交集

242. 有效的字母異位詞 nums [0]*26 : 這行代碼創建了一個包含26個0的列表&#xff0c;這個列表通常用于計數或者作為某種映射的基礎&#xff0c;比如統計字符串中每個字母出現的次數&#xff08;假設只考慮小寫字母a-z&#xff09;。 ord() Python 中的一個內置函數&#x…

HTML第二課:塊級元素

HTML第二課&#xff1a;塊級元素塊級元素塊級元素 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang"zh-CN"> <head><meta http-equiv"Content-…

微論-突觸的作用賦能思考(可能是下一代人工智能架構的啟發式理論)

突觸智能&#xff1a;微觀結構與宏觀智慧的橋梁摘要&#xff1a;傳統人工智能模型&#xff0c;尤其是深度學習&#xff0c;將突觸簡單抽象為一個靜態的權重參數&#xff0c;這極大地簡化了生物計算的復雜性。本文受啟發于生物突觸的微觀功能&#xff0c;提出了一種新的智能架構…

ARM - GPIO 標準庫開發

一、STM32MP157AAA開發板套件介紹1.1 核心板 - 主板如圖所示&#xff1a;主板各部分介紹1.2 IO 拓展板如圖所示&#xff1a;IO拓展板各部分介紹開發板名稱&#xff08;硬件平臺&#xff09;&#xff1a;FS-MP1A主控制器&#xff1a;STM32MP157AAA3 Cortex-A7 * 2 Cortex-M4 -…

橙武低代碼:不僅僅是云SaaS,更是云端開發+本地部署的新范式

版權歸作者所有&#xff0c;轉載請注明出處。 一、低代碼的時代背景 在過去十年里&#xff0c;軟件研發模式經歷了巨大的演變。從傳統的瀑布開發&#xff0c;到敏捷、DevOps&#xff0c;再到如今的低代碼/無代碼平臺&#xff0c;研發效率和交付模式發生了根本性變化。低代碼的…

神經語言學視角:腦科學與NLP深層分析技術的交叉融合

引言&#xff1a;從“統計擬合”到“類人理解”——NLP的下一個范式近年來&#xff0c;以Transformer架構為核心的大型語言模型&#xff08;LLM&#xff09;在自然語言處理&#xff08;NLP&#xff09;領域取得了前所未有的成功 。它們能夠生成流暢的文本、回答復雜的問題&…

Coze源碼分析-工作空間-項目查詢-前端源碼

前言 本文將深入分析Coze Studio項目中用戶登錄后進入工作空間查看和管理項目的前端實現&#xff0c;通過源碼解讀來理解工作空間項目開發功能的架構設計和技術實現。Coze Studio采用了現代化的React TypeScript技術棧&#xff0c;結合微前端架構和模塊化設計&#xff0c;為用…

【系統架構師設計(9)】系統設計:結構化設計與面向對象設計

文章目錄一、核心思想&#xff1a;模塊化與對象化的設計哲學1、結構化設計的核心思想2、面向對象設計的核心思想3、兩種設計方法的本質區別二、結構化設計知識點1、設計階段2、設計原則3、 內聚類型&#xff08;從低到高&#xff09;耦合類型&#xff08;從低到高&#xff09;模…

還在從零開發AI應用?這個項目直接給你500個現成方案!!!

大家好&#xff0c;我是顧北&#xff0c;一名AI應用探索者&#xff0c;也是GitHub開源項目收集者。昨晚又在GitHub上瞎逛...咦&#xff0c;碰到了一個特別有意思的項目。說實話吧&#xff0c;作為一個天天折騰AI工具的人&#xff0c;見過的項目沒有一千也有八百了&#xff0c;但…

react+taro的使用整理

前言&#xff1a; 本文主要整理下我們跨段工具taro的具體使用方法與相關資料。 taro官網&#xff1a; 安裝及使用 | Taro 文檔 安裝&#xff1a; 全局腳手架安裝&#xff1a; npm install -g tarojs/cli 使用腳手架安裝我們的taro項目 taro init myApp 運行到不同小程序教…