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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【笔记】opencv图像轮廓 获得平均灰度值在原图上画轮廓 观察灰度图的分解

發布時間:2024/9/30 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【笔记】opencv图像轮廓 获得平均灰度值在原图上画轮廓 观察灰度图的分解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

調整大小:

image = cv2.resize(image,dst=None,fx=0.5,fy = 0.5,dsize=None) img = cv2.resize(img,dst=None,fx=0.5,fy = 0.5,dsize=None)

畫輪廓

獲得平均灰度值的辦法:

**

template = cv2.imread('pl2.jpg') #獲得灰度圖 template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) h, w = template_gray.shape[:2] # template_gray 為灰度圖 m = np.reshape(template_gray, [1, w*h]) mean = m.sum()/(w*h) # 圖像平均灰度值

發現使用template_gray.shape[2]會報錯,認為原因應該是灰度圖是二維的,shape只有圖像的尺寸,而無第三個通道數。

reshape函數:

numpy.arange(n).reshape(a, b) 依次生成n個自然數,并且以a行b列的數組形式顯示
mat (or array).reshape(c, -1) 必須是矩陣格式或者數組格式,才能使用 .reshape(c, -1) 函數, 表示將此矩陣或者數組重組,以 c行d列的形式表示
arr.shape # (a,b)
arr.reshape(m,-1) #改變維度為m行、d列 (-1表示列數自動計算,d= ab /m )
arr.reshape(-1,m) #改變維度為d行、m列 (-1表示行數自動計算,d= ab /m )
-1的作用就在此: 自動計算d:d=數組或者矩陣里面所有的元素個數/c, d必須是整數,不然報錯)mat (or array).reshape(c, -1) 必須是矩陣格式或者數組格式,才能使用 .reshape(c, -1) 函數, 表示將此矩陣或者數組重組,以 c行d列的形式表示
arr.shape # (a,b)
arr.reshape(m,-1) #改變維度為m行、d列 (-1表示列數自動計算,d= ab /m )
arr.reshape(-1,m) #改變維度為d行、m列 (-1表示行數自動計算,d= ab /m )
-1的作用就在此: 自動計算d:d=數組或者矩陣里面所有的元素個數/c, d必須是整數,不然報錯)

上面的代碼中reshape的第一個參數為1,可見它將矩陣轉化為一行,輸出m得到:
[[67 68 70 … 86 84 82]]
輸出平均灰度mean:
166.6545988023952

函數cv2.threshold()

這個函數有四個參數,第一個原圖像,第二個進行分類的閾值,第三個是高于(低于)閾值時賦予的新值,第四個是一個方法選擇參數,常用的有:
? cv2.THRESH_BINARY(黑白二值)示閾值的二值化操作,大于閾值使用maxval表示,小于閾值使用0表示
? cv2.THRESH_BINARY_INV(黑白二值反轉)表示閾值的二值化翻轉操作,大于閾值的使用0表示,小于閾值的使用最大值表示
? cv2.THRESH_TRUNC (得到的圖像為多像素值) 表示進行截斷操作,大于閾值的使用閾值表示,小于閾值的不變
? cv2.THRESH_TOZERO 表示進行化零操作,大于閾值的不變,小于閾值的使用0表示
? cv2.THRESH_TOZERO_INV 表示進行化零操作的翻轉,大于閾值的使用0表示,小于閾值的不變

將上面的參數0換成cv2.THRESH_TRUNC之后:

換成cv2.THRESH_BINARY_INV:

可見對于最后輪廓的提取并沒有什么影響。
將第三個參數由原來的255換成100:

255為白色,100為上面的灰色,如果換成0圖片變成一片黑:

template_thresh = cv2.threshold(template_gray, mean, 0,0)[1] cv2.imshow('template_thresh', template_thresh)


且可以看到輪廓也沒有被提取出來,可見第三個參數對于結果也很重要。

下面提取輪廓:

# 對模板圖片進行二值化 cv2.imshow("a",template_gray) template_thresh = cv2.threshold(template_gray, mean, 255,0)[1] cv2.imshow('template_thresh', template_thresh)# 輪廓檢測 cv2.RETR_EXTERNAL--檢測外側輪廓 contours, hierarchy = cv2.findContours(template_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # print(contours) # 輪廓繪制 res = cv2.drawContours(template.copy(), contours, -1, (0, 0, 255), 1) cv2.imshow('res', res) cv2.waitKey(0) cv2.destroyAllWindows()

cv2.findContours

注意cv2.findContours的返回值現在只有兩個,多寫會報錯。
counters是返回的輪廓
 findContours( InputArray image, int mode,int method, Point offset = Point());  
 第一個參數:
 image 8位單通道,所有非0值被處理為1,0值不變,也就是說灰度圖會被自動處理為二值圖,一般都是先處理為二值圖之后再作為參數使用
 第二個參數:
 RETR_LIST 從解釋的角度來看,這中應是最簡單的。它只是提取所有的輪廓,而不去創建任何父子關系。
