赞
踩
SGBM双目测距是一种用于计算双目立体视觉的深度图的算法。双目立体视觉是一种通过两个摄像头(称为左目和右目)获取的图像来模拟人类双眼视觉的技术。通过计算左右两个摄像头之间的视差(即对应像素之间的水平位移),可以推断出场景中物体的深度信息。
SGBM算法是基于全局优化的立体视觉算法,它能够在一定程度上考虑像素点的全局一致性。以下是SGBM算法的主要步骤:
预处理:首先,对左右两个摄像头的图像进行预处理,包括去噪、图像矫正等操作,以便提高立体匹配的准确性。
特征提取:从左右两个图像中提取特征点,常用的特征点提取算法包括SIFT、SURF等。这些特征点通常具有良好的重复性和唯一性,可以用于进行匹配。
匹配代价计算:对于每个特征点,在右图像中搜索其在左图像中的匹配点。通过计算匹配代价来评估左右图像中像素点的相似度。常用的匹配代价计算方法包括灰度差异、视差一致性等。
代价聚合:将匹配代价沿着视差方向进行聚合,以捕捉像素点的全局一致性。常用的聚合方法包括代价聚合和代价累积。
视差优化:采用全局优化方法对代价聚合结果进行平滑和优化,以获得更准确的视差图。常用的优化方法包括动态规划、最小割/最大流等。
深度估计:通过视差值计算得到深度图,将每个像素点的视差值转换为物体到相机的距离。常用的深度估计方法包括三角测量、深度映射等。
主代码
- while True:
- # 开始计时
- t1 = time.time()
- # 是否读取到了帧,读取到了则为True
- ret, frame = capture.read()
- # 切割为左右两张图片
- frame1 = frame[0:720, 0:1280]
- frame2 = frame[0:720, 1280:2560]
- ############################################################################
- # 将BGR格式转换成灰度图片,用于畸变矫正
- imgL = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
- imgR = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
-
- # # 重映射,就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。
- # # 依据MATLAB测量数据重建无畸变图片,输入图片要求为灰度图
- img1_rectified = cv2.remap(imgL, left_map1, left_map2, cv2.INTER_LINEAR)
- img2_rectified = cv2.remap(imgR, right_map1, right_map2, cv2.INTER_LINEAR)
-
- # # 转换为opencv的BGR格式
- imageL = cv2.cvtColor(img1_rectified, cv2.COLOR_GRAY2BGR)
- imageR = cv2.cvtColor(img2_rectified, cv2.COLOR_GRAY2BGR)
- ############################################################################
- # ------------------------------------SGBM算法----------------------------------------------------------
- # blockSize 深度图成块,blocksize越低,其深度图就越零碎,0<blockSize<10
- # img_channels BGR图像的颜色通道,img_channels=3,不可更改
- # numDisparities SGBM感知的范围,越大生成的精度越好,速度越慢,需要被16整除,如numDisparities
- # 取16、32、48、64等
- # mode sgbm算法选择模式,以速度由快到慢为:STEREO_SGBM_MODE_SGBM_3WAY、
- # STEREO_SGBM_MODE_HH4、STEREO_SGBM_MODE_SGBM、STEREO_SGBM_MODE_HH。精度反之
- # ------------------------------------------------------------------------------------------------------
- num = cv2.getTrackbarPos("num", depthWinTitle)
- blockSize = cv2.getTrackbarPos("blockSize", depthWinTitle)
- img_channels = 3
- stereo = cv2.StereoSGBM_create(minDisparity=1,
- numDisparities=16 * num,
- blockSize=blockSize,
- P1=8 * img_channels * blockSize * blockSize,
- P2=32 * img_channels * blockSize * blockSize,
- disp12MaxDiff=-1,
- preFilterCap=1,
- uniquenessRatio=10,
- speckleWindowSize=100,
- speckleRange=100,
- mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY)
- #-----------------------生成视差图-------------------------------------
- # 计算视差
- disparity = stereo.compute(imageL, imageR)
-
- # 归一化函数算法,生成深度图(灰度图)
- disp = cv2.normalize(disparity, disparity, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
- # 生成深度图(颜色图)
- dis_color = disparity
- dis_color = cv2.normalize(dis_color, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
- dis_color = cv2.applyColorMap(dis_color, 2)
-
-
- # 计算三维坐标数据值
- threeD = cv2.reprojectImageTo3D(disparity, Q, handleMissingValues=True)
- # 计算出的threeD,需要乘以16,才等于现实中的距离
- threeD = threeD * 16
- # 鼠标回调事件
- cv2.setMouseCallback("depth", onmouse_pick_points, threeD)
-
- #完成计时,计算帧率
- fps = (fps + (1. / (time.time() - t1))) / 2
- frame = cv2.putText(frame, "fps= %.2f" % (fps), (0, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
-
- res=stackImages(0.5,[[frame1,frame2],[dis_color,disp]])
- cv2.imshow("depth", dis_color)
- cv2.imshow("res", res)
- cv2.imshow(WIN_NAME, disp) # 显示深度图的双目画面
- # 若键盘按下q则退出播放
- if cv2.waitKey(1) & 0xff == ord('q'):
- break
效果图:
视差图
深度图
点击深度图便可测量距离,(误差在1mm内)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。