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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

python-opencv 轮廓检测

發布時間:2023/11/27 生活经验 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python-opencv 轮廓检测 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

輪廓檢測

圖像處理中經常用到輪廓檢測,OpenCV-python接口中使用cv2.findContours()函數來查找檢測物體的輪廓。

import cv2img = cv2.imread('D:\\test\\contour.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,contours,-1,(0,0,255),3)cv2.imshow("img", img)
cv2.waitKey(0)

?

?

import cv2
import numpy as np
import math
import matplotlib.pyplot as plt# targetImg = cv2.imread('image/1.jpg')
targetImg = cv2.imread('image/1.jpg')
kernel_4 = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
HSV = cv2.cvtColor(targetImg, cv2.COLOR_BGR2HSV)  # 把BGR圖像轉換為HSV格式
Lower = np.array([0, 3, 5])  # 要識別顏色-紅色的下限    ## 0 5 5 10 255 255
Upper = np.array([10, 255, 255])  # 要識別的顏色-紅色的上限# mask是把HSV圖片中在顏色范圍內的區域變成白色,其他區域變成黑色
mask = cv2.inRange(HSV, Lower, Upper)
erosion = cv2.erode(mask, kernel_4, iterations=1)
erosion = cv2.erode(erosion, kernel_4, iterations=1)
dilation = cv2.dilate(erosion, kernel_4, iterations=1)
dilation = cv2.dilate(dilation, kernel_4, iterations=1)# target是把原圖中的非目標顏色區域去掉剩下的圖像
target = cv2.bitwise_and(targetImg, targetImg, mask=dilation)# 將濾波后的圖像變成二值圖像放在binary中
ret, binary = cv2.threshold(dilation, 127, 255, cv2.THRESH_BINARY)# 在binary中發現輪廓,輪廓按照面積從小到大排列
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# w_ = []
#
# for i in contours:  # 遍歷所有的輪廓
#         x1, y1, w, h = cv2.boundingRect(i)  # 將輪廓分解為識別對象的左上角坐標和寬、高
#         w_.append(w)
#         i = w_.index(max(w_))
# x, y, w, h = cv2.boundingRect(contours[i])# cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255,), 3)# cropped = targetImg[y - 150:y + 50, x - 80:x + 80]  # 裁剪坐標為[y0:y1, x0:x1]
# cv_cut_img_circle = cv2.imwrite("image2/cv_cut_img_circle.png", cropped)# print(x, y, w, h)
# cv2.imwrite('image/cv_cut_img_circle.png', cv_cut_img)  # 將畫上矩形的圖形保存到當前目錄
cv2.drawContours(targetImg, contours, -1, (0, 0, 255), 3)
cv2.imshow("img", targetImg)
cv2.imshow("mask", mask)
cv2.imshow("target", target)
cv2.imshow("erosion", erosion)
cv2.imshow("dilation", dilation)
cv2.waitKey()
# cv2.imshow("cv_cut_img_circle", cv_cut_img_circle)
# return cropped

?

?cv2.findContours()函數:

函數的原型為

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

返回兩個值:contours:hierarchy。

?參數

第一個參數是尋找輪廓的圖像;

第二個參數表示輪廓的檢索模式,有四種(本文介紹的都是新的cv2接口):
????cv2.RETR_EXTERNAL表示只檢測外輪廓
????cv2.RETR_LIST檢測的輪廓不建立等級關系
????cv2.RETR_CCOMP建立兩個等級的輪廓,上面的一層為外邊界,里面的一層為內孔的邊界信息。如果內孔內還有一個連通物體,這個物體的邊界也在頂層。
????cv2.RETR_TREE建立一個等級樹結構的輪廓。

第三個參數method為輪廓的近似辦法
????cv2.CHAIN_APPROX_NONE存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1
????cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點坐標,例如一個矩形輪廓只需4個點來保存輪廓信息
????cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
?

?返回值

?cv2.findContours()函數首先返回一個list,list中每個元素都是圖像中的一個輪廓,用numpy中的ndarray表示。這個概念非常重要。在下面drawContours中會看見。通過

print (type(contours))
print (type(contours[0]))
print (len(contours))

?hierarchy返回值

此外,該函數還可返回一個可選的hiararchy結果,這是一個ndarray,其中的元素個數和輪廓個數相同,每個輪廓contours[i]對應4個hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分別表示后一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號,如果沒有對應項,則該值為負數。

可以看出,hierarchy本身包含兩個ndarray,每個ndarray對應一個輪廓,每個輪廓有四個屬性。

print (type(hierarchy))
print (hierarchy.ndim)
print (hierarchy[0].ndim)
print (hierarchy.shape)

輪廓的繪制:OpenCV中通過cv2.drawContours在圖像上繪制輪廓

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])