RETR_EXTERNAL 如果你選擇這種模式的話,只會返回最外邊的的輪廓,所有的子輪廓都會被忽略掉。
RETR_CCOMP 在這種模式下會返回所有的輪廓并將輪廓分為兩級組織結構。
RETR_TREE 這種模式下會返回所有輪廓,并且創建一個完整的組織結構列表。它甚至會告訴你誰是爺爺,爸爸,兒子,孫子等
注意:后一個輪廓跟父子輪廓無關
第三個參數:
cv2.CHAIN_APPROX_NONE,,表示邊界所有點都會被儲存;而如果設為cv2.CHAIN_APPROX_SIMPLE 會壓縮輪廓,將輪廓上冗余點去掉,比如說四邊形就會只儲存四個角點。
之前上面代碼的運行結果:

將第三個參數cv2.CHAIN_APPROX_SIMPLE改為cv2.CHAIN_APPROX_NONE之后結果:

表示沒有看出什么差別。
返回的第一個參數:返回的輪廓(opencv4中取消了返回的原始圖像)
第二個參數:圖像的拓撲信息(輪廓層次)

該返回值返回的是一組輪廓信息,每個輪廓都是由若干個點所構成的。例如,contours[i]是第i個輪廓(下標從0開始),contours[i][j]是第i個輪廓內的第j個點。
返回值contours的type屬性是list類型,list的每個元素都是圖像的一個輪廓,用Numpy中的ndarray結構表示。
使用如下語句,可以獲取輪廓內第0個輪廓中具體點的位置屬性: print(contours[0])#打印第0個輪廓中的像素點

cv2.drawContours()

cv2.drawContours()被用來繪制輪廓。第一個參數是一張圖片,可以是原圖或者其他。第二個參數是輪廓,也可以說是cv2.findContours()找出來的點集,一個列表。第三個參數是對輪廓(第二個參數)的索引,當需要繪制獨立輪廓時很有用,若要全部繪制可設為-1。接下來的參數是輪廓的顏色和厚度。
(0,0,255)表示的是紅色,如果換成(0, 230, 255),可以看見顏色變成了淡黃
平均灰度值的獲得非常重要,即這句話:
template_thresh = cv2.threshold(template_gray, mean, 255,0)[1]
mean是平均灰度值。如果數值不對,無法提取輪廓,現在換成另一個數字150嘗試一下:(計算出來的數值是166)

可以看到旁邊出現了一些其他的輪廓,即并沒有正確框住輪廓。可見這個值對于結果非常重要。
完整代碼:

template = cv2.imread('pl2.jpg') template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) h, w = template_gray.shape[:2] # gray 為灰度圖 print(h) print(w)m = np.reshape(template_gray, [1, w*h]) mean = m.sum()/(w*h) # 圖像平均灰度值 print(mean) # 對模板圖片進行二值化 cv2.imshow("a",template_gray) template_thresh = cv2.threshold(template_gray, mean, 255,1)[1] cv2.imshow('template_thresh', template_thresh)# 輪廓檢測 cv2.RETR_EXTERNAL--檢測外側輪廓 contours, hierarchy = cv2.findContours(template_thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # print(contours) # 輪廓繪制 res = cv2.drawContours(template.copy(), contours, -1, (80, 45, 255), 1) #注意這里!!!cv2.imshow('res', res) cv2.waitKey(0) cv2.destroyAllWindows()

實例二:

img = cv2.imread("p7.jpg")gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,newi = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) hire,counters = cv2.findContours(newi,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) res = cv2.drawContours(img,hire,-1,(0,0,255),2) cv2.imshow("i",res)cv2.waitKey()


框矩形:
threshold函數的閾值設置非常重要,這里設置的是210

img = cv2.imread("pl2.jpg")gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,newi = cv2.threshold(gray,210,255,cv2.THRESH_BINARY)hire,counters = cv2.findContours(newi,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) x,y,w,h = cv2.boundingRect(hire[0]) box = np.array([[x,y],[x+w,y],[x+w,y+h],[x,y+h]]) res = cv2.drawContours(img,[box],-1,(0,0,255),2) cv2.imshow("i",img) cv2.imshow("it",res) cv2.waitKey()


另一種框矩形法:(不能用平均灰度,否則無法框出矩形)

最小矩形框

