Python Opencv實現單目標檢測的示例程式碼
阿新 • • 發佈:2020-09-10
一 簡介
目標檢測即為在影象中找到自己感興趣的部分,將其分割出來進行下一步操作,可避免背景的干擾。以下介紹幾種基於opencv的單目標檢測演算法,演算法總體思想先儘量將目標區域的畫素值全置為1,背景區域全置為0,然後通過其它方法找到目標的外接矩形並分割,在此選擇一張前景和背景相差較大的圖片作為示例。
環境:python3.7 opencv4.4.0
二 背景前景分離
1 灰度+二值+形態學 輪廓特徵和聯通元件
根據影象前景和背景的差異進行二值化,例如有明顯顏色差異的轉換到HSV色彩空間進行分割。
1 原圖
2 灰度化
3 二值化
4 形態學處理
5 提取輪廓並找出目標外接矩形
程式碼封裝:
def get_roi_contours(image_path,morph_size,num_morph): ''' 引數詳解: image_path:所需處理圖片路徑 morph_size:形態學處理核的大小 num_morph:進行形態學處理的次數 ''' image = cv2.imread(image_path,cv2.IMREAD_COLOR) #灰度轉換 gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) #二值化 threhold,binary_image = cv2.threshold(gray_image,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) #形態學操作 kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT,ksize=morph_size) morph_image = cv2.morphologyEx(binary_image,cv2.MORPH_CLOSE,kernel) for i in range(num_morph-1): morph_image = cv2.morphologyEx(morph_image,kernel) #查詢輪廓 contours,hierarchy = cv2.findContours(morph_image,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) #選取輪廓面積最大的輪廓 area = 0 max_area_index = 0 for j in range(len(contours)): if area < cv2.contourArea(contours[j]): max_area_index = j area = cv2.contourArea(contours[j]) rect = cv2.boundingRect(contours[max_area_index]) return rect
6 通過聯通元件找到外接矩形
程式碼封裝:
def get_roi_ConCom(image_path,kernel) #聯通元件查詢 numlabels,components_img,stats,centers = cv2.connectedComponentsWithStats(morph_image,8) #獲取除背景外的所有聯通元件 stats_without_back = stats[1:] #獲取除背景外的所有聯通元件的面積最大值 max_area = np.max(stats_without_back,axis=0)[-1] #獲取面積最大聯通元件的index max_area_index = stats_without_back[:,-1]==max_area rect = stats_without_back[max_area_index] return np.squeeze(rect)[0:4]
2 Kmeans聚類實現前景和背景的分離
1 kmeans聚類後的影象,由於簇的中心是隨機初始化的,所以目標的畫素值可能為0,也可能為1,若採用opencv的findContours則要求前景畫素值為1。
2 利用輪廓特徵找外接矩形
由於Kmeans隨機初始化簇中心導致前景目標畫素不確定,採用邊緣提取的方法再查詢輪廓。
邊緣圖:
程式碼封裝:
def get_roi_Kmeans(image_path): image = cv2.imread(image_path,cv2.IMREAD_COLOR) image_data = image.reshape(-1,3).astype(np.float32) #必須要轉成浮點型別進行計算 #簇內平方和,標籤和每個簇的中心 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT,10,1) interia,label,centers = cv2.kmeans(image_data,2,None,criteria,5,cv2.KMEANS_RANDOM_CENTERS) #二值化,將標籤為0的轉換為255,即是目標 label[label==0] = 255 label[label==1] = 0 #轉換資料型別,輪廓查詢要是uint8型別資料 thresh_img = label.reshape(image.shape[0:2]).astype(np.uint8) x_grad = cv2.Sobel(thresh_img,cv2.CV_32F,1,0) y_grad = cv2.Sobel(thresh_img,1) x_grad = cv2.convertScaleAbs(x_grad) #ax + b 線性變換 y_grad = cv2.convertScaleAbs(y_grad) dst = cv2.add(x_grad,y_grad,dtype=cv2.CV_16S) #將兩種sobel的加起來就可以得到整個邊緣 dst = cv2.convertScaleAbs(dst) plt.imshow(dst,cmap='gray') #輪廓查詢目標必須為1 contours,hierarchy = cv2.findContours(dst,cv2.CHAIN_APPROX_SIMPLE) #獲取外接矩形 rect = cv2.boundingRect(contours[0]) return rect
三 總結
單目標檢測較為簡單,只要合理利用目標和背景的差異便可將其分離出來。當然單目標檢測的方法還有很多,比如有目標模板的時候可以採用模板匹配或者均值漂移,有足夠的資料集時也可採用機器學習和深度學習方法。
到此這篇關於Python Opencv實現單目標檢測的示例程式碼的文章就介紹到這了,更多相關Opencv 單目標檢測內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!