当前位置:   article > 正文

realsense2+faster-rcnn+物体深度+物体宽度_关闭 enable_device_from_file

关闭 enable_device_from_file

pcl-python官方文档:

http://www.dabeaz.com/ply/ply.html

建议大家到官网下载,直接利用源代码安装
sudo python setup.py install
偷懒一点的朋友,也可以直接用apt安装,
sudo apt-get install python-ply

官方py文档:pyrealsense2

https://intelrealsense.github.io/librealsense/python_docs/_generated/pyrealsense2.html#module-pyrealsense2

dianyunxianshi:

https://github.com/dorodnic/binder_test/blob/master/pointcloud.ipynb

上一篇文章

https://blog.csdn.net/baidu_40840693/article/details/102918931

https://github.com/IntelRealSense/librealsense/tree/master/wrappers/python/examples

python -mpip install pyglet==1.3.0

python -mpip install pyrealsense2

python -mpip install pyntcloud

官方例子

https://github.com/IntelRealSense/librealsense/blob/jupyter/notebooks/depth_filters.ipynb

https://github.com/IntelRealSense/librealsense/blob/jupyter/notebooks/distance_to_object.ipynb

https://github.com/IntelRealSense/librealsense/tree/jupyter/notebooks

下载文件:

http://realsense-hw-public.s3.amazonaws.com/rs-tests/TestData/object_detection.bag

bag我没用上,因为bag是该设备保存的格式,代码中的

cfg.enable_device_from_file("../object_detection.bag")

是载入这个视频的意思,我们也可以保存,方式是

https://github.com/IntelRealSense/librealsense/issues/3029

  1. config = rs.config()
  2. config.enable_record_to_file('test.bag')


https://raw.githubusercontent.com/chuanqi305/MobileNet-SSD/f5d072ccc7e3dcddaa830e9805da4bf1000b2836/MobileNetSSD_deploy.prototxt


http://realsense-hw-public.s3.amazonaws.com/rs-tests/TestData/MobileNetSSD_deploy.caffemodel

例子:

  1. import cv2 # state of the art computer vision algorithms library
  2. import numpy as np # fundamental package for scientific computing
  3. import matplotlib.pyplot as plt # 2D plotting library producing publication quality figures
  4. import pyrealsense2 as rs # Intel RealSense cross-platform open-source API
  5. print("Environment Ready")
  6. # Setup:
  7. pipe = rs.pipeline()
  8. cfg = rs.config()
  9. #cfg.enable_device_from_file("../object_detection.bag")
  10. cfg.enable_stream(rs.stream.depth, 640, 360, rs.format.z16, 30)
  11. #cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
  12. cfg.enable_stream(rs.stream.color, 640, 480, rs.format.rgb8, 30)
  13. profile = pipe.start(cfg)
  14. # Skip 5 first frames to give the Auto-Exposure time to adjust
  15. for x in range(100):
  16. pipe.wait_for_frames()
  17. # Store next frameset for later processing:
  18. frameset = pipe.wait_for_frames()
  19. color_frame = frameset.get_color_frame()
  20. depth_frame = frameset.get_depth_frame()
  21. # Cleanup:
  22. pipe.stop()
  23. print("Frames Captured")
  24. color = np.asanyarray(color_frame.get_data())
  25. plt.rcParams["axes.grid"] = False
  26. plt.rcParams['figure.figsize'] = [12, 6]
  27. plt.imshow(color)
  28. plt.show()
  29. colorizer = rs.colorizer()
  30. colorized_depth = np.asanyarray(colorizer.colorize(depth_frame).get_data())
  31. plt.imshow(colorized_depth)
  32. plt.show()
  33. # Create alignment primitive with color as its target stream:
  34. align = rs.align(rs.stream.color)
  35. frameset = align.process(frameset)
  36. # Update color and depth frames:
  37. aligned_depth_frame = frameset.get_depth_frame()
  38. colorized_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
  39. # Show the two frames together:
  40. images = np.hstack((color, colorized_depth))
  41. plt.imshow(images)
  42. plt.show()
  43. # Standard OpenCV boilerplate for running the net:
  44. height, width = color.shape[:2]
  45. expected = 300
  46. aspect = width / height
  47. resized_image = cv2.resize(color, (round(expected * aspect), expected))
  48. crop_start = round(expected * (aspect - 1) / 2)
  49. crop_img = resized_image[0:expected, crop_start:crop_start+expected]
  50. net = cv2.dnn.readNetFromCaffe("./MobileNetSSD_deploy.prototxt", "./MobileNetSSD_deploy.caffemodel")
  51. inScaleFactor = 0.007843
  52. meanVal = 127.53
  53. classNames = ("background", "aeroplane", "bicycle", "bird", "boat",
  54. "bottle", "bus", "car", "cat", "chair",
  55. "cow", "diningtable", "dog", "horse",
  56. "motorbike", "person", "pottedplant",
  57. "sheep", "sofa", "train", "tvmonitor")
  58. blob = cv2.dnn.blobFromImage(crop_img, inScaleFactor, (expected, expected), meanVal, False)
  59. net.setInput(blob, "data")
  60. detections = net.forward("detection_out")
  61. label = detections[0,0,0,1]
  62. conf = detections[0,0,0,2]
  63. xmin = detections[0,0,0,3]
  64. ymin = detections[0,0,0,4]
  65. xmax = detections[0,0,0,5]
  66. ymax = detections[0,0,0,6]
  67. className = classNames[int(label)]
  68. cv2.rectangle(crop_img, (int(xmin * expected), int(ymin * expected)),
  69. (int(xmax * expected), int(ymax * expected)), (255, 255, 255), 2)
  70. cv2.putText(crop_img, className,
  71. (int(xmin * expected), int(ymin * expected) - 5),
  72. cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
  73. plt.imshow(crop_img)
  74. plt.show()
  75. scale = height / expected
  76. xmin_depth = int((xmin * expected + crop_start) * scale)
  77. ymin_depth = int((ymin * expected) * scale)
  78. xmax_depth = int((xmax * expected + crop_start) * scale)
  79. ymax_depth = int((ymax * expected) * scale)
  80. xmin_depth,ymin_depth,xmax_depth,ymax_depth
  81. cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
  82. (xmax_depth, ymax_depth), (255, 255, 255), 2)
  83. plt.imshow(colorized_depth)
  84. plt.show()
  85. depth = np.asanyarray(aligned_depth_frame.get_data())
  86. # Crop depth data:
  87. depth = depth[xmin_depth:xmax_depth,ymin_depth:ymax_depth].astype(float)
  88. # Get data scale from the device and convert to meters
  89. depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
  90. depth = depth * depth_scale
  91. dist,_,_,_ = cv2.mean(depth)
  92. print("Detected a {0} {1:.3} meters away.".format(className, dist))