img = cv2.imread("pl2.jpg")gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) h, w = gray.shape[:2] # template_gray 為灰度圖 m = np.reshape(gray, [1, w*h]) mean = m.sum()/(w*h) # 圖像平均灰度值 t,newi = cv2.threshold(gray,185,255,cv2.THRESH_BINARY)cv2.imshow("io",newi) hire,counters = cv2.findContours(newi,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) rect = cv2.minAreaRect(hire[0]) print(rect) points = cv2.boxPoints(rect) points = np.int0(points) #取整 image = cv2.drawContours(img,[points],0,(0,0,255),2) cv2.imshow("i",img) cv2.imshow("it",image)


(選圖很重要,不然根本出不來)
由于原圖中本來就有紅色的邊框,故改閾值:
t,newi = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)
現在進行凸包操作:

rect = cv2.convexHull(hire[1]) print(rect) cv2.polylines(img,[rect],True,(0,255,255),2)


此時能完全剛好框住。如果不設置為0的話會發現沒有全部框住:

遍歷所有輪廓

由于圖有問題,畫的輪廓也有問題

img = cv2.imread("erode.png") t,newi = cv2.threshold(gray,245,255,cv2.THRESH_BINARY) hire,counters = cv2.findContours(newi,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) n = len(hire) countt=[] print(len(hire)) for i in range(n):#print('cc'+str(i),cv2.contourArea(hire[i]))temp = np.zeros(img.shape,np.uint8)countt.append(temp)countt[i] = cv2.drawContours(countt[i],hire,i,(0,255,255),2)cv2.imshow(str(i),countt[i])

換了一張圖測試,效果好多了:

灰度圖分解

效果:

其中7最接近原始圖像。第七位二進制值在八位二進制值中權值最高,與原圖相關度最高
代碼:

a = cv2.imread("p7.jpg",0)h,w = a.shape newpic =np.zeros((h,w,8),dtype=np.uint8) for i in range(8):newpic[:,:,i] = 2**i h = np.zeros((h,w,8),dtype=np.uint8) for i in range(8):h[:,:,i] = np.bitwise_and(a,newpic[:,:,i])mask = h[:,:,i]>0h[mask] = 255cv2.imshow(str(i),h[:,:,i])cv2.waitKey(0) cv2.destroyAllWindows()

newpic =np.zeros((h,w,8),dtype=np.uint8):用于提取各個位平面的提取矩陣,8表示有8個通道,八個通道分別用來提取灰度圖像的八個位位平面,newpic[:,:,0]用來提取灰度圖像的第0個位平面
mask = h[:,:,i]>0將h中大于0的值處理為邏輯真,h[mask]=255,將h中對應mask中邏輯值為真的位置上的值替換為255

只框超過一定大小的輪廓:

img = cv2.imread("shu.png")gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) h, w = gray.shape[:2] # template_gray 為灰度圖 ret,binaryimg = cv2.threshold(gray,100,255,cv2.THRESH_BINARY) countimg = [] contours,hierarchy = cv2.findContours(binaryimg,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) n = len(contours) for i in range(n):temp = np.zeros(img.shape, np.uint8)countimg.append(temp)if cv2.contourArea(contours[i]) > 20000:countimg[i] = cv2.drawContours(img.copy(),contours,i,(0,0,255),3)cv2.resize(countimg[i],dst=None,fx = 0.5,fy=0.5,dsize=None)cv2.imshow("conter"+str(i),countimg[i])

指定hsv范圍框白色物體

試了好多次hsv的值終于框出來了,取值也太難了吧。中途因為取值問題壓根無法獲得邊緣。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6aMVJq1E-1614539904373)(C:\Users\14172\AppData\Roaming\Typora\typora-user-images\image-20210301024314126.png)]

img = cv2.imread("shu.png")gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) h, w = gray.shape[:2] # template_gray 為灰度圖 ret,binaryimg = cv2.threshold(gray,100,255,cv2.THRESH_BINARY_INV) countimg = [] lowhsv = np.array([0,0,100]) highhsv = np.array([180,40,255]) mask = cv2.inRange(hsv,lowerb=lowhsv,upperb=highhsv) median = cv2.medianBlur(mask,5) cannypic = cv2.Canny(median,30,255) cv2.imshow("f",cannypic) #contours,hierarchy = cv2.findContours(binaryimg,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) contours,hierarchy = cv2.findContours(cannypic,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE) n = len(contours) print(n) for i in range(n):temp = np.zeros(img.shape, np.uint8)countimg.append(temp)if cv2.contourArea(contours[i]) > 10000:countimg[i] = cv2.drawContours(img.copy(),contours,i,(0,0,255),3)countimg[i] = cv2.resize(countimg[i],dst=None,fx = 0.5,fy=0.5,dsize=None)cv2.imshow("conter"+str(i),countimg[i])

總結

以上是生活随笔為你收集整理的【笔记】opencv图像轮廓 获得平均灰度值在原图上画轮廓 观察灰度图的分解的全部內容,希望文章能夠幫你解決所遇到的問題。

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