使用opencv分割影象(python實現)
阿新 • 來源:網路 • 發佈:2023-01-07
使用opencv分割影象(python實現)
- 概述
本人在做無人農機的時候需要進行影象處理,尋找目標物並進行分割,於是總結網路各種小車尋跡等等demo,自己也終於把影象顏色分割做的七七八八,特來記錄一下,留作以後參考。 - 過程
- 導包
import numpy as np
import cv2
- 讀取圖片(此處可以換成視訊流,具體可以百度一下,原理相同,都是對一幀圖片進行處理)
image = cv2.imread("C:/Users/92803/Downloads/1.jpg")
- 對想要的顏色進行二值化處理
lower_blue = np.array([100,43,46])
upper_blue = np.array([124,255,255])
imgHSV = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
cv_image = cv2.inRange(imgHSV,lower_blue,upper_blue)
#cv_image已經是二值矩陣了
首先,圖片從BGR格式轉為HSV格式,因為RGB格式的圖片在顯示上非常方便,但是對於影象處理HSV格式是比較常用的,具體可以檢視HSV格式和RGB格式的區別。
其次,cv2.inRange就是將HSV格式的影象進行二值化,在lower_blue和upper_blue之間的填充255,其餘的都填充0。
具體各種顏色的值參考以下圖片:

我以上填寫的是過濾藍色,填寫對應的值就可以了。
- 過濾之後發現還有一些噪點,於是接著對影象進行腐蝕和膨脹:
#對圖片進行腐蝕操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,10))
#這裡的引數是選擇卷積核的大小
cv_image = cv2.erode(cv_image,kernel)
#對圖片進行膨脹操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,10))
cv_image = cv2.dilate(cv_image,kernel)
- 如果對結果還不滿意,還可以對連通區域的面積進行過濾
contours,hie = cv2.findContours(cv_image,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
'''
呼叫函式發現影象中的連通區域,注意這裡opencv3返回的是三個引數即image,contours,hie
contours與hie一一對應,根據findContours尋找的模式,contours可以找到連通區域的所有點輪廓,轉折點輪廓等,此處是找所有點輪廓。
len(contours)返回的是連通區域的個數
'''
contours = np.array(contours,dtype=object)
#以上contours返回的是一個元組形式,轉為ndarray格式,方便處理
index = 0
for contour in contours:
area = cv2.contourArea(contour)
#呼叫函式,求取連通區域面積(畫素點個數)
if area < 10000:
#設定閾值
cv2.drawContours(cv_image,contour[np.newaxis,:],-1,(0,0,0),cv2.FILLED)
#對於面積小於10000畫素的連通區域,進行填充黑色(本來是白色)
contours = np.delete(contours,index)
#從contours 中刪除
index = index-1
#同時索引減1
index = index + 1
#自增1
for index,contour in enumerate(contours):
x,y,w,h = cv2.boundingRect(contour)
cv2.rectangle(cv_image,(x,y),(x+w,y+h),(139,35,35),5)
#對於面積大於等於10000連通區域在影象中畫出矩形
對於為什麼不放在一個for迴圈中,是因為有的連通預期畫出矩形之後,然後填充面積不符合的區域,可能會把畫的矩形框給擦除,所以分兩步進行處理。
- 顯示圖片
cv2.imshow("image",cv_image)
#這一步是必須的,不加會報錯
cv2.waitKey(0)
參考資料:
1: cv2.findContours()函式
2:OpenCV-清除小面積連通域
3:HSV基本顏色分量範圍
4:三分鐘帶你快速學習RGB、HSV和HSL顏色空間
5:cv2.inRange函式
----------------------------------------分割線-----------------------------------------------------------------------
- 對於以上的程式碼可能會發生錯誤核心修改程式碼如下:
#標記連通區域並刪除小區域的連通區域
cv_image,contours,hierarchy = cv2.findContours(image=cv_image,mode=cv2.RETR_LIST,method=cv2.CHAIN_APPROX_NONE)
if len(contours)!=0:
#contours = np.array(contours,dtype=cv2.UMat)
contours2 = ()
for contour in contours:
area = cv2.contourArea(contour)
if area< 10000:
cv2.drawContours(cv_image,tuple([contour]),-1,(0,0,0),cv2.FILLED)
#contours = np.delete(contours,index)
else:
contours2 = contours2 + tuple([contour])
for contour in contours2:
x,y,w,h = cv2.boundingRect(contour)
cv2.rectangle(cv_image,(x,y),(x+w,y+h),(139,35,35),5)
如果顯示的是灰度圖和ros進行轉換要注意引數的設定
self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "mono8"))