注释修改版:

  1. # -*-coding:utf-8-*-
  2. import cv2 # state of the art computer vision algorithms library
  3. import numpy as np # fundamental package for scientific computing
  4. import matplotlib.pyplot as plt # 2D plotting library producing publication quality figures
  5. import pyrealsense2 as rs # Intel RealSense cross-platform open-source API
  6. print("Environment Ready")
  7. # 创建一个管道
  8. pipe = rs.pipeline()
  9. # 配置要流​​式传输的管道
  10. # 颜色和深度流的不同分辨率
  11. cfg = rs.config()
  12. #cfg.enable_device_from_file("../object_detection.bag")
  13. #1280, 720
  14. cfg.enable_stream(rs.stream.depth, 640, 360, rs.format.z16, 30)
  15. #cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
  16. cfg.enable_stream(rs.stream.color, 640, 480, rs.format.rgb8, 30)
  17. # 开始流式传输
  18. profile = pipe.start(cfg)
  19. # 跳过前300帧以设置自动曝光时间
  20. for x in range(100):
  21. pipe.wait_for_frames()
  22. # 拿到301帧
  23. frameset = pipe.wait_for_frames()
  24. # RGB图
  25. color_frame = frameset.get_color_frame()
  26. # 深度图
  27. depth_frame = frameset.get_depth_frame()
  28. # 停止管道传输
  29. pipe.stop()
  30. print("Frames Captured")
  31. # 显示RGB颜色图像color_frame
  32. color = np.asanyarray(color_frame.get_data())
  33. # 一些可视化显示设置,不用管
  34. plt.rcParams["axes.grid"] = False
  35. plt.rcParams['figure.figsize'] = [12, 6]
  36. plt.imshow(color)
  37. plt.show()
  38. # 显示深度图
  39. # (360, 640) uint16
  40. depth_image_ori = np.asanyarray(depth_frame.get_data())
  41. plt.imshow(depth_image_ori)
  42. plt.show()
  43. # https://github.com/IntelRealSense/librealsense/issues/3665
  44. # 不使用int8是因为精度不够cm
  45. depth_image_ori_int8 = depth_image_ori.astype('uint8')
  46. plt.imshow(depth_image_ori_int8)
  47. plt.show()
  48. # 创建colorizer滤波对象 将深度图映射成彩色图像显示
  49. colorizer = rs.colorizer()
  50. colorized_depth = np.asanyarray(colorizer.colorize(depth_frame).get_data())
  51. plt.imshow(colorized_depth)
  52. plt.show()
  53. # 创建对齐对象
  54. # rs.align允许我们执行深度帧与其他帧的对齐
  55. # “frameset”是我们计划对齐深度帧的流类型。
  56. # 将深度框与颜色框对齐
  57. # 将深度对齐到颜色
  58. align = rs.align(rs.stream.color)
  59. frameset = align.process(frameset)
  60. # 获取对齐更新后的深度图
  61. aligned_depth_frame = frameset.get_depth_frame()
  62. # 将深度图映射成彩色图像显示
  63. colorized_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
  64. # np.vstack():在竖直方向上堆叠
  65. # np.hstack():在水平方向上平铺
  66. images = np.hstack((color, colorized_depth))
  67. plt.imshow(images)
  68. plt.show()
  69. # np.vstack():在竖直方向上堆叠
  70. # np.hstack():在水平方向上平铺
  71. images = np.vstack((color, colorized_depth))
  72. plt.imshow(images)
  73. plt.show()
  74. # 通过对齐后的深度图,对齐原始RGB:color_frame,保存彩色点云
  75. pc = rs.pointcloud()
  76. pc.map_to(color_frame)
  77. points = pc.calculate(aligned_depth_frame)
  78. points.export_to_ply('./out.ply', color_frame)
  79. #pcd = read_point_cloud(file_path)
  80. # Visualize PLY
  81. #draw_geometries([pcd])
  82. #pc.map_to(colorizer.colorize(aligned_depth_frame))
  83. #points.export_to_ply('./out.ply', colorizer.colorize(aligned_depth_frame))
  84. # 480*640*3
  85. height, width = color.shape[:2]
  86. expected = 300
  87. # 1.333333... 原始图像的宽高比
  88. aspect = width / height
  89. # 300*400*3 新的图像也满足此宽高比
  90. resized_image = cv2.resize(color, (round(expected * aspect), expected))
  91. # 50
  92. crop_start = round(expected * (aspect - 1) / 2)
  93. # 300*300*3 H,W
  94. crop_img = resized_image[0:expected, crop_start:crop_start+expected]
  95. plt.imshow(crop_img)
  96. plt.show()
  97. # VOC目标检测网络
  98. net = cv2.dnn.readNetFromCaffe("./MobileNetSSD_deploy.prototxt", "./MobileNetSSD_deploy.caffemodel")
  99. inScaleFactor = 0.007843
  100. meanVal = 127.53
  101. classNames = ("background", "aeroplane", "bicycle", "bird", "boat",
  102. "bottle", "bus", "car", "cat", "chair",
  103. "cow", "diningtable", "dog", "horse",
  104. "motorbike", "person", "pottedplant",
  105. "sheep", "sofa", "train", "tvmonitor")
  106. blob = cv2.dnn.blobFromImage(crop_img, inScaleFactor, (expected, expected), meanVal, False)
  107. net.setInput(blob, "data")
  108. # 1*1*100*7[1-6]
  109. detections = net.forward("detection_out")
  110. # 输出检测结果
  111. # label = detections[0,0,0,1]
  112. # conf = detections[0,0,0,2]
  113. # xmin = detections[0,0,0,3]
  114. # ymin = detections[0,0,0,4]
  115. # xmax = detections[0,0,0,5]
  116. # ymax = detections[0,0,0,6]
  117. # className = classNames[int(label)]
  118. # cv2.rectangle(crop_img, (int(xmin * expected), int(ymin * expected)),
  119. # (int(xmax * expected), int(ymax * expected)), (255, 255, 255), 2)
  120. # cv2.putText(crop_img, className,
  121. # (int(xmin * expected), int(ymin * expected) - 5),
  122. # cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
  123. # plt.imshow(crop_img)
  124. # plt.show()
  125. # scale = height / expected
  126. # xmin_depth = int((xmin * expected + crop_start) * scale)
  127. # ymin_depth = int((ymin * expected) * scale)
  128. # xmax_depth = int((xmax * expected + crop_start) * scale)
  129. # ymax_depth = int((ymax * expected) * scale)
  130. # xmin_depth,ymin_depth,xmax_depth,ymax_depth
  131. # cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
  132. # (xmax_depth, ymax_depth), (255, 255, 255), 2)
  133. # plt.imshow(colorized_depth)
  134. # plt.show()
  135. label1 = detections[0,0,:,1]
  136. conf1 = detections[0,0,:,2]
  137. xmin1 = detections[0,0,:,3]
  138. ymin1 = detections[0,0,:,4]
  139. xmax1 = detections[0,0,:,5]
  140. ymax1 = detections[0,0,:,6]
  141. # 获取满足阈值的框
  142. # 框的x1y1 x2y2 是百分比,相对于300*300
  143. inds = np.where(conf1[:] > 0.3)[0]
  144. for index in inds:
  145. className = classNames[int(label1[index])]
  146. cv2.rectangle(crop_img, (int(xmin1[index] * expected), int(ymin1[index] * expected)),
  147. (int(xmax1[index] * expected), int(ymax1[index] * expected)), (255, 255, 255), 2)
  148. cv2.putText(crop_img, className,
  149. (int(xmin1[index] * expected), int(ymin1[index] * expected) - 5),
  150. cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
  151. plt.imshow(crop_img)
  152. plt.show()
  153. # 对于300,原始图像的扩大比为多少
  154. # 对齐后的深度图:aligned_depth_frame
  155. # 对齐后的深度图的彩色图:colorized_depth
  156. # xmin1[index] * expected 300*300检测图的坐标
  157. # xmin1[index] * expected + crop_start 300*400*3的坐标
  158. # (xmin1[index] * expected + crop_start) * scale 480*640*3的坐标
  159. depth = np.asanyarray(aligned_depth_frame.get_data())
  160. depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
  161. aa = profile.get_device()
  162. scale = height / expected
  163. from decimal import Decimal
  164. for index in inds:
  165. xmin_depth = int((xmin1[index] * expected + crop_start) * scale)
  166. ymin_depth = int((ymin1[index] * expected) * scale)
  167. xmax_depth = int((xmax1[index] * expected + crop_start) * scale)
  168. ymax_depth = int((ymax1[index] * expected) * scale)
  169. #xmin_depth,ymin_depth,xmax_depth,ymax_depth
  170. #depth_temp = depth[xmin_depth:xmax_depth, ymin_depth:ymax_depth].astype(float)
  171. depth_temp = depth[ymin_depth:ymax_depth, xmin_depth:xmax_depth].astype(float)
  172. depth_temp = depth_temp * depth_scale
  173. dist, _, _, _ = cv2.mean(depth_temp)
  174. cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
  175. (xmax_depth, ymax_depth), (255, 255, 255), 2)
  176. # 取小数点后3位
  177. dist_temp = Decimal(dist).quantize(Decimal('0.000'))
  178. cv2.putText(colorized_depth, str(dist_temp),
  179. (xmin_depth, ymin_depth - 5),
  180. cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
  181. plt.imshow(colorized_depth)
  182. plt.show()
  183. plt.close()
  184. # # 对齐后的深度图:aligned_depth_frame
  185. # # 对齐后的深度图的彩色图:colorized_depth
  186. # depth = np.asanyarray(aligned_depth_frame.get_data())
  187. # # crop深度数据
  188. # depth = depth[xmin_depth:xmax_depth,ymin_depth:ymax_depth].astype(float)
  189. # # 计算深度
  190. # # 设备获取数据比例并转换为m
  191. # depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
  192. # depth = depth * depth_scale
  193. # # 取均值获取到物体的距离
  194. # dist,_,_,_ = cv2.mean(depth)
  195. # print("Detected a {0} {1:.3} meters away.".format(className, dist))

改一改:

  1. # -*-coding:utf-8-*-
  2. import cv2 # state of the art computer vision algorithms library
  3. import numpy as np # fundamental package for scientific computing
  4. import matplotlib.pyplot as plt # 2D plotting library producing publication quality figures
  5. import pyrealsense2 as rs # Intel RealSense cross-platform open-source API
  6. print("Environment Ready")
  7. # 创建一个管道
  8. pipe = rs.pipeline()
  9. # 配置要流​​式传输的管道
  10. # 颜色和深度流的不同分辨率
  11. cfg = rs.config()
  12. #cfg.enable_device_from_file("./object_detection.bag")
  13. #cfg.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
  14. #cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
  15. #1280, 720
  16. cfg.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
  17. #cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
  18. cfg.enable_stream(rs.stream.color, 1280, 720, rs.format.rgb8, 30)
  19. # 开始流式传输
  20. profile = pipe.start(cfg)
  21. # 跳过前300帧以设置自动曝光时间
  22. for x in range(100):
  23. pipe.wait_for_frames()
  24. # 拿到301帧
  25. frameset = pipe.wait_for_frames()
  26. # RGB图
  27. color_frame = frameset.get_color_frame()
  28. # 深度图
  29. depth_frame = frameset.get_depth_frame()
  30. # 停止管道传输
  31. pipe.stop()
  32. print("Frames Captured")
  33. # 获取内参外参矩阵
  34. # Intrinsics & Extrinsics
  35. depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
  36. color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
  37. # 外参矩阵-深度图相对于彩色图像的外参
  38. depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
  39. color_frame.profile)
  40. print("内参ppx,ppy",depth_intrin.ppx, ':', depth_intrin.ppy)
  41. print("内参矩阵",depth_intrin)
  42. # 显示RGB颜色图像color_frame
  43. color = np.asanyarray(color_frame.get_data())
  44. # 一些可视化显示设置,不用管
  45. plt.rcParams["axes.grid"] = False
  46. plt.rcParams['figure.figsize'] = [12, 6]
  47. plt.imshow(color)
  48. plt.show()
  49. # 显示深度图
  50. # (360, 640) uint16
  51. depth_image_ori = np.asanyarray(depth_frame.get_data())
  52. plt.imshow(depth_image_ori)
  53. plt.show()
  54. # https://github.com/IntelRealSense/librealsense/issues/3665
  55. # 不使用int8是因为精度不够cm
  56. depth_image_ori_int8 = depth_image_ori.astype('uint8')
  57. plt.imshow(depth_image_ori_int8)
  58. plt.show()
  59. # 创建colorizer滤波对象 将深度图映射成彩色图像显示
  60. colorizer = rs.colorizer()
  61. colorized_depth = np.asanyarray(colorizer.colorize(depth_frame).get_data())
  62. plt.imshow(colorized_depth)
  63. plt.show()
  64. # 创建对齐对象
  65. # rs.align允许我们执行深度帧与其他帧的对齐
  66. # “frameset”是我们计划对齐深度帧的流类型。
  67. # 将深度框与颜色框对齐
  68. # 将深度对齐到颜色
  69. align = rs.align(rs.stream.color)
  70. frameset = align.process(frameset)
  71. # 获取对齐更新后的深度图
  72. aligned_depth_frame = frameset.get_depth_frame()
  73. # 将深度图映射成彩色图像显示
  74. colorized_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
  75. new_depth_image_array = np.asanyarray(aligned_depth_frame.get_data())
  76. np.save("out_ori.npy",new_depth_image_array)
  77. x = np.load("out_ori.npy")
  78. print(x-new_depth_image_array)
  79. bgr_color = cv2.cvtColor(color,cv2.COLOR_RGB2BGR)
  80. cv2.imwrite("out_ori.jpg",bgr_color)
  81. # np.vstack():在竖直方向上堆叠
  82. # np.hstack():在水平方向上平铺
  83. images = np.hstack((color, colorized_depth))
  84. plt.imshow(images)
  85. plt.show()
  86. # np.vstack():在竖直方向上堆叠
  87. # np.hstack():在水平方向上平铺
  88. images = np.vstack((color, colorized_depth))
  89. plt.imshow(images)
  90. plt.show()
  91. # 通过对齐后的深度图,对齐原始RGB:color_frame,保存彩色点云
  92. pc = rs.pointcloud()
  93. points = rs.points()
  94. pc.map_to(color_frame)
  95. points = pc.calculate(depth_frame)
  96. points.export_to_ply('./out_ori.ply', color_frame)
  97. #pcd = read_point_cloud(file_path)
  98. # Visualize PLY
  99. #draw_geometries([pcd])
  100. #pc.map_to(colorizer.colorize(aligned_depth_frame))
  101. #points.export_to_ply('./out.ply', colorizer.colorize(aligned_depth_frame))
  102. # 480*640*3
  103. height, width = color.shape[:2]
  104. expected = 300
  105. # 1.333333... 原始图像的宽高比
  106. aspect = width / height
  107. # 300*400*3 新的图像也满足此宽高比
  108. resized_image = cv2.resize(color, (round(expected * aspect), expected))
  109. # 50
  110. crop_start = round(expected * (aspect - 1) / 2)
  111. # 300*300*3 H,W
  112. crop_img = resized_image[0:expected, crop_start:crop_start+expected]
  113. plt.imshow(crop_img)
  114. plt.show()
  115. # VOC目标检测网络
  116. net = cv2.dnn.readNetFromCaffe("./MobileNetSSD_deploy.prototxt", "./MobileNetSSD_deploy.caffemodel")
  117. inScaleFactor = 0.007843
  118. meanVal = 127.53
  119. classNames = ("background", "aeroplane", "bicycle", "bird", "boat",
  120. "bottle", "bus", "car", "cat", "chair",
  121. "cow", "diningtable", "dog", "horse",
  122. "motorbike", "person", "pottedplant",
  123. "sheep", "sofa", "train", "tvmonitor")
  124. blob = cv2.dnn.blobFromImage(crop_img, inScaleFactor, (expected, expected), meanVal, False)
  125. net.setInput(blob, "data")
  126. # 1*1*100*7[1-6]
  127. detections = net.forward("detection_out")
  128. # 输出检测结果
  129. # label = detections[0,0,0,1]
  130. # conf = detections[0,0,0,2]
  131. # xmin = detections[0,0,0,3]
  132. # ymin = detections[0,0,0,4]
  133. # xmax = detections[0,0,0,5]
  134. # ymax = detections[0,0,0,6]
  135. # className = classNames[int(label)]
  136. # cv2.rectangle(crop_img, (int(xmin * expected), int(ymin * expected)),
  137. # (int(xmax * expected), int(ymax * expected)), (255, 255, 255), 2)
  138. # cv2.putText(crop_img, className,
  139. # (int(xmin * expected), int(ymin * expected) - 5),
  140. # cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
  141. # plt.imshow(crop_img)
  142. # plt.show()
  143. # scale = height / expected
  144. # xmin_depth = int((xmin * expected + crop_start) * scale)
  145. # ymin_depth = int((ymin * expected) * scale)
  146. # xmax_depth = int((xmax * expected + crop_start) * scale)
  147. # ymax_depth = int((ymax * expected) * scale)
  148. # xmin_depth,ymin_depth,xmax_depth,ymax_depth
  149. # cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
  150. # (xmax_depth, ymax_depth), (255, 255, 255), 2)
  151. # plt.imshow(colorized_depth)
  152. # plt.show()
  153. label1 = detections[0,0,:,1]
  154. conf1 = detections[0,0,:,2]
  155. xmin1 = detections[0,0,:,3]
  156. ymin1 = detections[0,0,:,4]
  157. xmax1 = detections[0,0,:,5]
  158. ymax1 = detections[0,0,:,6]
  159. # 获取满足阈值的框
  160. # 框的x1y1 x2y2 是百分比,相对于300*300
  161. inds = np.where(conf1[:] > 0.3)[0]
  162. for index in inds:
  163. className = classNames[int(label1[index])]
  164. cv2.rectangle(crop_img, (int(xmin1[index] * expected), int(ymin1[index] * expected)),
  165. (int(xmax1[index] * expected), int(ymax1[index] * expected)), (255, 255, 255), 2)
  166. cv2.putText(crop_img, className,
  167. (int(xmin1[index] * expected), int(ymin1[index] * expected) - 5),
  168. cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
  169. plt.imshow(crop_img)
  170. plt.show()
  171. # 对于300,原始图像的扩大比为多少
  172. # 对齐后的深度图:aligned_depth_frame
  173. # 对齐后的深度图的彩色图:colorized_depth
  174. # xmin1[index] * expected 300*300检测图的坐标
  175. # xmin1[index] * expected + crop_start 300*400*3的坐标
  176. # (xmin1[index] * expected + crop_start) * scale 480*640*3的坐标
  177. depth = np.asanyarray(aligned_depth_frame.get_data())
  178. depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
  179. aa = profile.get_device()
  180. scale = height / expected
  181. from decimal import Decimal
  182. for index in inds:
  183. xmin_depth = int((xmin1[index] * expected + crop_start) * scale)
  184. ymin_depth = int((ymin1[index] * expected) * scale)
  185. xmax_depth = int((xmax1[index] * expected + crop_start) * scale)
  186. ymax_depth = int((ymax1[index] * expected) * scale)
  187. depth_temp = depth[ymin_depth:ymax_depth, xmin_depth:xmax_depth].astype(float)
  188. #print(depth_temp.shape)
  189. depth_temp = depth_temp * depth_scale
  190. #dis = depth_temp[depth_tem,depth_temp]
  191. dist, _, _, _ = cv2.mean(depth_temp)
  192. cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
  193. (xmax_depth, ymax_depth), (255, 255, 255), 2)
  194. # 取小数点后3位
  195. dist_temp = Decimal(dist).quantize(Decimal('0.000'))
  196. cv2.putText(colorized_depth, str(dist_temp),
  197. (xmin_depth, ymin_depth - 5),
  198. cv2.FONT_HERSHEY_COMPLEX, 1.5, (255,255,255))
  199. plt.imshow(colorized_depth)
  200. plt.show()
  201. # # 对齐后的深度图:aligned_depth_frame
  202. # # 对齐后的深度图的彩色图:colorized_depth
  203. # depth = np.asanyarray(aligned_depth_frame.get_data())
  204. # # crop深度数据
  205. # depth = depth[xmin_depth:xmax_depth,ymin_depth:ymax_depth].astype(float)
  206. # # 计算深度
  207. # # 设备获取数据比例并转换为m
  208. # depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
  209. # depth = depth * depth_scale
  210. # # 取均值获取到物体的距离
  211. # dist,_,_,_ = cv2.mean(depth)
  212. # print("Detected a {0} {1:.3} meters away.".format(className, dist))

