当前位置:   article > 正文

python、opencv 双目视觉测距代码_双目摄像头算深度代码

双目摄像头算深度代码

傻瓜版,拿个双目摄像头,标定,得到数据,填进去,调调参数。

两个部分,一个是相机的参数设置,一个是测距

运用matlab里面的stereo Camera Calibrator APP进行拍照

拍个30多张,然后拉线,留个10-20张进行计算,把双目摄像机的数据填到camera_configs.py里面

camera_configs.py如何填写:

在matlab中输入红色框框内的内容,得到相应的数据,依次填入

1、输入:stereoParams.CameraParameters1.IntrinsicMatrix,得到数据后填写时注意进行矩阵的转置

 

2、stereoParams.CameraParameters1.RadialDistortion  和  stereoParams.CameraParameters1.TangentialDistortion

3、stereoParams.CameraParameters2.IntrinsicMatrix,,得到数据后填写时注意进行矩阵的转置

4、stereoParams.CameraParameters2.RadialDistortion  和  stereoParams.CameraParameters2.TangentialDistortion

5、stereoParams.RotationOfCamera2

6、stereoParams

camera_configs.py

  1. import cv2
  2. import numpy as np
  3. left_camera_matrix = np.array([[ 745.7529, 0.1488, 344.5329],
  4. [0, 750.1008, 253.2383],
  5. [0., 0., 1.]])
  6. left_distortion = np.array([[0.2232, -1.2455, -0.0014, 0.0023, -0.2597]])
  7. right_camera_matrix = np.array([[ 734.8314, 1.0615, 336.2630],
  8. [ 0, 738.2798, 267.4528],
  9. [ 0, 0, 1.0000]])
  10. right_distortion = np.array([[0.3381, -2.4884, 0.0022, 0.0025,4.6913]])
  11. R = np.matrix([
  12. [ 1.0000, 0.0022, 0.0022],
  13. [-0.0022, 1.0000, 0.0088],
  14. [-0.0022, -0.0088, 1.0000],
  15. ])
  16. # print(R)
  17. T = np.array([-18.0133, 1.0184, 0.9606]) # 平移关系向量
  18. size = (640, 480) # 图像尺寸
  19. # 进行立体更正
  20. R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion,
  21. right_camera_matrix, right_distortion, size, R,
  22. T)
  23. # 计算更正map
  24. left_map1, left_map2 = cv2.initUndistortRectifyMap(left_camera_matrix, left_distortion, R1, P1, size, cv2.CV_16SC2)
  25. right_map1, right_map2 = cv2.initUndistortRectifyMap(right_camera_matrix, right_distortion, R2, P2, size, cv2.CV_16SC2)

 depth.py

  1. # 该脚本实现深度图以及点击深度图测量像素点的真实距离
  2. # 可以运行看到效果之后最好自己重新标定一次
  3. from cv2 import cv2
  4. import numpy as np
  5. import camera_configs # 摄像头的标定数据
  6. cam1 = cv2.VideoCapture(1) # 摄像头的ID不同设备上可能不同
  7. cam2 = cv2.VideoCapture(0) # 摄像头的ID不同设备上可能不同
  8. # cam1 = cv2.VideoCapture(1 + cv2.CAP_DSHOW) # 摄像头的ID不同设备上可能不同
  9. # cam1.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) # 设置双目的宽度
  10. # cam1.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 设置双目的高度
  11. # 创建用于显示深度的窗口和调节参数的bar
  12. cv2.namedWindow("depth")
  13. cv2.moveWindow("left", 0, 0)
  14. cv2.moveWindow("right", 600, 0)
  15. # 创建用于显示深度的窗口和调节参数的bar
  16. # cv2.namedWindow("depth")
  17. cv2.namedWindow("config", cv2.WINDOW_NORMAL)
  18. cv2.moveWindow("left", 0, 0)
  19. cv2.moveWindow("right", 600, 0)
  20. cv2.createTrackbar("num", "config", 0, 60, lambda x: None)
  21. cv2.createTrackbar("blockSize", "config", 30, 255, lambda x: None)
  22. cv2.createTrackbar("SpeckleWindowSize", "config", 1, 10, lambda x: None)
  23. cv2.createTrackbar("SpeckleRange", "config", 1, 255, lambda x: None)
  24. cv2.createTrackbar("UniquenessRatio", "config", 1, 255, lambda x: None)
  25. cv2.createTrackbar("TextureThreshold", "config", 1, 255, lambda x: None)
  26. cv2.createTrackbar("UniquenessRatio", "config", 1, 255, lambda x: None)
  27. cv2.createTrackbar("MinDisparity", "config", 0, 255, lambda x: None)
  28. cv2.createTrackbar("PreFilterCap", "config", 1, 65, lambda x: None) # 注意调节的时候这个值必须是奇数
  29. cv2.createTrackbar("MaxDiff", "config", 1, 400, lambda x: None)
  30. # 添加点击事件,打印当前点的距离
  31. def callbackFunc(e, x, y, f, p):
  32. if e == cv2.EVENT_LBUTTONDOWN:
  33. print(threeD[y][x])
  34. if abs(threeD[y][x][2]) < 3000:
  35. print("当前距离:"+str(abs(threeD[y][x][2])))
  36. else:
  37. print("当前距离过大或请点击色块的位置")
  38. cv2.setMouseCallback("depth", callbackFunc, None)
  39. # 初始化计算FPS需要用到参数 注意千万不要用opencv自带fps的函数,那个函数得到的是摄像头最大的FPS
  40. frame_rate_calc = 1
  41. freq = cv2.getTickFrequency()
  42. font = cv2.FONT_HERSHEY_SIMPLEX
  43. imageCount = 1
  44. while True:
  45. t1 = cv2.getTickCount()
  46. ret1, frame1 = cam1.read()
  47. ret1, frame2 = cam2.read()
  48. if not ret1:
  49. print("camera is not connected!")
  50. break
  51. # 这里的左右两个摄像头的图像是连在一起的,所以进行一下分割
  52. # frame1 = frame[0:480, 0:640]
  53. # frame2 = frame[0:480, 640:1280]
  54. ####### 深度图测量开始 #######
  55. # 立体匹配这里使用BM算法,
  56. # 根据标定数据对图片进行重构消除图片的畸变
  57. img1_rectified = cv2.remap(frame1, camera_configs.left_map1, camera_configs.left_map2, cv2.INTER_LINEAR,
  58. cv2.BORDER_CONSTANT)
  59. img2_rectified = cv2.remap(frame2, camera_configs.right_map1, camera_configs.right_map2, cv2.INTER_LINEAR,
  60. cv2.BORDER_CONSTANT)
  61. # 如有些版本 remap()的图是反的 这里对角翻转一下
  62. # img1_rectified = cv2.flip(img1_rectified, -1)
  63. # img2_rectified = cv2.flip(img2_rectified, -1)
  64. # 将图片置为灰度图,为StereoBM作准备,BM算法只能计算单通道的图片,即灰度图
  65. # 单通道就是黑白的,一个像素只有一个值如[123],opencv默认的是BGR(注意不是RGB), 如[123,4,134]分别代表这个像素点的蓝绿红的值
  66. imgL = cv2.cvtColor(img1_rectified, cv2.COLOR_BGR2GRAY)
  67. imgR = cv2.cvtColor(img2_rectified, cv2.COLOR_BGR2GRAY)
  68. out = np.hstack((img1_rectified, img2_rectified))
  69. for i in range(0, out.shape[0], 30):
  70. cv2.line(out, (0, i), (out.shape[1], i), (0, 255, 0), 1)
  71. cv2.imshow("epipolar lines", out)
  72. # 通过bar来获取到当前的参数
  73. # BM算法对参数非常敏感,一定要耐心调整适合自己摄像头的参数,前两个参数影响大 后面的参数也要调节
  74. num = cv2.getTrackbarPos("num", "config")
  75. SpeckleWindowSize = cv2.getTrackbarPos("SpeckleWindowSize", "config")
  76. SpeckleRange = cv2.getTrackbarPos("SpeckleRange", "config")
  77. blockSize = cv2.getTrackbarPos("blockSize", "config")
  78. UniquenessRatio = cv2.getTrackbarPos("UniquenessRatio", "config")
  79. TextureThreshold = cv2.getTrackbarPos("TextureThreshold", "config")
  80. MinDisparity = cv2.getTrackbarPos("MinDisparity", "config")
  81. PreFilterCap = cv2.getTrackbarPos("PreFilterCap", "config")
  82. MaxDiff = cv2.getTrackbarPos("MaxDiff", "config")
  83. if blockSize % 2 == 0:
  84. blockSize += 1
  85. if blockSize < 5:
  86. blockSize = 5
  87. # 根据BM算法生成深度图的矩阵,也可以使用SGBM,SGBM算法的速度比BM慢,但是比BM的精度高
  88. stereo = cv2.StereoBM_create(
  89. numDisparities=16 * num,
  90. blockSize=blockSize,
  91. )
  92. stereo.setROI1(camera_configs.validPixROI1)
  93. stereo.setROI2(camera_configs.validPixROI2)
  94. stereo.setPreFilterCap(PreFilterCap)
  95. stereo.setMinDisparity(MinDisparity)
  96. stereo.setTextureThreshold(TextureThreshold)
  97. stereo.setUniquenessRatio(UniquenessRatio)
  98. stereo.setSpeckleWindowSize(SpeckleWindowSize)
  99. stereo.setSpeckleRange(SpeckleRange)
  100. stereo.setDisp12MaxDiff(MaxDiff)
  101. # 对深度进行计算,获取深度矩阵
  102. disparity = stereo.compute(imgL, imgR)
  103. # 按照深度矩阵生产深度图
  104. disp = cv2.normalize(disparity, disparity, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
  105. # 将深度图扩展至三维空间中,其z方向的值则为当前的距离
  106. threeD = cv2.reprojectImageTo3D(disparity.astype(np.float32) / 16., camera_configs.Q)
  107. # 将深度图转为伪色图,这一步对深度测量没有关系,只是好看而已
  108. fakeColorDepth = cv2.applyColorMap(disp, cv2.COLORMAP_JET)
  109. cv2.putText(frame1, "FPS: {0:.2f}".format(frame_rate_calc), (30, 50), font, 1, (255, 255, 0), 2, cv2.LINE_AA)
  110. # 按下S可以保存图片
  111. interrupt = cv2.waitKey(10)
  112. if interrupt & 0xFF == 27: # 按下ESC退出程序
  113. break
  114. if interrupt & 0xFF == ord('s'):
  115. cv2.imwrite('images/left' +'.jpg', frame1)
  116. cv2.imwrite('images/right' +'.jpg', frame2)
  117. cv2.imwrite('images/img1_rectified' +'.jpg', img1_rectified)#畸变,注意观察正反
  118. cv2.imwrite('images/img2_rectified' +'.jpg', img2_rectified)
  119. cv2.imwrite('images/depth' +'.jpg', disp)
  120. cv2.imwrite('images/fakeColor' +'.jpg', fakeColorDepth)
  121. cv2.imwrite('mages/epipolar' + '.jpg', out)
  122. ####### 任务1:测距结束 #######
  123. # 显示
  124. # cv2.imshow("frame", frame) # 原始输出,用于检测左右
  125. cv2.imshow("frame1", frame1) # 左边原始输出
  126. cv2.imshow("frame2", frame2) # 右边原始输出
  127. cv2.imshow("img1_rectified", img1_rectified) # 左边矫正后输出
  128. cv2.imshow("img2_rectified", img2_rectified) # 右边边矫正后输出
  129. cv2.imshow("depth", disp) # 输出深度图及调整的bar
  130. cv2.imshow("fakeColor", fakeColorDepth) # 输出深度图的伪色图,这个图没有用只是好看
  131. # 需要对深度图进行滤波将下面几行开启即可 开启后FPS会降低
  132. img_medianBlur = cv2.medianBlur(disp, 25)
  133. img_medianBlur_fakeColorDepth = cv2.applyColorMap(img_medianBlur, cv2.COLORMAP_JET)
  134. img_GaussianBlur = cv2.GaussianBlur(disp, (7, 7), 0)
  135. img_Blur = cv2.blur(disp, (5, 5))
  136. cv2.imshow("img_GaussianBlur", img_GaussianBlur) # 右边原始输出
  137. cv2.imshow("img_medianBlur_fakeColorDepth", img_medianBlur_fakeColorDepth) # 右边原始输出
  138. cv2.imshow("img_Blur", img_Blur) # 右边原始输出
  139. cv2.imshow("img_medianBlur", img_medianBlur) # 右边原始输出
  140. t2 = cv2.getTickCount()
  141. time1 = (t2 - t1) / freq
  142. frame_rate_calc = 1 / time1
  143. cam1.release()
  144. cv2.destroyAllWindows()

如何判断数据有没有填对

 看矫正图,每根极线上对应的点是不是一样的。

可能问题:1.摄像头左右标反了、

   2. 如有些opencv版本 remap()的图是反的 这里对角翻转一下

    # img1_rectified = cv2.flip(img1_rectified, -1)

    # img2_rectified = cv2.flip(img2_rectified, -1)

 

     3.摄像头输出的是一张图还是两张图,这里的左右两个摄像头的图像是连在一起的,所以进行一下分割

    # frame1 = frame[0:480, 0:640]

    # frame2 = frame[0:480, 640:1280]

我的是两张图,所以这一段注释了

 

参数自己看着调,先调前面两个,前面两个出不了距离后面调了也没用

 

效果:

 在depth窗口点击进行测距

先这么写着,以后有时间再写具体的

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/152892?site
推荐阅读
相关标签
  

闽ICP备14008679号