使用深度摄像头的数据来识别前景区域和背景区域,首先要有一个深度摄像头,比如微软的Kinect,英特尔的realsense。
RealSense不支持在OSX上运行
https://communities.intel.com/thread/109986
mac上配置解决方案
https://github.com/IntelRealSense/librealsense/blob/master/doc/installation_osx.md
深度相关通道的概念:
- 深度图:它是灰度图像,该图像的每个像素值都是摄像头到物体表面之间的距离的估计值,比如,CAPOPENNIDEPTH_MAP通道的图像给出了基于浮点数的距离,该距离以毫米为单位。
- 点云图:它是彩色图像,该图像的每种颜色都对应一个(x,y或z)维度空间,比如CAPOPENNIPOINTCLOUDMAP通道会得到BGR图像,从摄像头的角度来看,B对应x(蓝色是右边),G对应y(绿色是向上),R对应z(红色对应深度),这个值的单位是米。
- 视差图:它是灰度图像,该图像的每个像素值代表物体表面的立体视差,立体视差是指:假如将从不同视角观察同一场景得到的两张图像叠放在一起,这很可能让人感觉是两张不同的图像,在这个场景中,针对两张图像中两个孪生的物体之间任意一对相互对应的两个像素点,可以度量这些像素之间的距离,这个度量就是立体视差,近距离的物体会产生较大的立体视差,而远距离的就小一些,因此近距离的物体视差图会明亮一些。
- 有效深度掩模:它是表明一个给定的像素的深度信息是否有效(一个非零值表示有效,零值表示无效),比如,如果深度摄像头依赖于红外照明器(红外闪光灯),在灯光被遮挡的区域(阴影)的深度信息就为无效。
深度摄像头RealSense 的SDK
GitHub地址:https://github.com/IntelRealSense/librealsense(建议Window或Ubuntu)
使用普通摄像头进行深度估算
深度摄像头是极少在捕获图像时能估计物体与摄像头之间距离的设备,深度摄像头是如何得到深度信息的呢? 深度摄像头(比如微软的Kinect)将传统摄像头和一个红外传感器相结合来帮助摄像头区别相似物体并计算他们与摄像头之间的距离。
如何用realsensesdk,如何用Kinect
普通摄像头完成物体到摄像头之间的距离,极几何。极几何是如何工作的呢?它跟踪从摄像头到图像上每个物体的虚线,然后在第二张图片做同样的操作,并根据同一个物体对应的线交叉来计算距离。
OpenCV如何使用极几何来计算所谓的视差图?
视差图计算StereoSGBM
使用GrabCut进行前景检测
计算视差图对检测图像的前景很有用,(OpenCV)StereoSGBM主要是从二维图片中得到三维信息。
GrabCut算法的实现步骤为:
- 1.在图片中定义含有(一个或者多个)物体的矩形
- 2.矩形外的区域被自动认为是背景
- 3.对于用户定义的矩形区域,可用背景中的数据来区别它里面的前景和背景区域
- 4.用高斯混合模型来对背景和前景建模,并将未定义的像素标记为可能的前景或背景
- 5.图像中欧冠的每一个像素都被看作通过虚拟边与周围像素相连接,而每条边都有一个属于前景或背景的概率,这基于它与周围颜色上的相似性
- 6.每一个像素(即算法中的节点)会与一个前景或背景节点链接
- 7.在节点完成链接后,若节点之间的边属于不同终端,则会切断它们之间的边,这就能将图像各部分分割出来
import numpy as np
import cv2
from matplotlib import pyplot as plt
#使用分水岭和GrabCut算法进行物体分割
img = cv2.imread('images/statue_small.jpg')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (100,1,421,378)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
plt.subplot(121), plt.imshow(img)
plt.title("grabcut"), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(cv2.cvtColor(cv2.imread('images/statue_small.jpg'), cv2.COLOR_BGR2RGB))
plt.title("original"), plt.xticks([]), plt.yticks([])
plt.show()
使用分水岭算法进行图像分割
代码语言:javascript复制
#-*- coding=utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
#使用分水岭算法进行图像分割
img = cv2.imread('images/basil.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#将颜色转为灰度后,可为图像设一个阈值,将图像分为两部分:黑色部分和白色部分
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)
# noise removal 噪声去除,morphologyEx是一种对图像进行膨胀之后再进行腐蚀的操作
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
# sure background area 确定背景区域,图像进行膨胀操作
sure_bg = cv2.dilate(opening,kernel,iterations=3)
# Finding sure foreground area,通过distanceTransform来获取确定的前景区域
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)
# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers 1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0
markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]
plt.imshow(img)
plt.show()