日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python opencv轮廓提取_Python + Opencv2 实现轮廓提取,轮廓区域面积计算

發(fā)布時(shí)間:2024/4/19 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python opencv轮廓提取_Python + Opencv2 实现轮廓提取,轮廓区域面积计算 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

對(duì)圖像處理時(shí),會(huì)遇到這樣一個(gè)場(chǎng)景:找到圖像主體輪廓,這是其一,可能為了凸顯輪廓,需要用指定的顏色進(jìn)行標(biāo)記;輪廓標(biāo)記完可能任務(wù)還沒有結(jié)束,還需對(duì)輪廓所勾勒的像素面積區(qū)域統(tǒng)計(jì)計(jì)算。

本篇文章的主要內(nèi)容就是要解決上面場(chǎng)景遇到的三個(gè)問問題

找到圖像主題輪廓;

用指定顏色對(duì)源圖像進(jìn)行輪廓標(biāo)記;

計(jì)算輪廓中的主體;

實(shí)驗(yàn)環(huán)境配置為 Python + Opencv 3.4, 處理的圖像如下:

第一步,提取輪廓,Opencv 中的 findContours() 函數(shù) 可以直接提取輪廓,但對(duì)輸入圖像有一定要求

一,輸入的圖像必須是單通道,三通道不允許;

二,輸入的圖像數(shù)據(jù)類型需是 8UC1;否則程序會(huì)報(bào)錯(cuò)的,報(bào)錯(cuò)信息如下:

error: (-210) [start]FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function cvStartFindContours_Impl

解決方法,在讀取時(shí)加入下面這行代碼進(jìn)行數(shù)據(jù)格式轉(zhuǎn)換,同時(shí)解決上面兩個(gè)問題:

mat_img2 = cv2.imread(img_path,cv2.CV_8UC1)

三、輸入的圖像背景需是黑色的,否則輪廓提取失敗,就以本次圖像為例,如果直接提取效果如下:

圖片最外層是一層黑色部分,所以最終結(jié)果就是標(biāo)記最外層;對(duì)這類背景非黑色的圖片做輪廓提取時(shí),需要進(jìn)行預(yù)處理:把背景變?yōu)楹谏?/p>

提供一個(gè)簡(jiǎn)單辦法,閾值化處理:設(shè)定一個(gè)閾值 Threshold 和一個(gè)指定值 OutsideValue ,當(dāng)圖像中像素滿足某種條件(大于或小于設(shè)定的閾值時(shí)),像素值發(fā)生變化。

自適應(yīng)閾值化分割

這里用到的是 Opencv 提供的自適應(yīng)閾值分割算法,其函數(shù)格式為:

dst=cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)

src 需要分割的圖像( adarray 類型);

maxValue ,滿足條件是替換的像素值,等價(jià)于上面提到的 OutsideValue;

adaptiveMetheod: 自適應(yīng)閾值分割算法,Opencv 中提供兩種方法

1,ADAPTIVE_THRESH_MEAN_C : 最后的像素值 $T(x,y)$ 為原像素值 $(x,y)$ $blocksize*blocksize$ 區(qū)域像素的平均值 $C$;

2,ADAPTIVE_THRESH_GAUSSIAN_C : 最后像素值 $T(x,y)$ 為原像素值 $(x,y)$ 附近 $blocksize*blocksize$ 區(qū)域大小最小值 $C$;

thresholdType 閾值分割方法,Opencv 提供了5 種;

1,THRESH_BINARY:

$$

dst(x,y) = \left{

\begin{aligned}

maxval & &if\ src(x,y)>thresh\

0 & & otherwise\

\end{aligned}

\right.

$$

2,THRESH_BINARY_INV:

$$

dst(x,y) = \left{

\begin{aligned}

0 & &if\ src(x,y)>thresh\

maxval & & otherwise\

\end{aligned}

\right.

$$

3,THRESH_TRUNC:

$$

dst(x,y)=\left{

\begin{aligned}

threshold & & if\ src(x,y)>thresh\

src(x,y)& &otherwise\

\end{aligned}

\right.

$$

4,THRESH_TOZERO:

$$

dst(x,y)=\left{\begin{aligned}src(x,y) & & if\ src(x,y)>thresh\0& &otherwise\\end{aligned}\right.

$$

5,THRESH_TOZERO_INV;

$$

dst(x,y)=\left{\begin{aligned}0 & & if\ src(x,y)>thresh\src(x,y)& &otherwise\\end{aligned}\right.

$$

dst : 返回的閾值分割圖像(是 ndarray 類型)

下面這行代碼就是本次實(shí)驗(yàn)設(shè)置的參數(shù):

dst = cv2.adaptiveThreshold(mat_img2,210,cv2.BORDER_REPLICATE,cv2.THRESH_BINARY_INV,3,10)

自適應(yīng)閾值分割的結(jié)果:

輪廓提取

接下來就是進(jìn)行輪廓提取了,用到的函數(shù):

image, contours, hierarchy=cv2.findContours(image, mode, method)

image 返回的圖像,在 Opencv 4.0 之后就沒有這個(gè)參數(shù)了;

contours 標(biāo)記的輪廓,以 list 形式存在,每個(gè)輪廓中都包含了輪廓像素的坐標(biāo)向量;

hierarchy 表示輪廓的繼承關(guān)系,一般用不到;d

image 后面image 表示需要標(biāo)記輪廓的圖像,以 ndarray 格式存在;

mode 標(biāo)記輪廓的模式,Opencv 提供了4種;

1,RETR_EXTERNAL;只提取整體外部輪廓;

2,RETR_LIST; 提取所有輪廓,不需要建立任何繼承關(guān)系;

3, RETR_CCOMP ;提取所有輪廓,最后形成連個(gè)水平集,外面一個(gè),內(nèi)部一個(gè);

4, RETR_TREE ;提取所有輪廓,構(gòu)建等級(jí)關(guān)系(父子繼承關(guān)系)

method :輪廓近似點(diǎn)連接方式,例如一個(gè)長(zhǎng)方形,可以由數(shù)百個(gè)點(diǎn)連接而成,單節(jié)省內(nèi)存的方式就是找到四個(gè)角點(diǎn)即可;

其中前者為 CHAIN_APPROX_NONE 后者為 CHAIN_APPROX_SIMPLE

這里分別對(duì) mode 設(shè)置不同的參數(shù),一個(gè)設(shè)為 RETR_TREE (提取全部輪廓),一個(gè)設(shè)置 RETR_EXTRENAL (只提取最外部輪廓 );可以看一下提取輪廓效果:

RETR_TREE 結(jié)果:

RETR_EXTRENAL 結(jié)果:

是不是感受到了mode 不同導(dǎo)致輪廓的差距;一般只提取一個(gè)輪廓用 RETR_EXTRENAL,多個(gè)的話用 RETR_TREE;

輪廓標(biāo)記

對(duì)輪廓顏色繪制,用到 的函數(shù)

cv2.drawContours(image, contours, contourIdx, color,thickness)

image 繪制輪廓的圖像 ndarray 格式;

contours ,findContours 函數(shù)找到的輪廓列表;

contourIdx 繪制輪廓的索引數(shù),取整數(shù)時(shí)繪制特定索引的輪廓,為負(fù)值時(shí),繪制全部輪廓;

color 繪制輪廓所用到的顏色,這里需要提醒一下, 想使用 RGB 彩色繪制時(shí),必須保證 輸入的 image 為三通道,否則輪廓線非黑即白;

thickness ,用于繪制輪廓線條的寬度,取負(fù)值時(shí)將繪制整個(gè)輪廓區(qū)域;

以下就是分別取 thickness 為3(左)、-3(右) 繪制的結(jié)果

輪廓區(qū)域面積計(jì)算

最后計(jì)算輪廓面積,用到 cv2.contourArea(contour) 函數(shù),里面的參數(shù)指的就是計(jì)算的輪廓

area = 0

for i in contours:

area += cv2.contourArea(i)

print(area)

>>>16397.5 #最后結(jié)果

本篇文章用到的完整代碼如下:

import cv2

img_path = "E:/data_ceshi/images.jpg"

#讀取文件

mat_img = cv2.imread(img_path)

mat_img2 = cv2.imread(img_path,cv2.CV_8UC1)

#自適應(yīng)分割

dst = cv2.adaptiveThreshold(mat_img2,210,cv2.BORDER_REPLICATE,cv2.THRESH_BINARY_INV,3,10)

#提取輪廓

img,contours,heridency = cv2.findContours(dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

#標(biāo)記輪廓

cv2.drawContours(mat_img,contours,-1,(255,0,255),3)

#計(jì)算輪廓面積

area = 0

for i in contours:

area += cv2.contourArea(i)

print(area)

#圖像show

cv2.imshow("window1",mat_img)

cv2.waitKey(0)

總結(jié)

以上是生活随笔為你收集整理的python opencv轮廓提取_Python + Opencv2 实现轮廓提取,轮廓区域面积计算的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。