双目测距项目
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

150 lines
6.8KB

  1. import cv2
  2. import numpy as np
  3. import time
  4. import math
  5. # -----------------------------------双目相机的基本参数---------------------------------------------------------
  6. # left_camera_matrix 左相机的内参矩阵
  7. # right_camera_matrix 右相机的内参矩阵
  8. #
  9. # left_distortion 左相机的畸变系数 格式(K1,K2,P1,P2,0)
  10. # right_distortion 右相机的畸变系数
  11. # -------------------------------------------------------------------------------------------------------------
  12. # 左镜头的内参,如焦距
  13. left_camera_matrix = np.array([[716.44292633, 0., 641.67188624], [0., 712.73240811, 321.80519519], [0., 0., 1.]])
  14. right_camera_matrix = np.array([[714.26431969, 0., 642.69117299], [0., 710.9244224, 329.27392689], [0., 0., 1.]])
  15. # 畸变系数,K1、K2、K3为径向畸变,P1、P2为切向畸变
  16. left_distortion = np.array([[-0.05928891, 0.12398536, -0.00180906, 0.00385613, -0.51151642]])
  17. right_distortion = np.array([[-0.0371133, -0.01211102, 0.00179116, 0.00457662, -0.13804965]])
  18. # 旋转矩阵
  19. R = np.array([[0.99907365, 0.00181788, -0.04299471],
  20. [-0.00210211, 0.99997623, -0.00656642],
  21. [0.04298175, 0.00665072, 0.99905372]])
  22. # 平移矩阵
  23. T = np.array([-59.57562815, -1.61493649, -1.71697302])
  24. size = (1280, 720)
  25. # 通过之前标定的数据计算相关参数,用于畸变矫正
  26. R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion,
  27. right_camera_matrix, right_distortion, size, R,
  28. T)
  29. # 校正查找映射表,将原始图像和校正后的图像上的点一一对应起来
  30. left_map1, left_map2 = cv2.initUndistortRectifyMap(left_camera_matrix, left_distortion, R1, P1, size, cv2.CV_16SC2)
  31. right_map1, right_map2 = cv2.initUndistortRectifyMap(right_camera_matrix, right_distortion, R2, P2, size, cv2.CV_16SC2)
  32. print(Q)
  33. # --------------------------鼠标回调函数---------------------------------------------------------
  34. # event 鼠标事件
  35. # param 输入参数
  36. # -----------------------------------------------------------------------------------------------
  37. def onmouse_pick_points(event, x, y, flags, param):
  38. if event == cv2.EVENT_LBUTTONDOWN:
  39. threeD = param
  40. print('\n像素坐标 x = %d, y = %d' % (x, y))
  41. # print("世界坐标是:", threeD[y][x][0], threeD[y][x][1], threeD[y][x][2], "mm")
  42. print("世界坐标xyz 是:", threeD[y][x][0] / 1000.0, threeD[y][x][1] / 1000.0, threeD[y][x][2] / 1000.0, "m")
  43. distance = math.sqrt(threeD[y][x][0] ** 2 + threeD[y][x][1] ** 2 + threeD[y][x][2] ** 2)
  44. distance = distance / 1000.0 # mm -> m
  45. print("距离是:", distance, "m")
  46. # 加载视频文件
  47. capture = cv2.VideoCapture(1)
  48. capture.set(cv2.CAP_PROP_FRAME_WIDTH, 2560)
  49. capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
  50. WIN_NAME = 'depth'
  51. cv2.namedWindow(WIN_NAME, cv2.WINDOW_AUTOSIZE)
  52. # 读取视频
  53. fps = 0.0
  54. ret, frame = capture.read()
  55. while capture.isOpened():
  56. # 开始计时
  57. t1 = time.time()
  58. # 是否读取到了帧,读取到了则为True
  59. ret, frame = capture.read()
  60. # 切割为左右两张图片
  61. frame1 = frame[0:720, 0:1280]
  62. frame2 = frame[0:720, 1280:2560]
  63. # 将BGR格式转换成灰度图片,用于畸变矫正
  64. imgL = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
  65. imgR = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
  66. # 重映射,就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。
  67. # 依据MATLAB测量数据重建无畸变图片,输入图片要求为灰度图
  68. img1_rectified = cv2.remap(imgL, left_map1, left_map2, cv2.INTER_LINEAR) # 这一步进行畸变矫正,得到畸变矫正后的图片
  69. img2_rectified = cv2.remap(imgR, right_map1, right_map2, cv2.INTER_LINEAR)
  70. # 转换为opencv的BGR格式
  71. imageL = cv2.cvtColor(img1_rectified, cv2.COLOR_GRAY2BGR)
  72. imageR = cv2.cvtColor(img2_rectified, cv2.COLOR_GRAY2BGR)
  73. # ------------------------------------SGBM算法----------------------------------------------------------
  74. # blockSize 深度图成块,blocksize越低,其深度图就越零碎,0<blockSize<10
  75. # img_channels BGR图像的颜色通道,img_channels=3,不可更改
  76. # numDisparities SGBM感知的范围,越大生成的精度越好,速度越慢,需要被16整除,如numDisparities
  77. # 取16、32、48、64等
  78. # mode sgbm算法选择模式,以速度由快到慢为:STEREO_SGBM_MODE_SGBM_3WAY、
  79. # STEREO_SGBM_MODE_HH4、STEREO_SGBM_MODE_SGBM、STEREO_SGBM_MODE_HH。精度反之
  80. # ------------------------------------------------------------------------------------------------------
  81. blockSize = 8
  82. img_channels = 3
  83. stereo = cv2.StereoSGBM_create(minDisparity=1,
  84. numDisparities=64,
  85. blockSize=blockSize,
  86. P1=8 * img_channels * blockSize * blockSize,
  87. P2=32 * img_channels * blockSize * blockSize,
  88. disp12MaxDiff=-1,
  89. preFilterCap=1,
  90. uniquenessRatio=10,
  91. speckleWindowSize=100,
  92. speckleRange=100,
  93. mode=cv2.STEREO_SGBM_MODE_HH)
  94. # 计算视差
  95. disparity = stereo.compute(img1_rectified, img2_rectified)
  96. # 归一化函数算法,生成深度图(灰度图)
  97. disp = cv2.normalize(disparity, disparity, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
  98. # 生成深度图(颜色图)
  99. dis_color = disparity
  100. dis_color = cv2.normalize(dis_color, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
  101. dis_color = cv2.applyColorMap(dis_color, 2)
  102. # 计算三维坐标数据值
  103. threeD = cv2.reprojectImageTo3D(disparity, Q, handleMissingValues=True)
  104. # 计算出的threeD,需要乘以16,才等于现实中的距离
  105. threeD = threeD * 16
  106. # 鼠标回调事件
  107. cv2.setMouseCallback("depth", onmouse_pick_points, threeD)
  108. # 完成计时,计算帧率
  109. fps = (fps + (1. / (time.time() - t1))) / 2
  110. frame = cv2.putText(frame, "fps= %.2f" % (fps), (0, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
  111. cv2.imshow("depth", dis_color)
  112. cv2.imshow("left", frame1)
  113. cv2.imshow('Deep disp', disp) # 显示深度图的双目画面
  114. # 若键盘按下q则退出播放
  115. if cv2.waitKey(1) & 0xff == ord('q'):
  116. break
  117. # 释放资源
  118. capture.release()
  119. # 关闭所有窗口
  120. cv2.destroyAllWindows()