第四章 深度估計和分割python
1 捕獲深度攝像頭的幀算法
深度圖 灰度 每一個像素都是攝像頭到物體表面的距離 毫米windows
點雲圖 彩色 每種顏色對應一個維度空間 米數組
視差圖 灰度 每一個像素表明物體表面的立體視差 近大遠小函數
有效深度掩模一個給定像素的深度信息是否有效ui
2 從視差圖中獲得掩模spa
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2016/12/1 10:16 # @Author : Retacn # @Site : 深度攝像頭數據的處理 # @File : depth.py # @Software: PyCharm __author__ = "retacn" __copyright__ = "property of mankind." __license__ = "CN" __version__ = "0.0.1" __maintainer__ = "retacn" __email__ = "zhenhuayue@sina.com" __status__ = "Development" import numpy as np #設備 CAP_OPENNI=900 CAP_OPENNI_ASUS=910 #通道(基於浮點數的距離) CAP_OPENNI_DEPTH_MAP=0 #會獲得bgr圖像 CAP_OPENNI_POINT_CLOUD_MAP=1 #XYZ CAP_OPENNI_DISPARITY_MAP=2 # CAP_OPENNI_DISPARITY_MAP_32F=3 CAP_OPENNI_VALID_DEPTH_MASK=4 CAP_OPENNI_BGR_IMAGE=5 CAP_OPENNI_GRAY_IMAGE=6 #生成掩模 def createMedianMask(disparityMap,#視差圖 validDepthMask,#有效深度掩模 rect=None):#矩形 if rect is not None: x,y,w,h=rect disparityMap=disparityMap[y:y+h,x:x+w] validDepthMask=validDepthMask[y:y+h,x:x+w] #獲得中值 median=np.median(disparityMap) #生成掩模,逐像素進行布爾操做 return np.where((validDepthMask==0) | (abs(disparityMap-median)<12),#值爲真假的數組,當有效視差與平均視差>=12,看做噪聲 1.0,#爲真時,數組相應元素爲該值 0.0)#爲假時,爲該值
3 對複製操做進行掩模orm
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2016/12/1 10:22 # @Author : Retacn # @Site : 矩形區域複製 # @File : rects.py # @Software: PyCharm __author__ = "retacn" __copyright__ = "property of mankind." __license__ = "CN" __version__ = "0.0.1" __maintainer__ = "retacn" __email__ = "zhenhuayue@sina.com" __status__ = "Development" import cv2 import numpy as np from Three import utils #對複製操做執行掩模 def copyRect(src, dst, srcRect, dstRect, mask=None,#掩模參數,掩模要和圖像有相同的通道數 interpolation=cv2.INTER_LINEAR):#插值方法爲線性插值 x0,y0,w0,h0=srcRect x1,y1,w1,h1=dstRect #若是掩模爲空,則執行復制操做 if mask is None: dst[y1:y1+h1,x1:x1+w1]=cv2.resize(src[y0:y0+h0,y0:y0+h0],#源圖像 (w1,h1),#目標圖像 interpolation=interpolation)#插值方法 else: #若是掩模爲單通道,則複製通道 if not utils.isGray(src): mask=mask.repeat(3).reshape(h0,w0,3) dst[y1:y1+h1,x1:x1+w1]=np.where(cv2.resize(mask,(w1,h1),interpolation=cv2.INTER_NEAREST), cv2.resize(src[y0:y0+h0,x0:x0+w0],(w1,h1),interpolation=interpolation), dst[y1:y1 + h1, x1:x1 + w1] ) #一組矩形的循環交換 def swqpRects(src,dst,rects,masks=None,interpolation=cv2.INTER_LINEAR): if dst is not src: dst[:]=src numRects=len(rects) if numRects<2: return if masks is None: masks=[None]*numRects x,y,w,h=rects[numRects-1] temp=src[y:y+h,x:x+w].copy() i=numRects-2 while i>=0: copyRect(src,dst,rects[i],rects[i+1],masks[i],interpolation) i-=1 copyRect(temp,dst,(0,0,w,h),rects[0],masks[numRects-1],interpolation)
4 使用普通攝像頭進行深試評估事件
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2016/12/1 11:40 # @Author : Retacn # @Site : 使用普通攝像頭進行深試估計 # @File : commonCamera2Depth.py # @Software: PyCharm __author__ = "retacn" __copyright__ = "property of mankind." __license__ = "CN" __version__ = "0.0.1" __maintainer__ = "retacn" __email__ = "zhenhuayue@sina.com" __status__ = "Development" import cv2 import numpy as np def update(val=0): stereo.setBlockSize(cv2.getTrackbarPos('window_size','disparity')) stereo.setUniquenessRatio(cv2.getTrackbarPos('uniquenessRatio','disparity')) stereo.setSpeckleWindowSize(cv2.getTrackbarPos('speckleWindowSize','disparity')) stereo.setSpeckleRange(cv2.getTrackbarPos('speckleRange','disparity')) stereo.setDisp12MaxDiff(cv2.getTrackbarPos('disp12MaxDiff','disparity')) print('computing disparity...') disp = stereo.compute(imgL, imgR).astype(np.float32) / 16.0 cv2.imshow('left', imgL) cv2.imshow('disparity', (disp - min_disp) / num_disp) if __name__=='__main__': windows_size=5 #一個匹配塊的大小,大於1的奇數 min_disp=16 #最小視差值 num_disp=192-min_disp #最大視差值和最小視差值的差 blockSize=windows_size uniquenessRatio=1 speckleRange=3 #每一個已鏈接部分的最大視差變化 speckleWindowSize=3 #平滑視差區域的最大窗口尺寸 disp12MaxDiff=200 P1=600 #控制視差圖平滑度有第一個參數 P2=2400#第二個參數,值越大視差圖越平滑 #讀入圖像 imgL=cv2.imread('../imgl.jpg') imgR=cv2.imread('../imgr.jpg') cv2.namedWindow('disparity') cv2.createTrackbar('speckleRange','disparity',speckleRange,50,update) cv2.createTrackbar('window_size','disparity',windows_size,21,update) cv2.createTrackbar('speckleWindowSize','disparity',speckleWindowSize,200,update) cv2.createTrackbar('uniquenessRatio','disparity',uniquenessRatio,50,update) cv2.createTrackbar('disp12MaxDiff','disparity',disp12MaxDiff,250,update) stereo=cv2.StereoSGBM_create(minDisparity=min_disp, numDisparities=num_disp, blockSize=blockSize, uniquenessRatio=uniquenessRatio, speckleRange=speckleRange, speckleWindowSize=speckleWindowSize, disp12MaxDiff=disp12MaxDiff, P1=P1, P2=P2) update() cv2.waitKey()
5 使用分水嶺和grabcut算法進行物體分割utf-8
A 使用brabcut進行前景檢測
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2016/12/2 11:17 # @Author : Retacn # @Site : 使用grubCut進行前景檢測 # @File : grabcutNew.py # @Software: PyCharm __author__ = "retacn" __copyright__ = "property of mankind." __license__ = "CN" __version__ = "0.0.1" __maintainer__ = "retacn" __email__ = "zhenhuayue@sina.com" __status__ = "Development" import cv2 import numpy as np import sys # 定義顏色 BLUE = [255, 0, 0] # rectangle color RED = [0, 0, 255] # PR BG GREEN = [0, 255, 0] # PR FG BLACK = [0, 0, 0] # sure BG WHITE = [255, 255, 255] # sure FG DRAW_BG = {'color': BLACK, 'val': 0} DRAW_FG = {'color': WHITE, 'val': 1} DRAW_PR_FG = {'color': GREEN, 'val': 3} DRAW_PR_BG = {'color': RED, 'val': 2} # 設置標誌位 rect = (0, 0, 1, 1) # 隔離對像矩形 drawing = False # 繪製標誌位 rectangle = False # 矩形繪製標誌 rect_over = False # 檢查隔離矩形是否繪製 rect_or_mask = 100 # 掩模模式 value = DRAW_FG # thickness = 3 # 畫筆寬度 # 自定義鼠標回調函數 def onmouse(event, x, y, flags, param): # 定義全局變量 global img, img2, drawing, value, mask, rectangle, rect, rect_or_mask, ix, iy, rect_over # 繪製隔離矩形 if event == cv2.EVENT_RBUTTONDOWN: # 鼠標右健按下,開始繪製矩形 rectangle = True ix, iy = x, y elif event == cv2.EVENT_MOUSEMOVE: # 鼠標移動事件 if rectangle == True: # 繪製矩形 img = img2.copy() cv2.rectangle(img, # 源圖像 (ix, iy), # 開始點 (x, y), # 結束點 BLUE, # 畫筆顏色 2) # 畫筆寬度 rect = (min(ix, x), min(iy, y), abs(ix - x), abs(iy - y)) rect_or_mask = 0 elif event == cv2.EVENT_RBUTTONUP: # 右鍵擡起 rectangle = False # 設置標誌位,矩形繪製完成 rect_over = True cv2.rectangle(img, (ix, iy), (x, y), BLUE, 2) rect = (min(ix, x), min(iy, y), abs(ix - x), abs(iy - y)) rect_or_mask=0 print('按下 n , 開始繪製') #繪製隔離圓形 if event==cv2.EVENT_LBUTTONDOWN: #左鍵按下 if rect_over==False: print("請先繪製圓形") else: drawing=True cv2.circle(img,(x,y),thickness,value['color'],-1) cv2.circle(mask,(x,y),thickness,value['color'],-1) elif event==cv2.EVENT_MOUSEMOVE: if drawing==True: cv2.circle(img, (x, y), thickness, value['color'], -1) cv2.circle(mask, (x, y), thickness, value['color'], -1) elif event==cv2.EVENT_LBUTTONUP: if drawing==True: drawing=False cv2.circle(img, (x, y), thickness, value['color'], -1) cv2.circle(mask, (x, y), thickness, value['color'], -1) if __name__ == '__main__': fileName = '../test1.jpg' img = cv2.imread(fileName) img2 = img.copy() mask = np.zeros(img.shape[:2], dtype=np.uint8) output = np.zeros(img.shape, np.uint8) # 定義輸入輸出窗口 cv2.namedWindow("output") cv2.namedWindow('input') #輸出窗口註冊鼠標事件 cv2.setMouseCallback('input', onmouse) cv2.moveWindow('input',img.shape[1]+10,90) print("操做指南:\n") print('使用鼠標右健在源圖像中繪製矩形\n') while(1): #顯示圖像 cv2.imshow('output',output) cv2.imshow('input',img) k=0xFF&cv2.waitKey(1) if k==27: #ESC鍵退出 break elif k==ord('0'):#繪製背景 print("左鍵繪製background標識區域 \n") value=DRAW_BG elif k==ord('1'):#繪製前景 print('左鍵繪製foreground標識區域 \n') value=DRAW_FG elif k==ord('2'): value=DRAW_PR_BG elif k == ord('3'): value = DRAW_PR_FG elif k==ord('s'):# 保存圖像 bar=np.zeros((img.shape[0],5,3),np.uint8) res=np.hstack((img2.bar,img,bar,output)) cv2.imwrite('grabcut_output.png',res) print('保存圖像') elif k==ord('r'):#重置 print('開始重置 \n') rect = (0, 0, 1, 1) drawing = False rectangle = False rect_or_mask = 100 rect_over = False value = DRAW_FG img = img2.copy() mask = np.zeros(img.shape[:2], dtype=np.uint8) output = np.zeros(img.shape, np.uint8) elif k == ord('n'): # 圖像截取 print(""" For finer touchups, mark foreground and background after pressing keys 0-3 and again press 'n' \n""") if (rect_or_mask == 0): # 設置掩模 bgdmodel = np.zeros((1, 65), np.float64) fgdmodel = np.zeros((1, 65), np.float64) cv2.grabCut(img2, mask, rect, bgdmodel, fgdmodel, 1, cv2.GC_INIT_WITH_RECT) rect_or_mask = 1 elif rect_or_mask == 1: # 設置掩模 bgdmodel = np.zeros((1, 65), np.float64) fgdmodel = np.zeros((1, 65), np.float64) cv2.grabCut(img2, mask, rect, bgdmodel, fgdmodel, 1, cv2.GC_INIT_WITH_MASK) mask2 = np.where((mask == 1) + (mask == 3), 255, 0).astype('uint8') output = cv2.bitwise_and(img2, img2, mask=mask2) cv2.destroyAllWindows()
B 使用分水嶺算法進行圖像分割
示例代碼以下:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2016/12/2 12:21 # @Author : Retacn # @Site : 使用分水嶺算法進行圖像分割 # @File : watershed.py # @Software: PyCharm __author__ = "retacn" __copyright__ = "property of mankind." __license__ = "CN" __version__ = "0.0.1" __maintainer__ = "retacn" __email__ = "zhenhuayue@sina.com" __status__ = "Development" import cv2 import numpy as np from matplotlib import pyplot as plt img =cv2.imread('../test1.jpg') gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #轉換爲灰度圖,設置閾值 ret,thresh=cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) kernel=np.ones((3,3),np.uint8) opening=cv2.morphologyEx(thresh,#源圖像 cv2.MORPH_OPEN, #開運算 kernel, #核 iterations=2)#迭代次數 #取得肯定的前景區域 sure_bg=cv2.dilate(opening,kernel,iterations=3) dist_transform=cv2.distanceTransform(opening,cv2.DIST_L2,5) ret,sure_fg=cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) sure_fg=np.uint8(sure_fg) unknown=cv2.subtract(sure_bg,sure_fg) ret,markers=cv2.connectedComponents(sure_fg) markers=markers+1 markers[unknown==255]=0 markers=cv2.watershed(img,markers) img[markers==-1]=[255,0,0] plt.imshow(img) plt.show()