点云程序:

  1. # License: Apache 2.0. See LICENSE file in root directory.
  2. # Copyright(c) 2015-2017 Intel Corporation. All Rights Reserved.
  3. """
  4. OpenGL Pointcloud viewer with http://pyglet.org
  5. Usage:
  6. ------
  7. Mouse:
  8. Drag with left button to rotate around pivot (thick small axes),
  9. with right button to translate and the wheel to zoom.
  10. Keyboard:
  11. [p] Pause
  12. [r] Reset View
  13. [d] Cycle through decimation values
  14. [z] Toggle point scaling
  15. [x] Toggle point distance attenuation
  16. [c] Toggle color source
  17. [l] Toggle lighting
  18. [f] Toggle depth post-processing
  19. [s] Save PNG (./out.png)
  20. [e] Export points to ply (./out.ply)
  21. [q/ESC] Quit
  22. Notes:
  23. ------
  24. Using deprecated OpenGL (FFP lighting, matrix stack...) however, draw calls
  25. are kept low with pyglet.graphics.* which uses glDrawArrays internally.
  26. Normals calculation is done with numpy on CPU which is rather slow, should really
  27. be done with shaders but was omitted for several reasons - brevity, for lowering
  28. dependencies (pyglet doesn't ship with shader support & recommends pyshaders)
  29. and for reference.
  30. """
  31. import math
  32. import ctypes
  33. import pyglet
  34. import pyglet.gl as gl
  35. import numpy as np
  36. import pyrealsense2 as rs
  37. # https://stackoverflow.com/a/6802723
  38. def rotation_matrix(axis, theta):
  39. """
  40. Return the rotation matrix associated with counterclockwise rotation about
  41. the given axis by theta radians.
  42. """
  43. axis = np.asarray(axis)
  44. axis = axis / math.sqrt(np.dot(axis, axis))
  45. a = math.cos(theta / 2.0)
  46. b, c, d = -axis * math.sin(theta / 2.0)
  47. aa, bb, cc, dd = a * a, b * b, c * c, d * d
  48. bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
  49. return np.array([[aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
  50. [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
  51. [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc]])
  52. class AppState:
  53. def __init__(self, *args, **kwargs):
  54. self.pitch, self.yaw = math.radians(-10), math.radians(-15)
  55. self.translation = np.array([0, 0, 1], np.float32)
  56. self.distance = 2
  57. self.mouse_btns = [False, False, False]
  58. self.paused = False
  59. self.decimate = 0
  60. self.scale = True
  61. self.attenuation = False
  62. self.color = True
  63. self.lighting = False
  64. self.postprocessing = False
  65. def reset(self):
  66. self.pitch, self.yaw, self.distance = 0, 0, 2
  67. self.translation[:] = 0, 0, 1
  68. @property
  69. def rotation(self):
  70. Rx = rotation_matrix((1, 0, 0), math.radians(-self.pitch))
  71. Ry = rotation_matrix((0, 1, 0), math.radians(-self.yaw))
  72. return np.dot(Ry, Rx).astype(np.float32)
  73. state = AppState()
  74. # Configure streams
  75. pipeline = rs.pipeline()
  76. config = rs.config()
  77. config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
  78. # other_stream, other_format = rs.stream.infrared, rs.format.y8
  79. other_stream, other_format = rs.stream.color, rs.format.rgb8
  80. config.enable_stream(other_stream, 640, 480, other_format, 30)
  81. # Start streaming
  82. pipeline.start(config)
  83. profile = pipeline.get_active_profile()
  84. depth_sensor = profile.get_device().first_depth_sensor()
  85. depth_scale = depth_sensor.get_depth_scale()
  86. depth_profile = rs.video_stream_profile(profile.get_stream(rs.stream.depth))
  87. depth_intrinsics = depth_profile.get_intrinsics()
  88. w, h = depth_intrinsics.width, depth_intrinsics.height
  89. # Processing blocks
  90. pc = rs.pointcloud()
  91. decimate = rs.decimation_filter()
  92. decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
  93. colorizer = rs.colorizer()
  94. filters = [rs.disparity_transform(),
  95. rs.spatial_filter(),
  96. rs.temporal_filter(),
  97. rs.disparity_transform(False)]
  98. # pyglet
  99. window = pyglet.window.Window(
  100. config=gl.Config(
  101. double_buffer=True,
  102. samples=8 # MSAA
  103. ),
  104. resizable=True, vsync=True)
  105. keys = pyglet.window.key.KeyStateHandler()
  106. window.push_handlers(keys)
  107. def convert_fmt(fmt):
  108. """rs.format to pyglet format string"""
  109. return {
  110. rs.format.rgb8: 'RGB',
  111. rs.format.bgr8: 'BGR',
  112. rs.format.rgba8: 'RGBA',
  113. rs.format.bgra8: 'BGRA',
  114. rs.format.y8: 'L',
  115. }[fmt]
  116. # Create a VertexList to hold pointcloud data
  117. # Will pre-allocates memory according to the attributes below
  118. vertex_list = pyglet.graphics.vertex_list(
  119. w * h, 'v3f/stream', 't2f/stream', 'n3f/stream')
  120. # Create and allocate memory for our color data
  121. other_profile = rs.video_stream_profile(profile.get_stream(other_stream))
  122. image_data = pyglet.image.ImageData(w, h, convert_fmt(
  123. other_profile.format()), (gl.GLubyte * (w * h * 3))())
  124. fps_display = pyglet.clock.ClockDisplay()
  125. @window.event
  126. def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
  127. w, h = map(float, window.get_size())
  128. if buttons & pyglet.window.mouse.LEFT:
  129. state.yaw -= dx * 0.5
  130. state.pitch -= dy * 0.5
  131. if buttons & pyglet.window.mouse.RIGHT:
  132. dp = np.array((dx / w, -dy / h, 0), np.float32)
  133. state.translation += np.dot(state.rotation, dp)
  134. if buttons & pyglet.window.mouse.MIDDLE:
  135. dz = dy * 0.01
  136. state.translation -= (0, 0, dz)
  137. state.distance -= dz
  138. def handle_mouse_btns(x, y, button, modifiers):
  139. state.mouse_btns[0] ^= (button & pyglet.window.mouse.LEFT)
  140. state.mouse_btns[1] ^= (button & pyglet.window.mouse.RIGHT)
  141. state.mouse_btns[2] ^= (button & pyglet.window.mouse.MIDDLE)
  142. window.on_mouse_press = window.on_mouse_release = handle_mouse_btns
  143. @window.event
  144. def on_mouse_scroll(x, y, scroll_x, scroll_y):
  145. dz = scroll_y * 0.1
  146. state.translation -= (0, 0, dz)
  147. state.distance -= dz
  148. def on_key_press(symbol, modifiers):
  149. if symbol == pyglet.window.key.R:
  150. state.reset()
  151. if symbol == pyglet.window.key.P:
  152. state.paused ^= True
  153. if symbol == pyglet.window.key.D:
  154. state.decimate = (state.decimate + 1) % 3
  155. decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
  156. if symbol == pyglet.window.key.C:
  157. state.color ^= True
  158. if symbol == pyglet.window.key.Z:
  159. state.scale ^= True
  160. if symbol == pyglet.window.key.X:
  161. state.attenuation ^= True
  162. if symbol == pyglet.window.key.L:
  163. state.lighting ^= True
  164. if symbol == pyglet.window.key.F:
  165. state.postprocessing ^= True
  166. if symbol == pyglet.window.key.S:
  167. pyglet.image.get_buffer_manager().get_color_buffer().save('out.png')
  168. if symbol == pyglet.window.key.Q:
  169. window.close()
  170. window.push_handlers(on_key_press)
  171. def axes(size=1, width=1):
  172. """draw 3d axes"""
  173. gl.glLineWidth(width)
  174. pyglet.graphics.draw(6, gl.GL_LINES,
  175. ('v3f', (0, 0, 0, size, 0, 0,
  176. 0, 0, 0, 0, size, 0,
  177. 0, 0, 0, 0, 0, size)),
  178. ('c3f', (1, 0, 0, 1, 0, 0,
  179. 0, 1, 0, 0, 1, 0,
  180. 0, 0, 1, 0, 0, 1,
  181. ))
  182. )
  183. def frustum(intrinsics):
  184. """draw camera's frustum"""
  185. w, h = intrinsics.width, intrinsics.height
  186. batch = pyglet.graphics.Batch()
  187. for d in range(1, 6, 2):
  188. def get_point(x, y):
  189. p = rs.rs2_deproject_pixel_to_point(intrinsics, [x, y], d)
  190. batch.add(2, gl.GL_LINES, None, ('v3f', [0, 0, 0] + p))
  191. return p
  192. top_left = get_point(0, 0)
  193. top_right = get_point(w, 0)
  194. bottom_right = get_point(w, h)
  195. bottom_left = get_point(0, h)
  196. batch.add(2, gl.GL_LINES, None, ('v3f', top_left + top_right))
  197. batch.add(2, gl.GL_LINES, None, ('v3f', top_right + bottom_right))
  198. batch.add(2, gl.GL_LINES, None, ('v3f', bottom_right + bottom_left))
  199. batch.add(2, gl.GL_LINES, None, ('v3f', bottom_left + top_left))
  200. batch.draw()
  201. def grid(size=1, n=10, width=1):
  202. """draw a grid on xz plane"""
  203. gl.glLineWidth(width)
  204. s = size / float(n)
  205. s2 = 0.5 * size
  206. batch = pyglet.graphics.Batch()
  207. for i in range(0, n + 1):
  208. x = -s2 + i * s
  209. batch.add(2, gl.GL_LINES, None, ('v3f', (x, 0, -s2, x, 0, s2)))
  210. for i in range(0, n + 1):
  211. z = -s2 + i * s
  212. batch.add(2, gl.GL_LINES, None, ('v3f', (-s2, 0, z, s2, 0, z)))
  213. batch.draw()
  214. @window.event
  215. def on_draw():
  216. window.clear()
  217. gl.glEnable(gl.GL_DEPTH_TEST)
  218. gl.glEnable(gl.GL_LINE_SMOOTH)
  219. width, height = window.get_size()
  220. gl.glViewport(0, 0, width, height)
  221. gl.glMatrixMode(gl.GL_PROJECTION)
  222. gl.glLoadIdentity()
  223. gl.gluPerspective(60, width / float(height), 0.01, 20)
  224. gl.glMatrixMode(gl.GL_TEXTURE)
  225. gl.glLoadIdentity()
  226. # texcoords are [0..1] and relative to top-left pixel corner, add 0.5 to center
  227. gl.glTranslatef(0.5 / image_data.width, 0.5 / image_data.height, 0)
  228. # texture size may be increased by pyglet to a power of 2
  229. tw, th = image_data.texture.owner.width, image_data.texture.owner.height
  230. gl.glScalef(image_data.width / float(tw),
  231. image_data.height / float(th), 1)
  232. gl.glMatrixMode(gl.GL_MODELVIEW)
  233. gl.glLoadIdentity()
  234. gl.gluLookAt(0, 0, 0, 0, 0, 1, 0, -1, 0)
  235. gl.glTranslatef(0, 0, state.distance)
  236. gl.glRotated(state.pitch, 1, 0, 0)
  237. gl.glRotated(state.yaw, 0, 1, 0)
  238. if any(state.mouse_btns):
  239. axes(0.1, 4)
  240. gl.glTranslatef(0, 0, -state.distance)
  241. gl.glTranslatef(*state.translation)
  242. gl.glColor3f(0.5, 0.5, 0.5)
  243. gl.glPushMatrix()
  244. gl.glTranslatef(0, 0.5, 0.5)
  245. grid()
  246. gl.glPopMatrix()
  247. psz = max(window.get_size()) / float(max(w, h)) if state.scale else 1
  248. gl.glPointSize(psz)
  249. distance = (0, 0, 1) if state.attenuation else (1, 0, 0)
  250. gl.glPointParameterfv(gl.GL_POINT_DISTANCE_ATTENUATION,
  251. (gl.GLfloat * 3)(*distance))
  252. if state.lighting:
  253. ldir = [0.5, 0.5, 0.5] # world-space lighting
  254. ldir = np.dot(state.rotation, (0, 0, 1)) # MeshLab style lighting
  255. ldir = list(ldir) + [0] # w=0, directional light
  256. gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, (gl.GLfloat * 4)(*ldir))
  257. gl.glLightfv(gl.GL_LIGHT0, gl.GL_DIFFUSE,
  258. (gl.GLfloat * 3)(1.0, 1.0, 1.0))
  259. gl.glLightfv(gl.GL_LIGHT0, gl.GL_AMBIENT,
  260. (gl.GLfloat * 3)(0.75, 0.75, 0.75))
  261. gl.glEnable(gl.GL_LIGHT0)
  262. gl.glEnable(gl.GL_NORMALIZE)
  263. gl.glEnable(gl.GL_LIGHTING)
  264. gl.glColor3f(1, 1, 1)
  265. texture = image_data.get_texture()
  266. gl.glEnable(texture.target)
  267. gl.glBindTexture(texture.target, texture.id)
  268. gl.glTexParameteri(
  269. gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
  270. # comment this to get round points with MSAA on
  271. gl.glEnable(gl.GL_POINT_SPRITE)
  272. if not state.scale and not state.attenuation:
  273. gl.glDisable(gl.GL_MULTISAMPLE) # for true 1px points with MSAA on
  274. vertex_list.draw(gl.GL_POINTS)
  275. gl.glDisable(texture.target)
  276. if not state.scale and not state.attenuation:
  277. gl.glEnable(gl.GL_MULTISAMPLE)
  278. gl.glDisable(gl.GL_LIGHTING)
  279. gl.glColor3f(0.25, 0.25, 0.25)
  280. frustum(depth_intrinsics)
  281. axes()
  282. gl.glMatrixMode(gl.GL_PROJECTION)
  283. gl.glLoadIdentity()
  284. gl.glOrtho(0, width, 0, height, -1, 1)
  285. gl.glMatrixMode(gl.GL_MODELVIEW)
  286. gl.glLoadIdentity()
  287. gl.glMatrixMode(gl.GL_TEXTURE)
  288. gl.glLoadIdentity()
  289. gl.glDisable(gl.GL_DEPTH_TEST)
  290. fps_display.draw()
  291. def run(dt):
  292. global w, h
  293. window.set_caption("RealSense (%dx%d) %dFPS (%.2fms) %s" %
  294. (w, h, 0 if dt == 0 else 1.0 / dt, dt * 1000,
  295. "PAUSED" if state.paused else ""))
  296. if state.paused:
  297. return
  298. success, frames = pipeline.try_wait_for_frames(timeout_ms=0)
  299. if not success:
  300. return
  301. depth_frame = frames.get_depth_frame()
  302. other_frame = frames.first(other_stream).as_video_frame()
  303. depth_frame = decimate.process(depth_frame)
  304. if state.postprocessing:
  305. for f in filters:
  306. depth_frame = f.process(depth_frame)
  307. # Grab new intrinsics (may be changed by decimation)
  308. depth_intrinsics = rs.video_stream_profile(
  309. depth_frame.profile).get_intrinsics()
  310. w, h = depth_intrinsics.width, depth_intrinsics.height
  311. color_image = np.asanyarray(other_frame.get_data())
  312. colorized_depth = colorizer.colorize(depth_frame)
  313. depth_colormap = np.asanyarray(colorized_depth.get_data())
  314. if state.color:
  315. mapped_frame, color_source = other_frame, color_image
  316. else:
  317. mapped_frame, color_source = colorized_depth, depth_colormap
  318. points = pc.calculate(depth_frame)
  319. pc.map_to(mapped_frame)
  320. # handle color source or size change
  321. fmt = convert_fmt(mapped_frame.profile.format())
  322. global image_data
  323. if (image_data.format, image_data.pitch) != (fmt, color_source.strides[0]):
  324. empty = (gl.GLubyte * (w * h * 3))()
  325. image_data = pyglet.image.ImageData(w, h, fmt, empty)
  326. # copy image data to pyglet
  327. image_data.set_data(fmt, color_source.strides[0], color_source.ctypes.data)
  328. verts = np.asarray(points.get_vertices(2)).reshape(h, w, 3)
  329. texcoords = np.asarray(points.get_texture_coordinates(2))
  330. if len(vertex_list.vertices) != verts.size:
  331. vertex_list.resize(verts.size // 3)
  332. # need to reassign after resizing
  333. vertex_list.vertices = verts.ravel()
  334. vertex_list.tex_coords = texcoords.ravel()
  335. # copy our data to pre-allocated buffers, this is faster than assigning...
  336. # pyglet will take care of uploading to GPU
  337. def copy(dst, src):
  338. """copy numpy array to pyglet array"""
  339. # timeit was mostly inconclusive, favoring slice assignment for safety
  340. np.array(dst, copy=False)[:] = src.ravel()
  341. # ctypes.memmove(dst, src.ctypes.data, src.nbytes)
  342. copy(vertex_list.vertices, verts)
  343. copy(vertex_list.tex_coords, texcoords)
  344. if state.lighting:
  345. # compute normals
  346. dy, dx = np.gradient(verts, axis=(0, 1))
  347. n = np.cross(dx, dy)
  348. # can use this, np.linalg.norm or similar to normalize, but OpenGL can do this for us, see GL_NORMALIZE above
  349. # norm = np.sqrt((n*n).sum(axis=2, keepdims=True))
  350. # np.divide(n, norm, out=n, where=norm != 0)
  351. # import cv2
  352. # n = cv2.bilateralFilter(n, 5, 1, 1)
  353. copy(vertex_list.normals, n)
  354. if keys[pyglet.window.key.E]:
  355. points.export_to_ply('./out.ply', mapped_frame)
  356. pyglet.clock.schedule(run)
  357. try:
  358. pyglet.app.run()
  359. finally:
  360. pipeline.stop()

原始程序有个bug

https://github.com/IntelRealSense/librealsense/issues/3887

加上

.as_video_frame()

 

接下来物体宽度:

官方文档:

https://github.com/IntelRealSense/librealsense/wiki/Projection-in-RealSense-SDK-2.0#point-coordinates

https://github.com/IntelRealSense/librealsense/tree/master/examples/measure

大家提的问题:

https://github.com/IntelRealSense/librealsense/issues/1904

https://github.com/IntelRealSense/librealsense/issues/1231

https://github.com/IntelRealSense/librealsense/issues/1904

https://forums.intel.com/s/question/0D50P0000490XJBSA2/accuracy-in-real-world-xyz-coordinates?language=zh_CN

https://github.com/IntelRealSense/librealsense/issues/1413#

https://github.com/IntelRealSense/librealsense/issues/5135

 

https://github.com/IntelRealSense/librealsense/blob/master/examples/example.hpp

https://github.com/IntelRealSense/librealsense/tree/master/examples/measure

关于例子:机翻

  1. // License: Apache 2.0. See LICENSE file in root directory.
  2. // Copyright(c) 2017 Intel Corporation. All Rights Reserved.
  3. #include <librealsense2/rs.hpp> // Include RealSense Cross Platform API
  4. #include <librealsense2/rsutil.h>
  5. #include "example.hpp" // Include short list of convenience functions for rendering
  6. // 包括用于渲染的便捷功能的简短列表
  7. // This example will require several standard data-structures and algorithms:
  8. #define _USE_MATH_DEFINES
  9. #include <math.h>
  10. #include <queue>
  11. #include <unordered_set>
  12. #include <map>
  13. #include <thread>
  14. #include <atomic>
  15. #include <mutex>
  16. using pixel = std::pair<int, int>;
  17. // Distance 3D is used to calculate real 3D distance between two pixels
  18. // 距离3D用于计算两个像素之间的真实3D距离
  19. float dist_3d(const rs2::depth_frame& frame, pixel u, pixel v);
  20. // Toggle helper class will be used to render the two buttons
  21. // controlling the edges of our ruler
  22. // Toggle helper类将用于渲染控制标尺边缘的两个按钮
  23. struct toggle
  24. {
  25. toggle() : x(0.f), y(0.f) {}
  26. toggle(float xl, float yl)
  27. : x(std::min(std::max(xl, 0.f), 1.f)),
  28. y(std::min(std::max(yl, 0.f), 1.f))
  29. {}
  30. // Move from [0,1] space to pixel space of specific frame
  31. // 从[0,1]空间移至特定帧的像素空间
  32. pixel get_pixel(rs2::depth_frame frm) const
  33. {
  34. int px = x * frm.get_width();
  35. int py = y * frm.get_height();
  36. return{ px, py };
  37. }
  38. void render(const window& app)
  39. {
  40. glColor4f(0.f, 0.0f, 0.0f, 0.2f);
  41. render_circle(app, 10);
  42. render_circle(app, 8);
  43. glColor4f(1.f, 0.9f, 1.0f, 1.f);
  44. render_circle(app, 6);
  45. }
  46. void render_circle(const window& app, float r)
  47. {
  48. const float segments = 16;
  49. glBegin(GL_TRIANGLE_STRIP);
  50. for (auto i = 0; i <= segments; i++)
  51. {
  52. auto t = 2 * M_PI * float(i) / segments;
  53. glVertex2f(x * app.width() + cos(t) * r,
  54. y * app.height() + sin(t) * r);
  55. glVertex2f(x * app.width(),
  56. y * app.height());
  57. }
  58. glEnd();
  59. }
  60. // This helper function is used to find the button
  61. // closest to the mouse cursor
  62. // Since we are only comparing this distance, sqrt can be safely skipped
  63. // 此辅助函数用于查找最接近鼠标光标的按钮
  64. // 由于我们仅比较此距离,因此可以安全地跳过sqrt
  65. float dist_2d(const toggle& other) const
  66. {
  67. return pow(x - other.x, 2) + pow(y - other.y, 2);
  68. }
  69. float x;
  70. float y;
  71. bool selected = false;
  72. };
  73. // Application state shared between the main-thread and GLFW events
  74. // 主线程和GLFW事件之间共享的应用程序状态
  75. struct state
  76. {
  77. bool mouse_down = false;
  78. toggle ruler_start;
  79. toggle ruler_end;
  80. };
  81. // Helper function to register to UI events
  82. // 帮助程序功能注册到UI事件
  83. void register_glfw_callbacks(window& app, state& app_state);
  84. // Distance rendering functions:
  85. // 距离渲染功能:
  86. // Simple distance is the classic pythagorean distance between 3D points
  87. // This distance ignores the topology of the object and can cut both through
  88. // air and through solid
  89. // 简单距离是3D点之间的经典勾股距离
  90. // 这个距离忽略了物体的拓扑结构,可以穿过空气和固体
  91. void render_simple_distance(const rs2::depth_frame& depth,
  92. const state& s,
  93. const window& app);
  94. int main(int argc, char * argv[]) try
  95. {
  96. // OpenGL textures for the color and depth frames
  97. // 彩色和深度帧的OpenGL纹理
  98. texture depth_image, color_image;
  99. // Colorizer is used to visualize depth data
  100. // 着色器用于可视化深度数据
  101. rs2::colorizer color_map;
  102. // Use black to white color map
  103. // 使用黑色到白色的颜色图
  104. color_map.set_option(RS2_OPTION_COLOR_SCHEME, 2.f);
  105. // Decimation filter reduces the amount of data (while preserving best samples)
  106. // 抽取滤波器可减少数据量(同时保留最佳样本)
  107. rs2::decimation_filter dec;
  108. // If the demo is too slow, make sure you run in Release (-DCMAKE_BUILD_TYPE=Release)
  109. // 如果速度太慢,请确保在Release (-DCMAKE_BUILD_TYPE=Release)中运行
  110. // but you can also increase the following parameter to decimate depth more (reducing quality)
  111. // 但您也可以增加以下参数来进一步降低深度(降低质量)
  112. dec.set_option(RS2_OPTION_FILTER_MAGNITUDE, 2);
  113. // Define transformations from and to Disparity domain
  114. // 定义视差域之间的转换
  115. rs2::disparity_transform depth2disparity;
  116. rs2::disparity_transform disparity2depth(false);
  117. // Define spatial filter (edge-preserving)
  118. // 定义空间过滤器(边缘保留)
  119. rs2::spatial_filter spat;
  120. // Enable hole-filling
  121. // Hole filling is an agressive heuristic and it gets the depth wrong many times
  122. // However, this demo is not built to handle holes
  123. // (the shortest-path will always prefer to "cut" through the holes since they have zero 3D distance)
  124. // 启用孔填充
  125.     // 孔填充是一种攻击性的启发式方法,它多次导致深度错误
  126.     // 但是,此演示不是为处理孔洞而构建的
  127.     //(最短路径始终喜欢通过孔洞“切”,因为它们的零3D距离为零)
  128. spat.set_option(RS2_OPTION_HOLES_FILL, 5); // 5 = fill all the zero pixels
  129. // Define temporal filter
  130. // 定义时间过滤器
  131. rs2::temporal_filter temp;
  132. // Spatially align all streams to depth viewport
  133. // We do this because:
  134. // a. Usually depth has wider FOV, and we only really need depth for this demo
  135. // b. We don't want to introduce new holes
  136. // 在空间上将所有流与深度视口对齐
  137.     // 我们这样做是因为:
  138.     // 通常,深度具有较宽的FOV,我们只需要此演示的深度
  139.     // 我们不想引入新的孔洞
  140. rs2::align align_to(RS2_STREAM_DEPTH);
  141. // Declare RealSense pipeline, encapsulating the actual device and sensors
  142. // 声明RealSense管道,封装实际的设备和传感器
  143. rs2::pipeline pipe;
  144. rs2::config cfg;
  145. cfg.enable_stream(RS2_STREAM_DEPTH); // Enable default depth //启用默认深度
  146. // For the color stream, set format to RGBA
  147. // To allow blending of the color frame on top of the depth frame
  148. // 对于颜色流,将格式设置为RGBA
  149.     // 允许在深度框上方混合颜色框
  150. cfg.enable_stream(RS2_STREAM_COLOR, RS2_FORMAT_RGBA8);
  151. auto profile = pipe.start(cfg);
  152. auto sensor = profile.get_device().first<rs2::depth_sensor>();
  153. // Set the device to High Accuracy preset of the D400 stereoscopic cameras
  154. // 将设备设置为D400立体摄像机的“高精度”预设
  155. if (sensor && sensor.is<rs2::depth_stereo_sensor>())
  156. {
  157. sensor.set_option(RS2_OPTION_VISUAL_PRESET, RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY);
  158. }
  159. auto stream = profile.get_stream(RS2_STREAM_DEPTH).as<rs2::video_stream_profile>();
  160. // Create a simple OpenGL window for rendering:
  161. // 创建一个简单的OpenGL窗口进行渲染:
  162. window app(stream.width(), stream.height(), "RealSense Measure Example");
  163. // Define application state and position the ruler buttons
  164. // 定义应用程序状态并定位标尺按钮
  165. state app_state;
  166. app_state.ruler_start = { 0.45f, 0.5f };
  167. app_state.ruler_end = { 0.55f, 0.5f };
  168. register_glfw_callbacks(app, app_state);
  169. // After initial post-processing, frames will flow into this queue:
  170. // 初始后处理后,帧将流入此队列:
  171. rs2::frame_queue postprocessed_frames;
  172. // Alive boolean will signal the worker threads to finish-up
  173. // 激活的布尔值将指示工作线程完成
  174. std::atomic_bool alive{ true };
  175. // Video-processing thread will fetch frames from the camera,
  176. // apply post-processing and send the result to the main thread for rendering
  177. // It recieves synchronized (but not spatially aligned) pairs
  178. // and outputs synchronized and aligned pairs
  179. // 视频处理线程将从摄像头获取帧,进行后处理并将结果发送到主线程进行渲染
  180. // 接收同步(但在空间上不对齐)对,并输出同步和对齐对
  181. std::thread video_processing_thread([&]() {
  182. while (alive)
  183. {
  184. // Fetch frames from the pipeline and send them for processing
  185. // 从管道中获取帧并将其发送以进行处理
  186. rs2::frameset data;
  187. if (pipe.poll_for_frames(&data))
  188. {
  189. // First make the frames spatially aligned
  190. // 首先使框架在空间上对齐
  191. data = data.apply_filter(align_to);
  192. // Decimation will reduce the resultion of the depth image,
  193. // closing small holes and speeding-up the algorithm
  194. // 抽取会降低深度图像的分辨率,关闭小孔并加快算法
  195. data = data.apply_filter(dec);
  196. // To make sure far-away objects are filtered proportionally
  197. // we try to switch to disparity domain
  198. // 确保远处的对象按比例过滤
  199.                 // 我们尝试切换到视差域
  200. data = data.apply_filter(depth2disparity);
  201. // Apply spatial filtering
  202. // 应用空间过滤
  203. data = data.apply_filter(spat);
  204. // Apply temporal filtering
  205. // 应用时间过滤
  206. data = data.apply_filter(temp);
  207. // If we are in disparity domain, switch back to depth
  208. // 如果我们处于视差域,请切换回深度
  209. data = data.apply_filter(disparity2depth);
  210. Apply color map for visualization of depth
  211. // 应用颜色图以可视化深度
  212. data = data.apply_filter(color_map);
  213. // Send resulting frames for visualization in the main thread
  214. // 发送结果帧以在主线程中进行可视化
  215. postprocessed_frames.enqueue(data);
  216. }
  217. }
  218. });
  219. rs2::frameset current_frameset;
  220. while(app) // Application still alive?//应用程序还在激活状态吗
  221. {
  222. // Fetch the latest available post-processed frameset
  223. // 获取最新的可用后处理框架集
  224. postprocessed_frames.poll_for_frame(&current_frameset);
  225. if (current_frameset)
  226. {
  227. auto depth = current_frameset.get_depth_frame();
  228. auto color = current_frameset.get_color_frame();
  229. auto colorized_depth = current_frameset.first(RS2_STREAM_DEPTH, RS2_FORMAT_RGB8);
  230. glEnable(GL_BLEND);
  231. // Use the Alpha channel for blending
  232. // 使用Alpha通道进行混合
  233. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  234. // First render the colorized depth image
  235. // 首先渲染彩色深度图像
  236. depth_image.render(colorized_depth, { 0, 0, app.width(), app.height() });
  237. // Render the color frame (since we have selected RGBA format
  238. // pixels out of FOV will appear transparent)
  239. // 渲染颜色框(因为我们从FOV中选择了RGBA格式的像素将显示为透明)
  240. color_image.render(color, { 0, 0, app.width(), app.height() });
  241. // Render the simple pythagorean distance
  242. // 渲染简单的勾股距离
  243. render_simple_distance(depth, app_state, app);
  244. // Render the ruler
  245. // 渲染标尺
  246. app_state.ruler_start.render(app);
  247. app_state.ruler_end.render(app);
  248. glColor3f(1.f, 1.f, 1.f);
  249. glDisable(GL_BLEND);
  250. }
  251. }
  252. // Signal threads to finish and wait until they do
  253. // 通知线程完成并等待它们完成
  254. alive = false;
  255. video_processing_thread.join();
  256. return EXIT_SUCCESS;
  257. }
  258. catch (const rs2::error & e)
  259. {
  260. std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << std::endl;
  261. return EXIT_FAILURE;
  262. }
  263. catch (const std::exception& e)
  264. {
  265. std::cerr << e.what() << std::endl;
  266. return EXIT_FAILURE;
  267. }
  268. float dist_3d(const rs2::depth_frame& frame, pixel u, pixel v)
  269. {
  270. float upixel[2]; // From pixel像素
  271. float upoint[3]; // From point (in 3D)
  272. float vpixel[2]; // To pixel
  273. float vpoint[3]; // To point (in 3D)
  274. // Copy pixels into the arrays (to match rsutil signatures)
  275. // 将像素复制到数组中(以匹配rsutil签名)
  276. upixel[0] = u.first;
  277. upixel[1] = u.second;
  278. vpixel[0] = v.first;
  279. vpixel[1] = v.second;
  280. // Query the frame for distance
  281. // Note: this can be optimized
  282. // It is not recommended to issue an API call for each pixel
  283. // (since the compiler can't inline these)
  284. // However, in this example it is not one of the bottlenecks
  285. // 查询框架的距离
  286.     // 注意:可以优化
  287.     // 不建议为每个像素发出API调用
  288.     //(因为编译器无法内联这些代码)
  289.     // 但是,在此示例中,这不是瓶颈之一
  290. auto udist = frame.get_distance(upixel[0], upixel[1]);
  291. auto vdist = frame.get_distance(vpixel[0], vpixel[1]);
  292. // Deproject from pixel to point in 3D
  293. // 在3D模式下从像素投影到点
  294. rs2_intrinsics intr = frame.get_profile().as<rs2::video_stream_profile>().get_intrinsics(); // Calibration data
  295. rs2_deproject_pixel_to_point(upoint, &intr, upixel, udist);
  296. rs2_deproject_pixel_to_point(vpoint, &intr, vpixel, vdist);
  297. // Calculate euclidean distance between the two points
  298. // 计算两点之间的欧几里得距离
  299. return sqrt(pow(upoint[0] - vpoint[0], 2) +
  300. pow(upoint[1] - vpoint[1], 2) +
  301. pow(upoint[2] - vpoint[2], 2));
  302. }
  303. void draw_line(float x0, float y0, float x1, float y1, int width)
  304. {
  305. glPushAttrib(GL_ENABLE_BIT);
  306. glLineStipple(1, 0x00ff);
  307. glEnable(GL_LINE_STIPPLE);
  308. glLineWidth(width);
  309. glBegin(GL_LINE_STRIP);
  310. glVertex2f(x0, y0);
  311. glVertex2f(x1, y1);
  312. glEnd();
  313. glPopAttrib();
  314. }
  315. void render_simple_distance(const rs2::depth_frame& depth,
  316. const state& s,
  317. const window& app)
  318. {
  319. pixel center;
  320. glColor4f(0.f, 0.0f, 0.0f, 0.2f);
  321. draw_line(s.ruler_start.x * app.width(),
  322. s.ruler_start.y * app.height(),
  323. s.ruler_end.x * app.width(),
  324. s.ruler_end.y * app.height(), 9);
  325. glColor4f(0.f, 0.0f, 0.0f, 0.3f);
  326. draw_line(s.ruler_start.x * app.width(),
  327. s.ruler_start.y * app.height(),
  328. s.ruler_end.x * app.width(),
  329. s.ruler_end.y * app.height(), 7);
  330. glColor4f(1.f, 1.0f, 1.0f, 1.f);
  331. draw_line(s.ruler_start.x * app.width(),
  332. s.ruler_start.y * app.height(),
  333. s.ruler_end.x * app.width(),
  334. s.ruler_end.y * app.height(), 3);
  335. auto from_pixel = s.ruler_start.get_pixel(depth);
  336. auto to_pixel = s.ruler_end.get_pixel(depth);
  337. float air_dist = dist_3d(depth, from_pixel, to_pixel);
  338. center.first = (from_pixel.first + to_pixel.first) / 2;
  339. center.second = (from_pixel.second + to_pixel.second) / 2;
  340. std::stringstream ss;
  341. ss << int(air_dist * 100) << " cm";
  342. auto str = ss.str();
  343. auto x = (float(center.first) / depth.get_width()) * app.width() + 15;
  344. auto y = (float(center.second) / depth.get_height()) * app.height() + 15;
  345. auto w = stb_easy_font_width((char*)str.c_str());
  346. // Draw dark background for the text label
  347. // 为文字标签绘制深色背景
  348. glColor4f(0.f, 0.f, 0.f, 0.4f);
  349. glBegin(GL_TRIANGLES);
  350. glVertex2f(x - 3, y - 10);
  351. glVertex2f(x + w + 2, y - 10);
  352. glVertex2f(x + w + 2, y + 2);
  353. glVertex2f(x + w + 2, y + 2);
  354. glVertex2f(x - 3, y + 2);
  355. glVertex2f(x - 3, y - 10);
  356. glEnd();
  357. // Draw white text label
  358. // 绘制白色文字标签
  359. glColor4f(1.f, 1.f, 1.f, 1.f);
  360. draw_text(x, y, str.c_str());
  361. }
  362. // Implement drag&drop behaviour for the buttons:
  363. // 实现按钮的拖放行为:
  364. void register_glfw_callbacks(window& app, state& app_state)
  365. {
  366. app.on_left_mouse = [&](bool pressed)
  367. {
  368. app_state.mouse_down = pressed;
  369. };
  370. app.on_mouse_move = [&](double x, double y)
  371. {
  372. toggle cursor{ float(x) / app.width(), float(y) / app.height() };
  373. std::vector<toggle*> toggles{
  374. &app_state.ruler_start,
  375. &app_state.ruler_end };
  376. if (app_state.mouse_down)
  377. {
  378. toggle* best = toggles.front();
  379. for (auto&& t : toggles)
  380. {
  381. if (t->dist_2d(cursor) < best->dist_2d(cursor))
  382. {
  383. best = t;
  384. }
  385. }
  386. best->selected = true;
  387. }
  388. else
  389. {
  390. for (auto&& t : toggles) t->selected = false;
  391. }
  392. for (auto&& t : toggles)
  393. {
  394. if (t->selected) *t = cursor;
  395. }
  396. };
  397. }

计算宽度:

  1. import pyrealsense2 as rs
  2. import numpy as np
  3. import cv2
  4. import os
  5. # opencv-haar人脸检测
  6. face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
  7. # Configure depth and color streams
  8. pipeline = rs.pipeline()
  9. config = rs.config()
  10. config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
  11. config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
  12. # Start streaming
  13. pipe_profile = pipeline.start(config)
  14. curr_frame = 0
  15. try:
  16. while True:
  17. # Wait for a coherent pair of frames: depth and color
  18. frames = pipeline.wait_for_frames()
  19. depth_frame = frames.get_depth_frame()
  20. color_frame = frames.get_color_frame()
  21. if frames.size() < 2:
  22. continue
  23. if not depth_frame or not color_frame:
  24. continue
  25. # Intrinsics & Extrinsics
  26. # 深度相机内参矩阵
  27. depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
  28. # RGB相机内参矩阵
  29. color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
  30. # 深度图到彩图的外参RT
  31. depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
  32. color_frame.profile)
  33. # print(depth_intrin.ppx, depth_intrin.ppy)
  34. # Convert images to numpy arrays
  35. depth_image = np.asanyarray(depth_frame.get_data())
  36. color_image = np.asanyarray(color_frame.get_data())
  37. # 将RGB对齐到深度,获取对应下的XYZ
  38. #Color->Depth
  39. align = rs.align(rs.stream.depth)
  40. frameset = align.process(frames)
  41. if frameset.size() < 2:
  42. continue
  43. depth_frame = frameset.get_depth_frame()
  44. color_frame = frameset.get_color_frame()
  45. depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
  46. color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
  47. depth_image = np.asanyarray(depth_frame.get_data())
  48. color_image = np.asanyarray(color_frame.get_data())
  49. # 找到人脸
  50. # find the human face in the color_image
  51. gray = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
  52. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
  53. left = []
  54. for (x, y, w, h) in faces:
  55. # 当前帧大于100
  56. if curr_frame > 100 and curr_frame % 40 == 10:
  57. # 取出人脸的深度图和彩色图
  58. roi_depth_image = depth_image[y:y+h, x:x+w]
  59. roi_color_image = color_image[y:y+h, x:x+w]
  60. # 新建
  61. os.system('mkdir -p ./3d_output/%d' % curr_frame)
  62. # 保存
  63. cv2.imwrite('./3d_output/%d/depth.jpg' %
  64. curr_frame, roi_depth_image)
  65. cv2.imwrite('./3d_output/%d/color.jpg' %
  66. curr_frame, roi_color_image)
  67. # write the depth data in a depth.txt
  68. with open('./3d_output/%d/depth.csv' % curr_frame, 'w') as f:
  69. # W
  70. cols = list(range(x, x+w))
  71. # H
  72. rows = list(range(y, y+h))
  73. for i in rows: #H
  74. for j in cols: #W
  75. # 坐标变换一定要注意检查
  76. # 此时获取的是真实世界坐标的深度
  77. # https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/hpp/rs_frame.hpp#L810
  78. depth = depth_frame.get_distance(j, i) # W,H
  79. # 给定没有失真或反失真系数的图像中的像素坐标和深度,计算相对于同一相机的3D空间中的对应点
  80. # https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/rsutil.h#L67
  81. depth_point = rs.rs2_deproject_pixel_to_point(
  82. depth_intrin, [j, i], depth)
  83. text = "%.5lf, %.5lf, %.5lf\n" % (
  84. depth_point[0], depth_point[1], depth_point[2])
  85. f.write(text)
  86. if i==rows[0]:
  87. left.append(depth_point)
  88. print("Finish writing the depth img")
  89. temp = np.array(left)
  90. index = np.where(temp != 0)[0]
  91. #dist2 = np.sqrt(np.square(left[index[-1]][0] - left[index[0]][0])+np.square(left[index[-1]][1] - left[index[0]][1])+np.square(left[index[-1]][2] - left[index[0]][2]))
  92. # // 计算两点之间的欧几里得距离
  93. # return sqrt(pow(upoint[0] - vpoint[0], 2) +
  94. # pow(upoint[1] - vpoint[1], 2) +
  95. # pow(upoint[2] - vpoint[2], 2));
  96. #这里的距离,收到环境的影响,因为我是直接计算框里面最左端到最右端的距离
  97. #如果把背景框进来,那么你测的是两个背景的宽度
  98. print("dist","---------------------", str(left[index[-1]][0] - left[index[0]][0]))
  99. cv2.putText(color_image, str(left[index[-1]][0] - left[index[0]][0]),
  100. (x, y - 30),
  101. cv2.FONT_HERSHEY_COMPLEX, 1.5, (255, 255, 255))
  102. cv2.rectangle(color_image, (x, y), (x+w, y+h), (255, 0, 0), 2)
  103. # Apply colormap on depth image (image must be converted to 8-bit per pixel first)
  104. depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
  105. depth_image, alpha=0.03), cv2.COLORMAP_JET)
  106. # Stack both images horizontally
  107. images = np.hstack((color_image, depth_colormap))
  108. # Show images
  109. cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
  110. cv2.imshow('RealSense', images)
  111. cv2.waitKey(1)
  112. curr_frame += 1
  113. finally:
  114. # Stop streaming
  115. pipeline.stop()