?第一個參數是指明在哪幅圖像上繪制輪廓;
第二個參數是輪廓本身,在Python中是一個list。
第三個參數指定繪制輪廓list中的哪條輪廓,如果是-1,則繪制其中的所有輪廓。后面的參數很簡單。其中thickness表明輪廓線的寬度,如果是-1(cv2.FILLED),則為填充模式。繪制參數將在以后獨立詳細介紹。

?輪廓的極值點計算

pentagram = contours[1] #第二條輪廓是五角星leftmost = tuple(pentagram[:,0][pentagram[:,:,0].argmin()])
rightmost = tuple(pentagram[:,0][pentagram[:,:,0].argmin()])cv2.circle(img, leftmost, 2, (0,255,0),3) 
cv2.circle(img, rightmost, 2, (0,0,255),3) 

注意!假設輪廓有100個點,OpenCV返回的ndarray的維數是(100, 1, 2)!!!而不是我們認為的(100, 2)。切記!!!推薦《NumPy攻略:Python科學計算與數據分析》。

更新:關于pentagram[:,0]的意思

在numpy的數組中,用逗號分隔的是軸的索引。舉個例子,假設有如下的數組:

a = np.array([[[3,4]], [[1,2]],[[5,7]],[[3,7]],[[1,8]]])

?其shape是(5, 1, 2)。與我們的輪廓是相同的。那么a[:,0]的結果就是:

?[3,4], [1,2], [5,7], [3,7], [1,8]

?

這里a[:,0]的意思就是a[0:5,0],也就是a[0:5,0:0:2],這三者是等價的。
回頭看一下,a的shape是(5,1,2),表明是三個軸的。在numpy的數組中,軸的索引是通過逗號分隔的。同時冒號索引“:”表示的是該軸的所有元素。因此a[:, 0]表示的是第一個軸的所有元素和第二個軸的第一個元素。在這里既等價于a[0:5, 0]。

再者,若給出的索引數少于數組中總索引數,則將已給出的索引樹默認按順序指派到軸上。比如a[0:5,0]只給出了兩個軸的索引,則第一個索引就是第一個軸的,第二個索引是第二個軸的,而第三個索引沒有,則默認為[:],即該軸的所有內容。因此a[0:5,0]也等價于a[0:5,0:0:2]。

再詳細一點,a的全體內容為:[[[3,4]], [[1,2]],[[5,7]],[[3,7]],[[1,8]]]。去掉第一層方括號,其中有五個元素,每個元素為[[3,4]]這樣的,所以第一個索引的范圍為[0:5]。注意OpenCV函數返回的多維數組和常見的numpy數組的不同之處!

觀察[[3,4]],我們發現其中只有一個元素,即[3, 4],第二個索引為[0:1]。

再去掉一層方括號,我們面對的是[3,4],有兩個元素,所以第三個索引的范圍為[0:2]。

再次強調一下OpenCVPython接口函數返回的NumPy數組和普通的NumPy數組在組織上的不同之處。
?

?

參考書籍:

《圖像處理與計算機視覺算法及應用(第2版)?》

《Opencv2 Computer Vision Application Programming Cookbook》

《OpenCV References Manule》

OpenCV官方文檔Contour部分

參考blog:

https://blog.csdn.net/Darlingqiang/article/details/103595341

https://blog.csdn.net/sunny2038/article/details/12889059

https://blog.csdn.net/on2way/article/details/47028969

?

總結

以上是生活随笔為你收集整理的python-opencv 轮廓检测的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。