我正在尝试从未经校准的立体摄像机生成实时深度图。我知道算法大致看起来像:
- 检测关键点(SURF,SIFT)
- 提取描述符(SURF,SIFT)
- 比较和匹配描述符(BruteForce,基于Flann的方法)
- 从这些对中找到基本垫(findFundamentalMat())
- stereoRectifyUncalibrated()
- StereoSGBM
我在这里找到此算法:3d reconstruction from 2 images without info about the camera
我也找到了类似的实现:Github 3d reconstruction project
以及本教程:Stereo 3D reconstruction with OpenCV using an iPhone camera.
在这三个资源的帮助下,我整理了一个测试实现:
# I size down the original frames
IMG_L = cv2.resize(IMG_L,(int(WINDOW_WIDTH/3),int(WINDOW_HEIGHT/3)))
IMG_R = cv2.resize(IMG_R,(int(WINDOW_WIDTH/3),int(WINDOW_HEIGHT/3)))
window_size = 15
left_matcher = cv2.StereoSGBM_create(
minDisparity=0,
numDisparities=16,
blockSize=11,
P1=8 * 3 * window_size ** 2,
P2=32 * 3 * window_size ** 2,
disp12MaxDiff=1,
uniquenessRatio=3,
speckleWindowSize=1,
speckleRange=1,
preFilterCap=63,
mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
)
right_matcher = cv2.ximgproc.createRightMatcher(left_matcher)
lmbda = 80000
sigma = 1.2
visual_multiplier = 1.0
wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=left_matcher)
wls_filter.setLambda(lmbda)
wls_filter.setSigmaColor(sigma)
displ = left_matcher.compute(IMG_L, IMG_R)
dispr = right_matcher.compute(IMG_R, IMG_L)
displ = np.int16(displ)
dispr = np.int16(dispr)
filteredImg = wls_filter.filter(displ, IMG_L, None, dispr) # important to put "imgL" here!!!
filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=0, alpha=255, norm_type=cv2.NORM_MINMAX);
filteredImg = np.uint8(filteredImg)
使用这段代码,我生成以下输出:Video
现在您可能会看到我的问题:
对于第一个问题,我需要一个好的解决方案来消除这种闪烁。有没有办法考虑以前的深度图?
对于第二个问题,我可能对应该采取的措施有所了解:我需要纠正我的立体图像(如算法描述所建议的那样)。为了校正这些图像,我需要使用SIFT或SURF。但是我读到SIFT和SURF太慢,无法实时运行,所以我可能需要其他解决方案吗?
在尝试优化程序之前,我将专注于第一个和第二个问题,因此您现在可以暂时忽略我的第三个问题。
感谢您的帮助:)
您对闪烁的问题有好运吗?我目前正在从事类似的实时视频视差图像采集项目,并且遇到了同样的问题。我得到的图像很整齐,但一直闪烁。
对于您问题的实时部分,可以对算法的几个部分进行修改以提高速度(尽管多数情况下以质量为代价)。例如,对于我来说,使用StereoBM而不是StereoSGBM可以不断提高我的帧率。至于图像质量以及预处理步骤,如果可能,您可能需要校准相机。这大大改善了块匹配输出。