`

opencv计算机视觉学习笔记三

 
阅读更多

第四章 深度估计和分割

1 捕获深度摄像头的帧

深度图 灰度 每个像素都是摄像头到物体表面的距离 毫米

点云图 彩色 每种颜色对应一个维度空间 米

视差图 灰度 每个像素代表物体表面的立体视差 近大远小

有效深度掩模一个给定像素的深度信息是否有效

2 从视差图中得到掩模

#!/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 对复制操作进行掩模

#!/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算法进行物体分割

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()
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics