(一)使用普通摄像头进行深度估计
-使用(普通)深度摄像头识别前景区域和背景区域-深度摄像头/立体图像。
-深度摄像头可以计算与摄像头的距离。
-极几何:属于立体视觉几何学,从同一物体的两张不同图像提取三维信息。跟踪从摄像头到图像上每个物体的虚线,然后在第二章图像做同样的操作,并根据同一个物体对应的交叉来计算距离。
视差图:灰度图像,该图像的每个像素值代表物体表面的立体视差。
立体视差:从不同视角观察同一场景得到的两张图像叠放在一起,感觉是两张不同的图像,针对两张图像中两个孪生物体之间任意一对相互对应的两个像素点,可以度量像素之间的距离。近距离的物体会产生较大的立体视差,远距离的就小一些
使用极几何计算视差图,对图像中检测到的不同深度的基本表示。-提取前景部分。
条件:在不同视角相同距离拍摄两幅图像,否则计算失败。
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__":
window_size = 5
min_disp = 16
num_disp = 192 - min_disp
blockSize = window_size
uniquenessRatio = 1
speckleRange = 3
speckleWindowSize = 3
disp12MaxDiff = 200
P1 = 600
P2 = 2400
imgL = cv2.imread("dep1.jpg")
imgR = cv2.imread("dep2.jpg")
cv2.namedWindow("disparity")
cv2.createTrackbar("speckleRange", "disparity", speckleRange, 50, update)
cv2.createTrackerbar("window_size", "disparity", window_size, 21, update)
cv2.createTrackerbar(
"speckleWindowSize", "disparity", speckleWindowSize, 200, update
)
cv2.createTrackerbar("uniquenessRatio", "disparity", uniquenessRatio, 50, update)
cv2.createTrackerbar("disp12MaxDiff", "disparity", disp12MaxDiff, 250, update)
stereo = cv2.StereoSGBM_create(
minDisparity=min_disp,
numDisparities=num_disp,
blockSize=window_size,
uniquenessRatio=uniquenessRatio,
speckleRange=speckleRange,
speckleWindowSize=speckleWindowSize,
disp12MaxDiff=disp12MaxDiff,
P1=P1,
P2=P2,
)
update()
cv2.waitKey()
(二)使用GrabCut进行前景检测
grabCut函数:
输入图像、掩码、矩形区域、背景/前景模型、迭代次数、grabCut初始化方式
img = cv2.imread("mouse.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, 50, 421, 378) # 用于被初始化的grabCut算法
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
# 进行分割
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype("uint8")
# 创建新的掩码,将原来掩码中值为2和0 的区域设置为0,其他区域设置为1
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("mouse.jpg"), cv2.COLOR_BGR2RGB))
plt.title("original"), plt.xticks([]), plt.yticks([])
plt.show()
(三)使用分水岭算法进行图像分割
cv2.morphologyEx函数:形态学操作类型——op参数:
img = cv2.imread("luole.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)
ret1, 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)
# 计算未知区域,即既不是前景也不是背景的区域。
ret2, markers = cv2.connectedComponents(sure_fg)
# 标记连通的前景
markers = markers + 1
# 增加标签数量
markers[unknown == 255] = 0
markers = cv2.watershed(img, markers)
# 使用Watershed算法标记图片
img[markers == -1] = [255, 0, 0]
plt.imshow(img)
plt.show()