有一个显示相机位置的py例子:

  1. # License: Apache 2.0. See LICENSE file in root directory.
  2. # Copyright(c) 2015-2017 Intel Corporation. All Rights Reserved.
  3. """
  4. OpenGL Pointcloud viewer with http://pyglet.org
  5. Usage:
  6. ------
  7. Mouse:
  8. Drag with left button to rotate around pivot (thick small axes),
  9. with right button to translate and the wheel to zoom.
  10. Keyboard:
  11. [p] Pause
  12. [r] Reset View
  13. [d] Cycle through decimation values
  14. [z] Toggle point scaling
  15. [x] Toggle point distance attenuation
  16. [c] Toggle color source
  17. [l] Toggle lighting
  18. [f] Toggle depth post-processing
  19. [s] Save PNG (./out.png)
  20. [e] Export points to ply (./out.ply)
  21. [q/ESC] Quit
  22. Notes:
  23. ------
  24. Using deprecated OpenGL (FFP lighting, matrix stack...) however, draw calls
  25. are kept low with pyglet.graphics.* which uses glDrawArrays internally.
  26. Normals calculation is done with numpy on CPU which is rather slow, should really
  27. be done with shaders but was omitted for several reasons - brevity, for lowering
  28. dependencies (pyglet doesn't ship with shader support & recommends pyshaders)
  29. and for reference.
  30. """
  31. import math
  32. import ctypes
  33. import pyglet
  34. import pyglet.gl as gl
  35. import numpy as np
  36. import pyrealsense2 as rs
  37. # https://stackoverflow.com/a/6802723
  38. def rotation_matrix(axis, theta):
  39. """
  40. Return the rotation matrix associated with counterclockwise rotation about
  41. the given axis by theta radians.
  42. """
  43. axis = np.asarray(axis)
  44. axis = axis / math.sqrt(np.dot(axis, axis))
  45. a = math.cos(theta / 2.0)
  46. b, c, d = -axis * math.sin(theta / 2.0)
  47. aa, bb, cc, dd = a * a, b * b, c * c, d * d
  48. bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
  49. return np.array([[aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
  50. [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
  51. [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc]])
  52. class AppState:
  53. def __init__(self, *args, **kwargs):
  54. self.pitch, self.yaw = math.radians(-10), math.radians(-15)
  55. self.translation = np.array([0, 0, 1], np.float32)
  56. self.distance = 2
  57. self.mouse_btns = [False, False, False]
  58. self.paused = False
  59. self.decimate = 0
  60. self.scale = True
  61. self.attenuation = False
  62. self.color = True
  63. self.lighting = False
  64. self.postprocessing = False
  65. def reset(self):
  66. self.pitch, self.yaw, self.distance = 0, 0, 2
  67. self.translation[:] = 0, 0, 1
  68. @property
  69. def rotation(self):
  70. Rx = rotation_matrix((1, 0, 0), math.radians(-self.pitch))
  71. Ry = rotation_matrix((0, 1, 0), math.radians(-self.yaw))
  72. return np.dot(Ry, Rx).astype(np.float32)
  73. state = AppState()
  74. # Configure streams
  75. pipeline = rs.pipeline()
  76. config = rs.config()
  77. config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
  78. # other_stream, other_format = rs.stream.infrared, rs.format.y8
  79. other_stream, other_format = rs.stream.color, rs.format.rgb8
  80. config.enable_stream(other_stream, 640, 480, other_format, 30)
  81. # Start streaming
  82. pipeline.start(config)
  83. profile = pipeline.get_active_profile()
  84. depth_sensor = profile.get_device().first_depth_sensor()
  85. depth_scale = depth_sensor.get_depth_scale()
  86. depth_profile = rs.video_stream_profile(profile.get_stream(rs.stream.depth))
  87. depth_intrinsics = depth_profile.get_intrinsics()
  88. w, h = depth_intrinsics.width, depth_intrinsics.height
  89. # Processing blocks
  90. pc = rs.pointcloud()
  91. decimate = rs.decimation_filter()
  92. decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
  93. colorizer = rs.colorizer()
  94. filters = [rs.disparity_transform(),
  95. rs.spatial_filter(),
  96. rs.temporal_filter(),
  97. rs.disparity_transform(False)]
  98. # pyglet
  99. window = pyglet.window.Window(
  100. config=gl.Config(
  101. double_buffer=True,
  102. samples=8 # MSAA
  103. ),
  104. resizable=True, vsync=True)
  105. keys = pyglet.window.key.KeyStateHandler()
  106. window.push_handlers(keys)
  107. def convert_fmt(fmt):
  108. """rs.format to pyglet format string"""
  109. return {
  110. rs.format.rgb8: 'RGB',
  111. rs.format.bgr8: 'BGR',
  112. rs.format.rgba8: 'RGBA',
  113. rs.format.bgra8: 'BGRA',
  114. rs.format.y8: 'L',
  115. }[fmt]
  116. # Create a VertexList to hold pointcloud data
  117. # Will pre-allocates memory according to the attributes below
  118. vertex_list = pyglet.graphics.vertex_list(
  119. w * h, 'v3f/stream', 't2f/stream', 'n3f/stream')
  120. # Create and allocate memory for our color data
  121. other_profile = rs.video_stream_profile(profile.get_stream(other_stream))
  122. image_data = pyglet.image.ImageData(w, h, convert_fmt(
  123. other_profile.format()), (gl.GLubyte * (w * h * 3))())
  124. fps_display = pyglet.clock.ClockDisplay()
  125. @window.event
  126. def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
  127. w, h = map(float, window.get_size())
  128. if buttons & pyglet.window.mouse.LEFT:
  129. state.yaw -= dx * 0.5
  130. state.pitch -= dy * 0.5
  131. if buttons & pyglet.window.mouse.RIGHT:
  132. dp = np.array((dx / w, -dy / h, 0), np.float32)
  133. state.translation += np.dot(state.rotation, dp)
  134. if buttons & pyglet.window.mouse.MIDDLE:
  135. dz = dy * 0.01
  136. state.translation -= (0, 0, dz)
  137. state.distance -= dz
  138. def handle_mouse_btns(x, y, button, modifiers):
  139. state.mouse_btns[0] ^= (button & pyglet.window.mouse.LEFT)
  140. state.mouse_btns[1] ^= (button & pyglet.window.mouse.RIGHT)
  141. state.mouse_btns[2] ^= (button & pyglet.window.mouse.MIDDLE)
  142. window.on_mouse_press = window.on_mouse_release = handle_mouse_btns
  143. @window.event
  144. def on_mouse_scroll(x, y, scroll_x, scroll_y):
  145. dz = scroll_y * 0.1
  146. state.translation -= (0, 0, dz)
  147. state.distance -= dz
  148. def on_key_press(symbol, modifiers):
  149. if symbol == pyglet.window.key.R:
  150. state.reset()
  151. if symbol == pyglet.window.key.P:
  152. state.paused ^= True
  153. if symbol == pyglet.window.key.D:
  154. state.decimate = (state.decimate + 1) % 3
  155. decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
  156. if symbol == pyglet.window.key.C:
  157. state.color ^= True
  158. if symbol == pyglet.window.key.Z:
  159. state.scale ^= True
  160. if symbol == pyglet.window.key.X:
  161. state.attenuation ^= True
  162. if symbol == pyglet.window.key.L:
  163. state.lighting ^= True
  164. if symbol == pyglet.window.key.F:
  165. state.postprocessing ^= True
  166. if symbol == pyglet.window.key.S:
  167. pyglet.image.get_buffer_manager().get_color_buffer().save('out.png')
  168. if symbol == pyglet.window.key.Q:
  169. window.close()
  170. window.push_handlers(on_key_press)
  171. def axes(size=1, width=1):
  172. """draw 3d axes"""
  173. gl.glLineWidth(width)
  174. pyglet.graphics.draw(6, gl.GL_LINES,
  175. ('v3f', (0, 0, 0, size, 0, 0,
  176. 0, 0, 0, 0, size, 0,
  177. 0, 0, 0, 0, 0, size)),
  178. ('c3f', (1, 0, 0, 1, 0, 0,
  179. 0, 1, 0, 0, 1, 0,
  180. 0, 0, 1, 0, 0, 1,
  181. ))
  182. )
  183. def frustum(intrinsics):
  184. """draw camera's frustum"""
  185. w, h = intrinsics.width, intrinsics.height
  186. batch = pyglet.graphics.Batch()
  187. for d in range(1, 6, 2):
  188. def get_point(x, y):
  189. p = rs.rs2_deproject_pixel_to_point(intrinsics, [x, y], d)
  190. batch.add(2, gl.GL_LINES, None, ('v3f', [0, 0, 0] + p))
  191. return p
  192. top_left = get_point(0, 0)
  193. top_right = get_point(w, 0)
  194. bottom_right = get_point(w, h)
  195. bottom_left = get_point(0, h)
  196. batch.add(2, gl.GL_LINES, None, ('v3f', top_left + top_right))
  197. batch.add(2, gl.GL_LINES, None, ('v3f', top_right + bottom_right))
  198. batch.add(2, gl.GL_LINES, None, ('v3f', bottom_right + bottom_left))
  199. batch.add(2, gl.GL_LINES, None, ('v3f', bottom_left + top_left))
  200. batch.draw()
  201. def grid(size=1, n=10, width=1):
  202. """draw a grid on xz plane"""
  203. gl.glLineWidth(width)
  204. s = size / float(n)
  205. s2 = 0.5 * size
  206. batch = pyglet.graphics.Batch()
  207. for i in range(0, n + 1):
  208. x = -s2 + i * s
  209. batch.add(2, gl.GL_LINES, None, ('v3f', (x, 0, -s2, x, 0, s2)))
  210. for i in range(0, n + 1):
  211. z = -s2 + i * s
  212. batch.add(2, gl.GL_LINES, None, ('v3f', (-s2, 0, z, s2, 0, z)))
  213. batch.draw()
  214. @window.event
  215. def on_draw():
  216. window.clear()
  217. gl.glEnable(gl.GL_DEPTH_TEST)
  218. gl.glEnable(gl.GL_LINE_SMOOTH)
  219. width, height = window.get_size()
  220. gl.glViewport(0, 0, width, height)
  221. gl.glMatrixMode(gl.GL_PROJECTION)
  222. gl.glLoadIdentity()
  223. gl.gluPerspective(60, width / float(height), 0.01, 20)
  224. gl.glMatrixMode(gl.GL_TEXTURE)
  225. gl.glLoadIdentity()
  226. # texcoords are [0..1] and relative to top-left pixel corner, add 0.5 to center
  227. gl.glTranslatef(0.5 / image_data.width, 0.5 / image_data.height, 0)
  228. # texture size may be increased by pyglet to a power of 2
  229. tw, th = image_data.texture.owner.width, image_data.texture.owner.height
  230. gl.glScalef(image_data.width / float(tw),
  231. image_data.height / float(th), 1)
  232. gl.glMatrixMode(gl.GL_MODELVIEW)
  233. gl.glLoadIdentity()
  234. gl.gluLookAt(0, 0, 0, 0, 0, 1, 0, -1, 0)
  235. gl.glTranslatef(0, 0, state.distance)
  236. gl.glRotated(state.pitch, 1, 0, 0)
  237. gl.glRotated(state.yaw, 0, 1, 0)
  238. if any(state.mouse_btns):
  239. axes(0.1, 4)
  240. gl.glTranslatef(0, 0, -state.distance)
  241. gl.glTranslatef(*state.translation)
  242. gl.glColor3f(0.5, 0.5, 0.5)
  243. gl.glPushMatrix()
  244. gl.glTranslatef(0, 0.5, 0.5)
  245. grid()
  246. gl.glPopMatrix()
  247. psz = max(window.get_size()) / float(max(w, h)) if state.scale else 1
  248. gl.glPointSize(psz)
  249. distance = (0, 0, 1) if state.attenuation else (1, 0, 0)
  250. gl.glPointParameterfv(gl.GL_POINT_DISTANCE_ATTENUATION,
  251. (gl.GLfloat * 3)(*distance))
  252. if state.lighting:
  253. ldir = [0.5, 0.5, 0.5] # world-space lighting
  254. ldir = np.dot(state.rotation, (0, 0, 1)) # MeshLab style lighting
  255. ldir = list(ldir) + [0] # w=0, directional light
  256. gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, (gl.GLfloat * 4)(*ldir))
  257. gl.glLightfv(gl.GL_LIGHT0, gl.GL_DIFFUSE,
  258. (gl.GLfloat * 3)(1.0, 1.0, 1.0))
  259. gl.glLightfv(gl.GL_LIGHT0, gl.GL_AMBIENT,
  260. (gl.GLfloat * 3)(0.75, 0.75, 0.75))
  261. gl.glEnable(gl.GL_LIGHT0)
  262. gl.glEnable(gl.GL_NORMALIZE)
  263. gl.glEnable(gl.GL_LIGHTING)
  264. gl.glColor3f(1, 1, 1)
  265. texture = image_data.get_texture()
  266. gl.glEnable(texture.target)
  267. gl.glBindTexture(texture.target, texture.id)
  268. gl.glTexParameteri(
  269. gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
  270. # comment this to get round points with MSAA on
  271. gl.glEnable(gl.GL_POINT_SPRITE)
  272. if not state.scale and not state.attenuation:
  273. gl.glDisable(gl.GL_MULTISAMPLE) # for true 1px points with MSAA on
  274. vertex_list.draw(gl.GL_POINTS)
  275. gl.glDisable(texture.target)
  276. if not state.scale and not state.attenuation:
  277. gl.glEnable(gl.GL_MULTISAMPLE)
  278. gl.glDisable(gl.GL_LIGHTING)
  279. gl.glColor3f(0.25, 0.25, 0.25)
  280. frustum(depth_intrinsics)
  281. axes()
  282. gl.glMatrixMode(gl.GL_PROJECTION)
  283. gl.glLoadIdentity()
  284. gl.glOrtho(0, width, 0, height, -1, 1)
  285. gl.glMatrixMode(gl.GL_MODELVIEW)
  286. gl.glLoadIdentity()
  287. gl.glMatrixMode(gl.GL_TEXTURE)
  288. gl.glLoadIdentity()
  289. gl.glDisable(gl.GL_DEPTH_TEST)
  290. fps_display.draw()
  291. def run(dt):
  292. global w, h
  293. window.set_caption("RealSense (%dx%d) %dFPS (%.2fms) %s" %
  294. (w, h, 0 if dt == 0 else 1.0 / dt, dt * 1000,
  295. "PAUSED" if state.paused else ""))
  296. if state.paused:
  297. return
  298. success, frames = pipeline.try_wait_for_frames(timeout_ms=0)
  299. if not success:
  300. return
  301. depth_frame = frames.get_depth_frame()
  302. other_frame = frames.first(other_stream)
  303. depth_frame = decimate.process(depth_frame)
  304. if state.postprocessing:
  305. for f in filters:
  306. depth_frame = f.process(depth_frame)
  307. # Grab new intrinsics (may be changed by decimation)
  308. depth_intrinsics = rs.video_stream_profile(
  309. depth_frame.profile).get_intrinsics()
  310. w, h = depth_intrinsics.width, depth_intrinsics.height
  311. color_image = np.asanyarray(other_frame.get_data())
  312. colorized_depth = colorizer.colorize(depth_frame)
  313. depth_colormap = np.asanyarray(colorized_depth.get_data())
  314. if state.color:
  315. mapped_frame, color_source = other_frame, color_image
  316. else:
  317. mapped_frame, color_source = colorized_depth, depth_colormap
  318. points = pc.calculate(depth_frame)
  319. pc.map_to(mapped_frame)
  320. # handle color source or size change
  321. fmt = convert_fmt(mapped_frame.profile.format())
  322. global image_data
  323. if (image_data.format, image_data.pitch) != (fmt, color_source.strides[0]):
  324. empty = (gl.GLubyte * (w * h * 3))()
  325. image_data = pyglet.image.ImageData(w, h, fmt, empty)
  326. # copy image data to pyglet
  327. image_data.set_data(fmt, color_source.strides[0], color_source.ctypes.data)
  328. verts = np.asarray(points.get_vertices(2)).reshape(h, w, 3)
  329. texcoords = np.asarray(points.get_texture_coordinates(2))
  330. if len(vertex_list.vertices) != verts.size:
  331. vertex_list.resize(verts.size // 3)
  332. # need to reassign after resizing
  333. vertex_list.vertices = verts.ravel()
  334. vertex_list.tex_coords = texcoords.ravel()
  335. # copy our data to pre-allocated buffers, this is faster than assigning...
  336. # pyglet will take care of uploading to GPU
  337. def copy(dst, src):
  338. """copy numpy array to pyglet array"""
  339. # timeit was mostly inconclusive, favoring slice assignment for safety
  340. np.array(dst, copy=False)[:] = src.ravel()
  341. # ctypes.memmove(dst, src.ctypes.data, src.nbytes)
  342. copy(vertex_list.vertices, verts)
  343. copy(vertex_list.tex_coords, texcoords)
  344. if state.lighting:
  345. # compute normals
  346. dy, dx = np.gradient(verts, axis=(0, 1))
  347. n = np.cross(dx, dy)
  348. # can use this, np.linalg.norm or similar to normalize, but OpenGL can do this for us, see GL_NORMALIZE above
  349. # norm = np.sqrt((n*n).sum(axis=2, keepdims=True))
  350. # np.divide(n, norm, out=n, where=norm != 0)
  351. # import cv2
  352. # n = cv2.bilateralFilter(n, 5, 1, 1)
  353. copy(vertex_list.normals, n)
  354. if keys[pyglet.window.key.E]:
  355. points.export_to_ply('./out.ply', mapped_frame)
  356. pyglet.clock.schedule(run)
  357. try:
  358. pyglet.app.run()
  359. finally:
  360. pipeline.stop()

结合改进:

  1. import pyrealsense2 as rs
  2. import numpy as np
  3. import cv2
  4. import os
  5. # opencv-haar人脸检测
  6. face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
  7. # Configure depth and color streams
  8. pipeline = rs.pipeline()
  9. config = rs.config()
  10. config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
  11. config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
  12. # Start streaming
  13. pipe_profile = pipeline.start(config)
  14. curr_frame = 0
  15. try:
  16. while True:
  17. # Wait for a coherent pair of frames: depth and color
  18. frames = pipeline.wait_for_frames()
  19. depth_frame = frames.get_depth_frame()
  20. color_frame = frames.get_color_frame()
  21. if frames.size() < 2:
  22. continue
  23. if not depth_frame or not color_frame:
  24. continue
  25. # Intrinsics & Extrinsics
  26. # 深度相机内参矩阵
  27. depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
  28. # RGB相机内参矩阵
  29. color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
  30. # 深度图到彩图的外参RT
  31. depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
  32. color_frame.profile)
  33. depth_value = 0.5
  34. depth_pixel = [depth_intrin.ppx, depth_intrin.ppy]
  35. depth_point = rs.rs2_deproject_pixel_to_point(depth_intrin, depth_pixel, depth_value)
  36. print(depth_point)
  37. # print(depth_intrin.ppx, depth_intrin.ppy)
  38. # Convert images to numpy arrays
  39. depth_image = np.asanyarray(depth_frame.get_data())
  40. color_image = np.asanyarray(color_frame.get_data())
  41. # 将RGB对齐到深度,获取对应下的XYZ
  42. #Color->Depth
  43. align = rs.align(rs.stream.depth)
  44. frameset = align.process(frames)
  45. if frameset.size() < 2:
  46. continue
  47. depth_frame = frameset.get_depth_frame()
  48. color_frame = frameset.get_color_frame()
  49. depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
  50. color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
  51. depth_image = np.asanyarray(depth_frame.get_data())
  52. color_image = np.asanyarray(color_frame.get_data())
  53. # 找到人脸
  54. # find the human face in the color_image
  55. gray = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
  56. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
  57. left = []
  58. for (x, y, w, h) in faces:
  59. # 当前帧大于100
  60. if curr_frame > 100 and curr_frame % 40 == 10:
  61. # 取出人脸的深度图和彩色图
  62. roi_depth_image = depth_image[y:y+h, x:x+w]
  63. roi_color_image = color_image[y:y+h, x:x+w]
  64. # 新建
  65. os.system('mkdir -p ./3d_output/%d' % curr_frame)
  66. # 保存
  67. cv2.imwrite('./3d_output/%d/depth.jpg' %
  68. curr_frame, roi_depth_image)
  69. cv2.imwrite('./3d_output/%d/color.jpg' %
  70. curr_frame, roi_color_image)
  71. # write the depth data in a depth.txt
  72. with open('./3d_output/%d/depth.csv' % curr_frame, 'w') as f:
  73. # W
  74. cols = list(range(x, x+w))
  75. # H
  76. rows = list(range(y, y+h))
  77. for i in rows: #H
  78. for j in cols: #W
  79. # 坐标变换一定要注意检查
  80. # 此时获取的是真实世界坐标的深度
  81. # https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/hpp/rs_frame.hpp#L810
  82. depth = depth_frame.get_distance(j, i) # W,H
  83. # 给定没有失真或反失真系数的图像中的像素坐标和深度,计算相对于同一相机的3D空间中的对应点
  84. # https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/rsutil.h#L67
  85. depth_point = rs.rs2_deproject_pixel_to_point(
  86. depth_intrin, [j, i], depth)
  87. text = "%.5lf, %.5lf, %.5lf\n" % (
  88. depth_point[0], depth_point[1], depth_point[2])
  89. f.write(text)
  90. if i==rows[0]:
  91. left.append(depth_point)
  92. print("Finish writing the depth img")
  93. temp = np.array(left)
  94. index = np.where(temp != 0)[0]
  95. #dist2 = np.sqrt(np.square(left[index[-1]][0] - left[index[0]][0])+np.square(left[index[-1]][1] - left[index[0]][1])+np.square(left[index[-1]][2] - left[index[0]][2]))
  96. # // 计算两点之间的欧几里得距离
  97. # return sqrt(pow(upoint[0] - vpoint[0], 2) +
  98. # pow(upoint[1] - vpoint[1], 2) +
  99. # pow(upoint[2] - vpoint[2], 2));
  100. #这里的距离,收到环境的影响,因为我是直接计算框里面最左端到最右端的距离
  101. #如果把背景框进来,那么你测的是两个背景的宽度
  102. print("dist","---------------------", str(left[index[-1]][0] - left[index[0]][0]))
  103. # 这里要做很多工作,离群噪声点的去除,去除后矩阵的真实大小判断 很多行,哪一行是最真实的距离
  104. cv2.putText(color_image, str(left[index[-1]][0] - left[index[0]][0]),
  105. (x, y - 30),
  106. cv2.FONT_HERSHEY_COMPLEX, 1.5, (255, 255, 255))
  107. cv2.rectangle(color_image, (x, y), (x+w, y+h), (255, 0, 0), 2)
  108. # Apply colormap on depth image (image must be converted to 8-bit per pixel first)
  109. depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
  110. depth_image, alpha=0.03), cv2.COLORMAP_JET)
  111. # Stack both images horizontally
  112. images = np.hstack((color_image, depth_colormap))
  113. # Show images
  114. cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
  115. cv2.imshow('RealSense', images)
  116. cv2.waitKey(1)
  117. curr_frame += 1
  118. finally:
  119. # Stop streaming
  120. pipeline.stop()

修改版:

  1. import pyrealsense2 as rs
  2. import numpy as np
  3. import cv2
  4. import os
  5. # opencv-haar人脸检测
  6. face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
  7. # Configure depth and color streams
  8. pipeline = rs.pipeline()
  9. config = rs.config()
  10. config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
  11. config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
  12. # Start streaming
  13. pipe_profile = pipeline.start(config)
  14. curr_frame = 0
  15. try:
  16. while True:
  17. # Wait for a coherent pair of frames: depth and color
  18. frames = pipeline.wait_for_frames()
  19. depth_frame = frames.get_depth_frame()
  20. color_frame = frames.get_color_frame()
  21. if frames.size() < 2:
  22. continue
  23. if not depth_frame or not color_frame:
  24. continue
  25. # Intrinsics & Extrinsics
  26. # 深度相机内参矩阵
  27. depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
  28. # RGB相机内参矩阵
  29. color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
  30. # 深度图到彩图的外参RT
  31. depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
  32. color_frame.profile)
  33. depth_value = 0.5
  34. depth_pixel = [depth_intrin.ppx, depth_intrin.ppy]
  35. depth_point = rs.rs2_deproject_pixel_to_point(depth_intrin, depth_pixel, depth_value)
  36. #print(depth_point)
  37. # print(depth_intrin.ppx, depth_intrin.ppy)
  38. # Convert images to numpy arrays
  39. depth_image = np.asanyarray(depth_frame.get_data())
  40. color_image = np.asanyarray(color_frame.get_data())
  41. # 将RGB对齐到深度,获取对应下的XYZ
  42. #Color->Depth
  43. align = rs.align(rs.stream.depth)
  44. frameset = align.process(frames)
  45. if frameset.size() < 2:
  46. continue
  47. depth_frame = frameset.get_depth_frame()
  48. color_frame = frameset.get_color_frame()
  49. depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
  50. color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
  51. depth_image = np.asanyarray(depth_frame.get_data())
  52. color_image = np.asanyarray(color_frame.get_data())
  53. # 找到人脸
  54. # find the human face in the color_image
  55. gray = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
  56. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
  57. left = []
  58. for (x, y, w, h) in faces:
  59. # 当前帧大于100
  60. if curr_frame > 100 and curr_frame % 40 == 10:
  61. # 取出人脸的深度图和彩色图
  62. roi_depth_image = depth_image[y:y+h, x:x+w]
  63. roi_color_image = color_image[y:y+h, x:x+w]
  64. # W
  65. cols = list(range(x, x+w))
  66. # H
  67. rows = list(range(y, y+h))
  68. for i in rows: #H
  69. for j in cols: #W
  70. # 坐标变换一定要注意检查
  71. # 此时获取的是真实世界坐标的深度
  72. # https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/hpp/rs_frame.hpp#L810
  73. depth = depth_frame.get_distance(j, i) # W,H
  74. # 给定没有失真或反失真系数的图像中的像素坐标和深度,计算相对于同一相机的3D空间中的对应点
  75. # https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/rsutil.h#L67
  76. depth_point = rs.rs2_deproject_pixel_to_point(
  77. depth_intrin, [j, i], depth)
  78. text = "%.5lf, %.5lf, %.5lf\n" % (
  79. depth_point[0], depth_point[1], depth_point[2])
  80. #f.write(text)
  81. if i==rows[0]:
  82. left.append(depth_point)
  83. #print("Finish writing the depth img")
  84. # temp = np.array(left)
  85. # # 求均值
  86. # _mean = np.mean(temp, axis=0)
  87. # # 求方差
  88. # _var = np.var(temp, axis=0)
  89. # minmean = _mean - 1 * abs(_mean)
  90. # maxmean = _mean + 1 * abs(_mean)
  91. # minvar = _var - 1 * abs(_var)
  92. # maxvar = _var + 1 * abs(_var)
  93. def non_zero_mean(np_arr, axis):
  94. exist = (np_arr != 0)
  95. num = np_arr.sum(axis=axis)
  96. den = exist.sum(axis=axis)
  97. return num / den
  98. temp = np.array(left)
  99. # 求均值
  100. _mean = non_zero_mean(temp, axis=0)
  101. # 求方差
  102. _var = np.var(temp, axis=0)
  103. minmean = _mean - 1 * abs(_mean)
  104. maxmean = _mean + 1 * abs(_mean)
  105. minvar = _var - 1 * abs(_var)
  106. maxvar = _var + 1 * abs(_var)
  107. index = []
  108. i = 0 # H
  109. for j in range(len(cols)): # W
  110. if temp[j][0] != 0 and temp[j][1] != 0 and temp[j][2] != 0:
  111. if temp[j][0]>minmean[0] and temp[j][0]<maxmean[0]:
  112. if temp[j][1] > minmean[1] and temp[j][1] < maxmean[1]:
  113. if temp[j][2] > minmean[2] and temp[j][2] < maxmean[2]:
  114. index.append(j)
  115. #dist2 = np.sqrt(np.square(left[index[-1]][0] - left[index[0]][0])+np.square(left[index[-1]][1] - left[index[0]][1])+np.square(left[index[-1]][2] - left[index[0]][2]))
  116. # // 计算两点之间的欧几里得距离
  117. # return sqrt(pow(upoint[0] - vpoint[0], 2) +
  118. # pow(upoint[1] - vpoint[1], 2) +
  119. # pow(upoint[2] - vpoint[2], 2));
  120. #这里的距离,收到环境的影响,因为我是直接计算框里面最左端到最右端的距离
  121. #如果把背景框进来,那么你测的是两个背景的宽度
  122. if len(index) > (len(cols)/2):
  123. # 新建
  124. os.system('mkdir -p ./3d_output/%d' % curr_frame)
  125. # 保存
  126. cv2.imwrite('./3d_output/%d/depth.jpg' %
  127. curr_frame, roi_depth_image)
  128. cv2.imwrite('./3d_output/%d/color.jpg' %
  129. curr_frame, roi_color_image)
  130. print("dist","---------------------", str(left[index[-1]][0] - left[index[0]][0]))
  131. # 这里要做很多工作,离群噪声点的去除,去除后矩阵的真实大小判断 很多行,哪一行是最真实的距离
  132. cv2.putText(color_image, str(left[index[-1]][0] - left[index[0]][0]),
  133. (x, y - 30),
  134. cv2.FONT_HERSHEY_COMPLEX, 1.5, (255, 255, 255))
  135. cv2.rectangle(color_image, (x, y), (x+w, y+h), (255, 0, 0), 2)
  136. # Apply colormap on depth image (image must be converted to 8-bit per pixel first)
  137. depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
  138. depth_image, alpha=0.03), cv2.COLORMAP_JET)
  139. # Stack both images horizontally
  140. images = np.hstack((color_image, depth_colormap))
  141. # Show images
  142. cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
  143. cv2.imshow('RealSense', images)
  144. cv2.waitKey(1)
  145. curr_frame += 1
  146. finally:
  147. # Stop streaming
  148. pipeline.stop()

https://github.com/IntelRealSense/librealsense/issues/2351

https://github.com/IntelRealSense/librealsense/issues/2343

https://dev.intelrealsense.com/docs/rs-measure

https://forums.intel.com/s/question/0D50P0000490TLGSA2/measuring-length-of-object-using-depth-and-rgb-frames?language=en_US

https://intelrealsense.github.io/librealsense/python_docs/_generated/pyrealsense2.html

https://github.com/IntelRealSense/librealsense/tree/master/wrappers/python/examples/box_dimensioner_multicam

计算速度的例子

https://answers.opencv.org/question/209387/measuring-the-speed-of-an-object-with-variable-distance-from-camera/

计算体积的例子

https://github.com/IntelRealSense/librealsense/issues/4612

https://github.com/IntelRealSense/librealsense/tree/master/wrappers/python/examples/box_dimensioner_multicam

 

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

闽ICP备14008679号