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
config = rs.config()
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
例子:
import cv2 # state of the art computer vision algorithms library
import numpy as np # fundamental package for scientific computing
import matplotlib.pyplot as plt # 2D plotting library producing publication quality figures
import pyrealsense2 as rs # Intel RealSense cross-platform open-source API
print("Environment Ready")
# Setup:
pipe = rs.pipeline()
cfg = rs.config()
#cfg.enable_device_from_file("../object_detection.bag")
cfg.enable_stream(rs.stream.depth, 640, 360, rs.format.z16, 30)
#cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
cfg.enable_stream(rs.stream.color, 640, 480, rs.format.rgb8, 30)
profile = pipe.start(cfg)
# Skip 5 first frames to give the Auto-Exposure time to adjust
for x in range(100):
pipe.wait_for_frames()
# Store next frameset for later processing:
frameset = pipe.wait_for_frames()
color_frame = frameset.get_color_frame()
depth_frame = frameset.get_depth_frame()
# Cleanup:
pipe.stop()
print("Frames Captured")
color = np.asanyarray(color_frame.get_data())
plt.rcParams["axes.grid"] = False
plt.rcParams['figure.figsize'] = [12, 6]
plt.imshow(color)
plt.show()
colorizer = rs.colorizer()
colorized_depth = np.asanyarray(colorizer.colorize(depth_frame).get_data())
plt.imshow(colorized_depth)
plt.show()
# Create alignment primitive with color as its target stream:
align = rs.align(rs.stream.color)
frameset = align.process(frameset)
# Update color and depth frames:
aligned_depth_frame = frameset.get_depth_frame()
colorized_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
# Show the two frames together:
images = np.hstack((color, colorized_depth))
plt.imshow(images)
plt.show()
# Standard OpenCV boilerplate for running the net:
height, width = color.shape[:2]
expected = 300
aspect = width / height
resized_image = cv2.resize(color, (round(expected * aspect), expected))
crop_start = round(expected * (aspect - 1) / 2)
crop_img = resized_image[0:expected, crop_start:crop_start+expected]
net = cv2.dnn.readNetFromCaffe("./MobileNetSSD_deploy.prototxt", "./MobileNetSSD_deploy.caffemodel")
inScaleFactor = 0.007843
meanVal = 127.53
classNames = ("background", "aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair",
"cow", "diningtable", "dog", "horse",
"motorbike", "person", "pottedplant",
"sheep", "sofa", "train", "tvmonitor")
blob = cv2.dnn.blobFromImage(crop_img, inScaleFactor, (expected, expected), meanVal, False)
net.setInput(blob, "data")
detections = net.forward("detection_out")
label = detections[0,0,0,1]
conf = detections[0,0,0,2]
xmin = detections[0,0,0,3]
ymin = detections[0,0,0,4]
xmax = detections[0,0,0,5]
ymax = detections[0,0,0,6]
className = classNames[int(label)]
cv2.rectangle(crop_img, (int(xmin * expected), int(ymin * expected)),
(int(xmax * expected), int(ymax * expected)), (255, 255, 255), 2)
cv2.putText(crop_img, className,
(int(xmin * expected), int(ymin * expected) - 5),
cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
plt.imshow(crop_img)
plt.show()
scale = height / expected
xmin_depth = int((xmin * expected + crop_start) * scale)
ymin_depth = int((ymin * expected) * scale)
xmax_depth = int((xmax * expected + crop_start) * scale)
ymax_depth = int((ymax * expected) * scale)
xmin_depth,ymin_depth,xmax_depth,ymax_depth
cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
(xmax_depth, ymax_depth), (255, 255, 255), 2)
plt.imshow(colorized_depth)
plt.show()
depth = np.asanyarray(aligned_depth_frame.get_data())
# Crop depth data:
depth = depth[xmin_depth:xmax_depth,ymin_depth:ymax_depth].astype(float)
# Get data scale from the device and convert to meters
depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
depth = depth * depth_scale
dist,_,_,_ = cv2.mean(depth)
print("Detected a {0} {1:.3} meters away.".format(className, dist))
注释修改版:
# -*-coding:utf-8-*-
import cv2 # state of the art computer vision algorithms library
import numpy as np # fundamental package for scientific computing
import matplotlib.pyplot as plt # 2D plotting library producing publication quality figures
import pyrealsense2 as rs # Intel RealSense cross-platform open-source API
print("Environment Ready")
# 创建一个管道
pipe = rs.pipeline()
# 配置要流式传输的管道
# 颜色和深度流的不同分辨率
cfg = rs.config()
#cfg.enable_device_from_file("../object_detection.bag")
#1280, 720
cfg.enable_stream(rs.stream.depth, 640, 360, rs.format.z16, 30)
#cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
cfg.enable_stream(rs.stream.color, 640, 480, rs.format.rgb8, 30)
# 开始流式传输
profile = pipe.start(cfg)
# 跳过前300帧以设置自动曝光时间
for x in range(100):
pipe.wait_for_frames()
# 拿到301帧
frameset = pipe.wait_for_frames()
# RGB图
color_frame = frameset.get_color_frame()
# 深度图
depth_frame = frameset.get_depth_frame()
# 停止管道传输
pipe.stop()
print("Frames Captured")
# 显示RGB颜色图像color_frame
color = np.asanyarray(color_frame.get_data())
# 一些可视化显示设置,不用管
plt.rcParams["axes.grid"] = False
plt.rcParams['figure.figsize'] = [12, 6]
plt.imshow(color)
plt.show()
# 显示深度图
# (360, 640) uint16
depth_image_ori = np.asanyarray(depth_frame.get_data())
plt.imshow(depth_image_ori)
plt.show()
# https://github.com/IntelRealSense/librealsense/issues/3665
# 不使用int8是因为精度不够cm
depth_image_ori_int8 = depth_image_ori.astype('uint8')
plt.imshow(depth_image_ori_int8)
plt.show()
# 创建colorizer滤波对象 将深度图映射成彩色图像显示
colorizer = rs.colorizer()
colorized_depth = np.asanyarray(colorizer.colorize(depth_frame).get_data())
plt.imshow(colorized_depth)
plt.show()
# 创建对齐对象
# rs.align允许我们执行深度帧与其他帧的对齐
# “frameset”是我们计划对齐深度帧的流类型。
# 将深度框与颜色框对齐
# 将深度对齐到颜色
align = rs.align(rs.stream.color)
frameset = align.process(frameset)
# 获取对齐更新后的深度图
aligned_depth_frame = frameset.get_depth_frame()
# 将深度图映射成彩色图像显示
colorized_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
# np.vstack():在竖直方向上堆叠
# np.hstack():在水平方向上平铺
images = np.hstack((color, colorized_depth))
plt.imshow(images)
plt.show()
# np.vstack():在竖直方向上堆叠
# np.hstack():在水平方向上平铺
images = np.vstack((color, colorized_depth))
plt.imshow(images)
plt.show()
# 通过对齐后的深度图,对齐原始RGB:color_frame,保存彩色点云
pc = rs.pointcloud()
pc.map_to(color_frame)
points = pc.calculate(aligned_depth_frame)
points.export_to_ply('./out.ply', color_frame)
#pcd = read_point_cloud(file_path)
# Visualize PLY
#draw_geometries([pcd])
#pc.map_to(colorizer.colorize(aligned_depth_frame))
#points.export_to_ply('./out.ply', colorizer.colorize(aligned_depth_frame))
# 480*640*3
height, width = color.shape[:2]
expected = 300
# 1.333333... 原始图像的宽高比
aspect = width / height
# 300*400*3 新的图像也满足此宽高比
resized_image = cv2.resize(color, (round(expected * aspect), expected))
# 50
crop_start = round(expected * (aspect - 1) / 2)
# 300*300*3 H,W
crop_img = resized_image[0:expected, crop_start:crop_start+expected]
plt.imshow(crop_img)
plt.show()
# VOC目标检测网络
net = cv2.dnn.readNetFromCaffe("./MobileNetSSD_deploy.prototxt", "./MobileNetSSD_deploy.caffemodel")
inScaleFactor = 0.007843
meanVal = 127.53
classNames = ("background", "aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair",
"cow", "diningtable", "dog", "horse",
"motorbike", "person", "pottedplant",
"sheep", "sofa", "train", "tvmonitor")
blob = cv2.dnn.blobFromImage(crop_img, inScaleFactor, (expected, expected), meanVal, False)
net.setInput(blob, "data")
# 1*1*100*7[1-6]
detections = net.forward("detection_out")
# 输出检测结果
# label = detections[0,0,0,1]
# conf = detections[0,0,0,2]
# xmin = detections[0,0,0,3]
# ymin = detections[0,0,0,4]
# xmax = detections[0,0,0,5]
# ymax = detections[0,0,0,6]
# className = classNames[int(label)]
# cv2.rectangle(crop_img, (int(xmin * expected), int(ymin * expected)),
# (int(xmax * expected), int(ymax * expected)), (255, 255, 255), 2)
# cv2.putText(crop_img, className,
# (int(xmin * expected), int(ymin * expected) - 5),
# cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
# plt.imshow(crop_img)
# plt.show()
# scale = height / expected
# xmin_depth = int((xmin * expected + crop_start) * scale)
# ymin_depth = int((ymin * expected) * scale)
# xmax_depth = int((xmax * expected + crop_start) * scale)
# ymax_depth = int((ymax * expected) * scale)
# xmin_depth,ymin_depth,xmax_depth,ymax_depth
# cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
# (xmax_depth, ymax_depth), (255, 255, 255), 2)
# plt.imshow(colorized_depth)
# plt.show()
label1 = detections[0,0,:,1]
conf1 = detections[0,0,:,2]
xmin1 = detections[0,0,:,3]
ymin1 = detections[0,0,:,4]
xmax1 = detections[0,0,:,5]
ymax1 = detections[0,0,:,6]
# 获取满足阈值的框
# 框的x1y1 x2y2 是百分比,相对于300*300
inds = np.where(conf1[:] > 0.3)[0]
for index in inds:
className = classNames[int(label1[index])]
cv2.rectangle(crop_img, (int(xmin1[index] * expected), int(ymin1[index] * expected)),
(int(xmax1[index] * expected), int(ymax1[index] * expected)), (255, 255, 255), 2)
cv2.putText(crop_img, className,
(int(xmin1[index] * expected), int(ymin1[index] * expected) - 5),
cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
plt.imshow(crop_img)
plt.show()
# 对于300,原始图像的扩大比为多少
# 对齐后的深度图:aligned_depth_frame
# 对齐后的深度图的彩色图:colorized_depth
# xmin1[index] * expected 300*300检测图的坐标
# xmin1[index] * expected + crop_start 300*400*3的坐标
# (xmin1[index] * expected + crop_start) * scale 480*640*3的坐标
depth = np.asanyarray(aligned_depth_frame.get_data())
depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
aa = profile.get_device()
scale = height / expected
from decimal import Decimal
for index in inds:
xmin_depth = int((xmin1[index] * expected + crop_start) * scale)
ymin_depth = int((ymin1[index] * expected) * scale)
xmax_depth = int((xmax1[index] * expected + crop_start) * scale)
ymax_depth = int((ymax1[index] * expected) * scale)
#xmin_depth,ymin_depth,xmax_depth,ymax_depth
#depth_temp = depth[xmin_depth:xmax_depth, ymin_depth:ymax_depth].astype(float)
depth_temp = depth[ymin_depth:ymax_depth, xmin_depth:xmax_depth].astype(float)
depth_temp = depth_temp * depth_scale
dist, _, _, _ = cv2.mean(depth_temp)
cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
(xmax_depth, ymax_depth), (255, 255, 255), 2)
# 取小数点后3位
dist_temp = Decimal(dist).quantize(Decimal('0.000'))
cv2.putText(colorized_depth, str(dist_temp),
(xmin_depth, ymin_depth - 5),
cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
plt.imshow(colorized_depth)
plt.show()
plt.close()
# # 对齐后的深度图:aligned_depth_frame
# # 对齐后的深度图的彩色图:colorized_depth
# depth = np.asanyarray(aligned_depth_frame.get_data())
# # crop深度数据
# depth = depth[xmin_depth:xmax_depth,ymin_depth:ymax_depth].astype(float)
# # 计算深度
# # 设备获取数据比例并转换为m
# depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
# depth = depth * depth_scale
# # 取均值获取到物体的距离
# dist,_,_,_ = cv2.mean(depth)
# print("Detected a {0} {1:.3} meters away.".format(className, dist))
改一改:
# -*-coding:utf-8-*-
import cv2 # state of the art computer vision algorithms library
import numpy as np # fundamental package for scientific computing
import matplotlib.pyplot as plt # 2D plotting library producing publication quality figures
import pyrealsense2 as rs # Intel RealSense cross-platform open-source API
print("Environment Ready")
# 创建一个管道
pipe = rs.pipeline()
# 配置要流式传输的管道
# 颜色和深度流的不同分辨率
cfg = rs.config()
#cfg.enable_device_from_file("./object_detection.bag")
#cfg.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
#cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
#1280, 720
cfg.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
#cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
cfg.enable_stream(rs.stream.color, 1280, 720, rs.format.rgb8, 30)
# 开始流式传输
profile = pipe.start(cfg)
# 跳过前300帧以设置自动曝光时间
for x in range(100):
pipe.wait_for_frames()
# 拿到301帧
frameset = pipe.wait_for_frames()
# RGB图
color_frame = frameset.get_color_frame()
# 深度图
depth_frame = frameset.get_depth_frame()
# 停止管道传输
pipe.stop()
print("Frames Captured")
# 获取内参外参矩阵
# Intrinsics & Extrinsics
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
# 外参矩阵-深度图相对于彩色图像的外参
depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
color_frame.profile)
print("内参ppx,ppy",depth_intrin.ppx, ':', depth_intrin.ppy)
print("内参矩阵",depth_intrin)
# 显示RGB颜色图像color_frame
color = np.asanyarray(color_frame.get_data())
# 一些可视化显示设置,不用管
plt.rcParams["axes.grid"] = False
plt.rcParams['figure.figsize'] = [12, 6]
plt.imshow(color)
plt.show()
# 显示深度图
# (360, 640) uint16
depth_image_ori = np.asanyarray(depth_frame.get_data())
plt.imshow(depth_image_ori)
plt.show()
# https://github.com/IntelRealSense/librealsense/issues/3665
# 不使用int8是因为精度不够cm
depth_image_ori_int8 = depth_image_ori.astype('uint8')
plt.imshow(depth_image_ori_int8)
plt.show()
# 创建colorizer滤波对象 将深度图映射成彩色图像显示
colorizer = rs.colorizer()
colorized_depth = np.asanyarray(colorizer.colorize(depth_frame).get_data())
plt.imshow(colorized_depth)
plt.show()
# 创建对齐对象
# rs.align允许我们执行深度帧与其他帧的对齐
# “frameset”是我们计划对齐深度帧的流类型。
# 将深度框与颜色框对齐
# 将深度对齐到颜色
align = rs.align(rs.stream.color)
frameset = align.process(frameset)
# 获取对齐更新后的深度图
aligned_depth_frame = frameset.get_depth_frame()
# 将深度图映射成彩色图像显示
colorized_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
new_depth_image_array = np.asanyarray(aligned_depth_frame.get_data())
np.save("out_ori.npy",new_depth_image_array)
x = np.load("out_ori.npy")
print(x-new_depth_image_array)
bgr_color = cv2.cvtColor(color,cv2.COLOR_RGB2BGR)
cv2.imwrite("out_ori.jpg",bgr_color)
# np.vstack():在竖直方向上堆叠
# np.hstack():在水平方向上平铺
images = np.hstack((color, colorized_depth))
plt.imshow(images)
plt.show()
# np.vstack():在竖直方向上堆叠
# np.hstack():在水平方向上平铺
images = np.vstack((color, colorized_depth))
plt.imshow(images)
plt.show()
# 通过对齐后的深度图,对齐原始RGB:color_frame,保存彩色点云
pc = rs.pointcloud()
points = rs.points()
pc.map_to(color_frame)
points = pc.calculate(depth_frame)
points.export_to_ply('./out_ori.ply', color_frame)
#pcd = read_point_cloud(file_path)
# Visualize PLY
#draw_geometries([pcd])
#pc.map_to(colorizer.colorize(aligned_depth_frame))
#points.export_to_ply('./out.ply', colorizer.colorize(aligned_depth_frame))
# 480*640*3
height, width = color.shape[:2]
expected = 300
# 1.333333... 原始图像的宽高比
aspect = width / height
# 300*400*3 新的图像也满足此宽高比
resized_image = cv2.resize(color, (round(expected * aspect), expected))
# 50
crop_start = round(expected * (aspect - 1) / 2)
# 300*300*3 H,W
crop_img = resized_image[0:expected, crop_start:crop_start+expected]
plt.imshow(crop_img)
plt.show()
# VOC目标检测网络
net = cv2.dnn.readNetFromCaffe("./MobileNetSSD_deploy.prototxt", "./MobileNetSSD_deploy.caffemodel")
inScaleFactor = 0.007843
meanVal = 127.53
classNames = ("background", "aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair",
"cow", "diningtable", "dog", "horse",
"motorbike", "person", "pottedplant",
"sheep", "sofa", "train", "tvmonitor")
blob = cv2.dnn.blobFromImage(crop_img, inScaleFactor, (expected, expected), meanVal, False)
net.setInput(blob, "data")
# 1*1*100*7[1-6]
detections = net.forward("detection_out")
# 输出检测结果
# label = detections[0,0,0,1]
# conf = detections[0,0,0,2]
# xmin = detections[0,0,0,3]
# ymin = detections[0,0,0,4]
# xmax = detections[0,0,0,5]
# ymax = detections[0,0,0,6]
# className = classNames[int(label)]
# cv2.rectangle(crop_img, (int(xmin * expected), int(ymin * expected)),
# (int(xmax * expected), int(ymax * expected)), (255, 255, 255), 2)
# cv2.putText(crop_img, className,
# (int(xmin * expected), int(ymin * expected) - 5),
# cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
# plt.imshow(crop_img)
# plt.show()
# scale = height / expected
# xmin_depth = int((xmin * expected + crop_start) * scale)
# ymin_depth = int((ymin * expected) * scale)
# xmax_depth = int((xmax * expected + crop_start) * scale)
# ymax_depth = int((ymax * expected) * scale)
# xmin_depth,ymin_depth,xmax_depth,ymax_depth
# cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
# (xmax_depth, ymax_depth), (255, 255, 255), 2)
# plt.imshow(colorized_depth)
# plt.show()
label1 = detections[0,0,:,1]
conf1 = detections[0,0,:,2]
xmin1 = detections[0,0,:,3]
ymin1 = detections[0,0,:,4]
xmax1 = detections[0,0,:,5]
ymax1 = detections[0,0,:,6]
# 获取满足阈值的框
# 框的x1y1 x2y2 是百分比,相对于300*300
inds = np.where(conf1[:] > 0.3)[0]
for index in inds:
className = classNames[int(label1[index])]
cv2.rectangle(crop_img, (int(xmin1[index] * expected), int(ymin1[index] * expected)),
(int(xmax1[index] * expected), int(ymax1[index] * expected)), (255, 255, 255), 2)
cv2.putText(crop_img, className,
(int(xmin1[index] * expected), int(ymin1[index] * expected) - 5),
cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,255,255))
plt.imshow(crop_img)
plt.show()
# 对于300,原始图像的扩大比为多少
# 对齐后的深度图:aligned_depth_frame
# 对齐后的深度图的彩色图:colorized_depth
# xmin1[index] * expected 300*300检测图的坐标
# xmin1[index] * expected + crop_start 300*400*3的坐标
# (xmin1[index] * expected + crop_start) * scale 480*640*3的坐标
depth = np.asanyarray(aligned_depth_frame.get_data())
depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
aa = profile.get_device()
scale = height / expected
from decimal import Decimal
for index in inds:
xmin_depth = int((xmin1[index] * expected + crop_start) * scale)
ymin_depth = int((ymin1[index] * expected) * scale)
xmax_depth = int((xmax1[index] * expected + crop_start) * scale)
ymax_depth = int((ymax1[index] * expected) * scale)
depth_temp = depth[ymin_depth:ymax_depth, xmin_depth:xmax_depth].astype(float)
#print(depth_temp.shape)
depth_temp = depth_temp * depth_scale
#dis = depth_temp[depth_tem,depth_temp]
dist, _, _, _ = cv2.mean(depth_temp)
cv2.rectangle(colorized_depth, (xmin_depth, ymin_depth),
(xmax_depth, ymax_depth), (255, 255, 255), 2)
# 取小数点后3位
dist_temp = Decimal(dist).quantize(Decimal('0.000'))
cv2.putText(colorized_depth, str(dist_temp),
(xmin_depth, ymin_depth - 5),
cv2.FONT_HERSHEY_COMPLEX, 1.5, (255,255,255))
plt.imshow(colorized_depth)
plt.show()
# # 对齐后的深度图:aligned_depth_frame
# # 对齐后的深度图的彩色图:colorized_depth
# depth = np.asanyarray(aligned_depth_frame.get_data())
# # crop深度数据
# depth = depth[xmin_depth:xmax_depth,ymin_depth:ymax_depth].astype(float)
# # 计算深度
# # 设备获取数据比例并转换为m
# depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
# depth = depth * depth_scale
# # 取均值获取到物体的距离
# dist,_,_,_ = cv2.mean(depth)
# print("Detected a {0} {1:.3} meters away.".format(className, dist))
点云程序:
# License: Apache 2.0. See LICENSE file in root directory.
# Copyright(c) 2015-2017 Intel Corporation. All Rights Reserved.
"""
OpenGL Pointcloud viewer with http://pyglet.org
Usage:
------
Mouse:
Drag with left button to rotate around pivot (thick small axes),
with right button to translate and the wheel to zoom.
Keyboard:
[p] Pause
[r] Reset View
[d] Cycle through decimation values
[z] Toggle point scaling
[x] Toggle point distance attenuation
[c] Toggle color source
[l] Toggle lighting
[f] Toggle depth post-processing
[s] Save PNG (./out.png)
[e] Export points to ply (./out.ply)
[q/ESC] Quit
Notes:
------
Using deprecated OpenGL (FFP lighting, matrix stack...) however, draw calls
are kept low with pyglet.graphics.* which uses glDrawArrays internally.
Normals calculation is done with numpy on CPU which is rather slow, should really
be done with shaders but was omitted for several reasons - brevity, for lowering
dependencies (pyglet doesn't ship with shader support & recommends pyshaders)
and for reference.
"""
import math
import ctypes
import pyglet
import pyglet.gl as gl
import numpy as np
import pyrealsense2 as rs
# https://stackoverflow.com/a/6802723
def rotation_matrix(axis, theta):
"""
Return the rotation matrix associated with counterclockwise rotation about
the given axis by theta radians.
"""
axis = np.asarray(axis)
axis = axis / math.sqrt(np.dot(axis, axis))
a = math.cos(theta / 2.0)
b, c, d = -axis * math.sin(theta / 2.0)
aa, bb, cc, dd = a * a, b * b, c * c, d * d
bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
return np.array([[aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
[2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
[2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc]])
class AppState:
def __init__(self, *args, **kwargs):
self.pitch, self.yaw = math.radians(-10), math.radians(-15)
self.translation = np.array([0, 0, 1], np.float32)
self.distance = 2
self.mouse_btns = [False, False, False]
self.paused = False
self.decimate = 0
self.scale = True
self.attenuation = False
self.color = True
self.lighting = False
self.postprocessing = False
def reset(self):
self.pitch, self.yaw, self.distance = 0, 0, 2
self.translation[:] = 0, 0, 1
@property
def rotation(self):
Rx = rotation_matrix((1, 0, 0), math.radians(-self.pitch))
Ry = rotation_matrix((0, 1, 0), math.radians(-self.yaw))
return np.dot(Ry, Rx).astype(np.float32)
state = AppState()
# Configure streams
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
# other_stream, other_format = rs.stream.infrared, rs.format.y8
other_stream, other_format = rs.stream.color, rs.format.rgb8
config.enable_stream(other_stream, 640, 480, other_format, 30)
# Start streaming
pipeline.start(config)
profile = pipeline.get_active_profile()
depth_sensor = profile.get_device().first_depth_sensor()
depth_scale = depth_sensor.get_depth_scale()
depth_profile = rs.video_stream_profile(profile.get_stream(rs.stream.depth))
depth_intrinsics = depth_profile.get_intrinsics()
w, h = depth_intrinsics.width, depth_intrinsics.height
# Processing blocks
pc = rs.pointcloud()
decimate = rs.decimation_filter()
decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
colorizer = rs.colorizer()
filters = [rs.disparity_transform(),
rs.spatial_filter(),
rs.temporal_filter(),
rs.disparity_transform(False)]
# pyglet
window = pyglet.window.Window(
config=gl.Config(
double_buffer=True,
samples=8 # MSAA
),
resizable=True, vsync=True)
keys = pyglet.window.key.KeyStateHandler()
window.push_handlers(keys)
def convert_fmt(fmt):
"""rs.format to pyglet format string"""
return {
rs.format.rgb8: 'RGB',
rs.format.bgr8: 'BGR',
rs.format.rgba8: 'RGBA',
rs.format.bgra8: 'BGRA',
rs.format.y8: 'L',
}[fmt]
# Create a VertexList to hold pointcloud data
# Will pre-allocates memory according to the attributes below
vertex_list = pyglet.graphics.vertex_list(
w * h, 'v3f/stream', 't2f/stream', 'n3f/stream')
# Create and allocate memory for our color data
other_profile = rs.video_stream_profile(profile.get_stream(other_stream))
image_data = pyglet.image.ImageData(w, h, convert_fmt(
other_profile.format()), (gl.GLubyte * (w * h * 3))())
fps_display = pyglet.clock.ClockDisplay()
@window.event
def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
w, h = map(float, window.get_size())
if buttons & pyglet.window.mouse.LEFT:
state.yaw -= dx * 0.5
state.pitch -= dy * 0.5
if buttons & pyglet.window.mouse.RIGHT:
dp = np.array((dx / w, -dy / h, 0), np.float32)
state.translation += np.dot(state.rotation, dp)
if buttons & pyglet.window.mouse.MIDDLE:
dz = dy * 0.01
state.translation -= (0, 0, dz)
state.distance -= dz
def handle_mouse_btns(x, y, button, modifiers):
state.mouse_btns[0] ^= (button & pyglet.window.mouse.LEFT)
state.mouse_btns[1] ^= (button & pyglet.window.mouse.RIGHT)
state.mouse_btns[2] ^= (button & pyglet.window.mouse.MIDDLE)
window.on_mouse_press = window.on_mouse_release = handle_mouse_btns
@window.event
def on_mouse_scroll(x, y, scroll_x, scroll_y):
dz = scroll_y * 0.1
state.translation -= (0, 0, dz)
state.distance -= dz
def on_key_press(symbol, modifiers):
if symbol == pyglet.window.key.R:
state.reset()
if symbol == pyglet.window.key.P:
state.paused ^= True
if symbol == pyglet.window.key.D:
state.decimate = (state.decimate + 1) % 3
decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
if symbol == pyglet.window.key.C:
state.color ^= True
if symbol == pyglet.window.key.Z:
state.scale ^= True
if symbol == pyglet.window.key.X:
state.attenuation ^= True
if symbol == pyglet.window.key.L:
state.lighting ^= True
if symbol == pyglet.window.key.F:
state.postprocessing ^= True
if symbol == pyglet.window.key.S:
pyglet.image.get_buffer_manager().get_color_buffer().save('out.png')
if symbol == pyglet.window.key.Q:
window.close()
window.push_handlers(on_key_press)
def axes(size=1, width=1):
"""draw 3d axes"""
gl.glLineWidth(width)
pyglet.graphics.draw(6, gl.GL_LINES,
('v3f', (0, 0, 0, size, 0, 0,
0, 0, 0, 0, size, 0,
0, 0, 0, 0, 0, size)),
('c3f', (1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1, 0, 0, 1,
))
)
def frustum(intrinsics):
"""draw camera's frustum"""
w, h = intrinsics.width, intrinsics.height
batch = pyglet.graphics.Batch()
for d in range(1, 6, 2):
def get_point(x, y):
p = rs.rs2_deproject_pixel_to_point(intrinsics, [x, y], d)
batch.add(2, gl.GL_LINES, None, ('v3f', [0, 0, 0] + p))
return p
top_left = get_point(0, 0)
top_right = get_point(w, 0)
bottom_right = get_point(w, h)
bottom_left = get_point(0, h)
batch.add(2, gl.GL_LINES, None, ('v3f', top_left + top_right))
batch.add(2, gl.GL_LINES, None, ('v3f', top_right + bottom_right))
batch.add(2, gl.GL_LINES, None, ('v3f', bottom_right + bottom_left))
batch.add(2, gl.GL_LINES, None, ('v3f', bottom_left + top_left))
batch.draw()
def grid(size=1, n=10, width=1):
"""draw a grid on xz plane"""
gl.glLineWidth(width)
s = size / float(n)
s2 = 0.5 * size
batch = pyglet.graphics.Batch()
for i in range(0, n + 1):
x = -s2 + i * s
batch.add(2, gl.GL_LINES, None, ('v3f', (x, 0, -s2, x, 0, s2)))
for i in range(0, n + 1):
z = -s2 + i * s
batch.add(2, gl.GL_LINES, None, ('v3f', (-s2, 0, z, s2, 0, z)))
batch.draw()
@window.event
def on_draw():
window.clear()
gl.glEnable(gl.GL_DEPTH_TEST)
gl.glEnable(gl.GL_LINE_SMOOTH)
width, height = window.get_size()
gl.glViewport(0, 0, width, height)
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.gluPerspective(60, width / float(height), 0.01, 20)
gl.glMatrixMode(gl.GL_TEXTURE)
gl.glLoadIdentity()
# texcoords are [0..1] and relative to top-left pixel corner, add 0.5 to center
gl.glTranslatef(0.5 / image_data.width, 0.5 / image_data.height, 0)
# texture size may be increased by pyglet to a power of 2
tw, th = image_data.texture.owner.width, image_data.texture.owner.height
gl.glScalef(image_data.width / float(tw),
image_data.height / float(th), 1)
gl.glMatrixMode(gl.GL_MODELVIEW)
gl.glLoadIdentity()
gl.gluLookAt(0, 0, 0, 0, 0, 1, 0, -1, 0)
gl.glTranslatef(0, 0, state.distance)
gl.glRotated(state.pitch, 1, 0, 0)
gl.glRotated(state.yaw, 0, 1, 0)
if any(state.mouse_btns):
axes(0.1, 4)
gl.glTranslatef(0, 0, -state.distance)
gl.glTranslatef(*state.translation)
gl.glColor3f(0.5, 0.5, 0.5)
gl.glPushMatrix()
gl.glTranslatef(0, 0.5, 0.5)
grid()
gl.glPopMatrix()
psz = max(window.get_size()) / float(max(w, h)) if state.scale else 1
gl.glPointSize(psz)
distance = (0, 0, 1) if state.attenuation else (1, 0, 0)
gl.glPointParameterfv(gl.GL_POINT_DISTANCE_ATTENUATION,
(gl.GLfloat * 3)(*distance))
if state.lighting:
ldir = [0.5, 0.5, 0.5] # world-space lighting
ldir = np.dot(state.rotation, (0, 0, 1)) # MeshLab style lighting
ldir = list(ldir) + [0] # w=0, directional light
gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, (gl.GLfloat * 4)(*ldir))
gl.glLightfv(gl.GL_LIGHT0, gl.GL_DIFFUSE,
(gl.GLfloat * 3)(1.0, 1.0, 1.0))
gl.glLightfv(gl.GL_LIGHT0, gl.GL_AMBIENT,
(gl.GLfloat * 3)(0.75, 0.75, 0.75))
gl.glEnable(gl.GL_LIGHT0)
gl.glEnable(gl.GL_NORMALIZE)
gl.glEnable(gl.GL_LIGHTING)
gl.glColor3f(1, 1, 1)
texture = image_data.get_texture()
gl.glEnable(texture.target)
gl.glBindTexture(texture.target, texture.id)
gl.glTexParameteri(
gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
# comment this to get round points with MSAA on
gl.glEnable(gl.GL_POINT_SPRITE)
if not state.scale and not state.attenuation:
gl.glDisable(gl.GL_MULTISAMPLE) # for true 1px points with MSAA on
vertex_list.draw(gl.GL_POINTS)
gl.glDisable(texture.target)
if not state.scale and not state.attenuation:
gl.glEnable(gl.GL_MULTISAMPLE)
gl.glDisable(gl.GL_LIGHTING)
gl.glColor3f(0.25, 0.25, 0.25)
frustum(depth_intrinsics)
axes()
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.glOrtho(0, width, 0, height, -1, 1)
gl.glMatrixMode(gl.GL_MODELVIEW)
gl.glLoadIdentity()
gl.glMatrixMode(gl.GL_TEXTURE)
gl.glLoadIdentity()
gl.glDisable(gl.GL_DEPTH_TEST)
fps_display.draw()
def run(dt):
global w, h
window.set_caption("RealSense (%dx%d) %dFPS (%.2fms) %s" %
(w, h, 0 if dt == 0 else 1.0 / dt, dt * 1000,
"PAUSED" if state.paused else ""))
if state.paused:
return
success, frames = pipeline.try_wait_for_frames(timeout_ms=0)
if not success:
return
depth_frame = frames.get_depth_frame()
other_frame = frames.first(other_stream).as_video_frame()
depth_frame = decimate.process(depth_frame)
if state.postprocessing:
for f in filters:
depth_frame = f.process(depth_frame)
# Grab new intrinsics (may be changed by decimation)
depth_intrinsics = rs.video_stream_profile(
depth_frame.profile).get_intrinsics()
w, h = depth_intrinsics.width, depth_intrinsics.height
color_image = np.asanyarray(other_frame.get_data())
colorized_depth = colorizer.colorize(depth_frame)
depth_colormap = np.asanyarray(colorized_depth.get_data())
if state.color:
mapped_frame, color_source = other_frame, color_image
else:
mapped_frame, color_source = colorized_depth, depth_colormap
points = pc.calculate(depth_frame)
pc.map_to(mapped_frame)
# handle color source or size change
fmt = convert_fmt(mapped_frame.profile.format())
global image_data
if (image_data.format, image_data.pitch) != (fmt, color_source.strides[0]):
empty = (gl.GLubyte * (w * h * 3))()
image_data = pyglet.image.ImageData(w, h, fmt, empty)
# copy image data to pyglet
image_data.set_data(fmt, color_source.strides[0], color_source.ctypes.data)
verts = np.asarray(points.get_vertices(2)).reshape(h, w, 3)
texcoords = np.asarray(points.get_texture_coordinates(2))
if len(vertex_list.vertices) != verts.size:
vertex_list.resize(verts.size // 3)
# need to reassign after resizing
vertex_list.vertices = verts.ravel()
vertex_list.tex_coords = texcoords.ravel()
# copy our data to pre-allocated buffers, this is faster than assigning...
# pyglet will take care of uploading to GPU
def copy(dst, src):
"""copy numpy array to pyglet array"""
# timeit was mostly inconclusive, favoring slice assignment for safety
np.array(dst, copy=False)[:] = src.ravel()
# ctypes.memmove(dst, src.ctypes.data, src.nbytes)
copy(vertex_list.vertices, verts)
copy(vertex_list.tex_coords, texcoords)
if state.lighting:
# compute normals
dy, dx = np.gradient(verts, axis=(0, 1))
n = np.cross(dx, dy)
# can use this, np.linalg.norm or similar to normalize, but OpenGL can do this for us, see GL_NORMALIZE above
# norm = np.sqrt((n*n).sum(axis=2, keepdims=True))
# np.divide(n, norm, out=n, where=norm != 0)
# import cv2
# n = cv2.bilateralFilter(n, 5, 1, 1)
copy(vertex_list.normals, n)
if keys[pyglet.window.key.E]:
points.export_to_ply('./out.ply', mapped_frame)
pyglet.clock.schedule(run)
try:
pyglet.app.run()
finally:
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
关于例子:机翻
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
#include // Include RealSense Cross Platform API
#include
#include "example.hpp" // Include short list of convenience functions for rendering
// 包括用于渲染的便捷功能的简短列表
// This example will require several standard data-structures and algorithms:
#define _USE_MATH_DEFINES
#include
#include
#include
#include
计算宽度:
import pyrealsense2 as rs
import numpy as np
import cv2
import os
# opencv-haar人脸检测
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# Configure depth and color streams
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
# Start streaming
pipe_profile = pipeline.start(config)
curr_frame = 0
try:
while True:
# Wait for a coherent pair of frames: depth and color
frames = pipeline.wait_for_frames()
depth_frame = frames.get_depth_frame()
color_frame = frames.get_color_frame()
if frames.size() < 2:
continue
if not depth_frame or not color_frame:
continue
# Intrinsics & Extrinsics
# 深度相机内参矩阵
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
# RGB相机内参矩阵
color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
# 深度图到彩图的外参RT
depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
color_frame.profile)
# print(depth_intrin.ppx, depth_intrin.ppy)
# Convert images to numpy arrays
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# 将RGB对齐到深度,获取对应下的XYZ
#Color->Depth
align = rs.align(rs.stream.depth)
frameset = align.process(frames)
if frameset.size() < 2:
continue
depth_frame = frameset.get_depth_frame()
color_frame = frameset.get_color_frame()
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# 找到人脸
# find the human face in the color_image
gray = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
left = []
for (x, y, w, h) in faces:
# 当前帧大于100
if curr_frame > 100 and curr_frame % 40 == 10:
# 取出人脸的深度图和彩色图
roi_depth_image = depth_image[y:y+h, x:x+w]
roi_color_image = color_image[y:y+h, x:x+w]
# 新建
os.system('mkdir -p ./3d_output/%d' % curr_frame)
# 保存
cv2.imwrite('./3d_output/%d/depth.jpg' %
curr_frame, roi_depth_image)
cv2.imwrite('./3d_output/%d/color.jpg' %
curr_frame, roi_color_image)
# write the depth data in a depth.txt
with open('./3d_output/%d/depth.csv' % curr_frame, 'w') as f:
# W
cols = list(range(x, x+w))
# H
rows = list(range(y, y+h))
for i in rows: #H
for j in cols: #W
# 坐标变换一定要注意检查
# 此时获取的是真实世界坐标的深度
# https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/hpp/rs_frame.hpp#L810
depth = depth_frame.get_distance(j, i) # W,H
# 给定没有失真或反失真系数的图像中的像素坐标和深度,计算相对于同一相机的3D空间中的对应点
# https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/rsutil.h#L67
depth_point = rs.rs2_deproject_pixel_to_point(
depth_intrin, [j, i], depth)
text = "%.5lf, %.5lf, %.5lf\n" % (
depth_point[0], depth_point[1], depth_point[2])
f.write(text)
if i==rows[0]:
left.append(depth_point)
print("Finish writing the depth img")
temp = np.array(left)
index = np.where(temp != 0)[0]
#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]))
# // 计算两点之间的欧几里得距离
# return sqrt(pow(upoint[0] - vpoint[0], 2) +
# pow(upoint[1] - vpoint[1], 2) +
# pow(upoint[2] - vpoint[2], 2));
#这里的距离,收到环境的影响,因为我是直接计算框里面最左端到最右端的距离
#如果把背景框进来,那么你测的是两个背景的宽度
print("dist","---------------------", str(left[index[-1]][0] - left[index[0]][0]))
cv2.putText(color_image, str(left[index[-1]][0] - left[index[0]][0]),
(x, y - 30),
cv2.FONT_HERSHEY_COMPLEX, 1.5, (255, 255, 255))
cv2.rectangle(color_image, (x, y), (x+w, y+h), (255, 0, 0), 2)
# Apply colormap on depth image (image must be converted to 8-bit per pixel first)
depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
depth_image, alpha=0.03), cv2.COLORMAP_JET)
# Stack both images horizontally
images = np.hstack((color_image, depth_colormap))
# Show images
cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
cv2.imshow('RealSense', images)
cv2.waitKey(1)
curr_frame += 1
finally:
# Stop streaming
pipeline.stop()
有一个显示相机位置的py例子:
# License: Apache 2.0. See LICENSE file in root directory.
# Copyright(c) 2015-2017 Intel Corporation. All Rights Reserved.
"""
OpenGL Pointcloud viewer with http://pyglet.org
Usage:
------
Mouse:
Drag with left button to rotate around pivot (thick small axes),
with right button to translate and the wheel to zoom.
Keyboard:
[p] Pause
[r] Reset View
[d] Cycle through decimation values
[z] Toggle point scaling
[x] Toggle point distance attenuation
[c] Toggle color source
[l] Toggle lighting
[f] Toggle depth post-processing
[s] Save PNG (./out.png)
[e] Export points to ply (./out.ply)
[q/ESC] Quit
Notes:
------
Using deprecated OpenGL (FFP lighting, matrix stack...) however, draw calls
are kept low with pyglet.graphics.* which uses glDrawArrays internally.
Normals calculation is done with numpy on CPU which is rather slow, should really
be done with shaders but was omitted for several reasons - brevity, for lowering
dependencies (pyglet doesn't ship with shader support & recommends pyshaders)
and for reference.
"""
import math
import ctypes
import pyglet
import pyglet.gl as gl
import numpy as np
import pyrealsense2 as rs
# https://stackoverflow.com/a/6802723
def rotation_matrix(axis, theta):
"""
Return the rotation matrix associated with counterclockwise rotation about
the given axis by theta radians.
"""
axis = np.asarray(axis)
axis = axis / math.sqrt(np.dot(axis, axis))
a = math.cos(theta / 2.0)
b, c, d = -axis * math.sin(theta / 2.0)
aa, bb, cc, dd = a * a, b * b, c * c, d * d
bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
return np.array([[aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
[2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
[2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc]])
class AppState:
def __init__(self, *args, **kwargs):
self.pitch, self.yaw = math.radians(-10), math.radians(-15)
self.translation = np.array([0, 0, 1], np.float32)
self.distance = 2
self.mouse_btns = [False, False, False]
self.paused = False
self.decimate = 0
self.scale = True
self.attenuation = False
self.color = True
self.lighting = False
self.postprocessing = False
def reset(self):
self.pitch, self.yaw, self.distance = 0, 0, 2
self.translation[:] = 0, 0, 1
@property
def rotation(self):
Rx = rotation_matrix((1, 0, 0), math.radians(-self.pitch))
Ry = rotation_matrix((0, 1, 0), math.radians(-self.yaw))
return np.dot(Ry, Rx).astype(np.float32)
state = AppState()
# Configure streams
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
# other_stream, other_format = rs.stream.infrared, rs.format.y8
other_stream, other_format = rs.stream.color, rs.format.rgb8
config.enable_stream(other_stream, 640, 480, other_format, 30)
# Start streaming
pipeline.start(config)
profile = pipeline.get_active_profile()
depth_sensor = profile.get_device().first_depth_sensor()
depth_scale = depth_sensor.get_depth_scale()
depth_profile = rs.video_stream_profile(profile.get_stream(rs.stream.depth))
depth_intrinsics = depth_profile.get_intrinsics()
w, h = depth_intrinsics.width, depth_intrinsics.height
# Processing blocks
pc = rs.pointcloud()
decimate = rs.decimation_filter()
decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
colorizer = rs.colorizer()
filters = [rs.disparity_transform(),
rs.spatial_filter(),
rs.temporal_filter(),
rs.disparity_transform(False)]
# pyglet
window = pyglet.window.Window(
config=gl.Config(
double_buffer=True,
samples=8 # MSAA
),
resizable=True, vsync=True)
keys = pyglet.window.key.KeyStateHandler()
window.push_handlers(keys)
def convert_fmt(fmt):
"""rs.format to pyglet format string"""
return {
rs.format.rgb8: 'RGB',
rs.format.bgr8: 'BGR',
rs.format.rgba8: 'RGBA',
rs.format.bgra8: 'BGRA',
rs.format.y8: 'L',
}[fmt]
# Create a VertexList to hold pointcloud data
# Will pre-allocates memory according to the attributes below
vertex_list = pyglet.graphics.vertex_list(
w * h, 'v3f/stream', 't2f/stream', 'n3f/stream')
# Create and allocate memory for our color data
other_profile = rs.video_stream_profile(profile.get_stream(other_stream))
image_data = pyglet.image.ImageData(w, h, convert_fmt(
other_profile.format()), (gl.GLubyte * (w * h * 3))())
fps_display = pyglet.clock.ClockDisplay()
@window.event
def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
w, h = map(float, window.get_size())
if buttons & pyglet.window.mouse.LEFT:
state.yaw -= dx * 0.5
state.pitch -= dy * 0.5
if buttons & pyglet.window.mouse.RIGHT:
dp = np.array((dx / w, -dy / h, 0), np.float32)
state.translation += np.dot(state.rotation, dp)
if buttons & pyglet.window.mouse.MIDDLE:
dz = dy * 0.01
state.translation -= (0, 0, dz)
state.distance -= dz
def handle_mouse_btns(x, y, button, modifiers):
state.mouse_btns[0] ^= (button & pyglet.window.mouse.LEFT)
state.mouse_btns[1] ^= (button & pyglet.window.mouse.RIGHT)
state.mouse_btns[2] ^= (button & pyglet.window.mouse.MIDDLE)
window.on_mouse_press = window.on_mouse_release = handle_mouse_btns
@window.event
def on_mouse_scroll(x, y, scroll_x, scroll_y):
dz = scroll_y * 0.1
state.translation -= (0, 0, dz)
state.distance -= dz
def on_key_press(symbol, modifiers):
if symbol == pyglet.window.key.R:
state.reset()
if symbol == pyglet.window.key.P:
state.paused ^= True
if symbol == pyglet.window.key.D:
state.decimate = (state.decimate + 1) % 3
decimate.set_option(rs.option.filter_magnitude, 2 ** state.decimate)
if symbol == pyglet.window.key.C:
state.color ^= True
if symbol == pyglet.window.key.Z:
state.scale ^= True
if symbol == pyglet.window.key.X:
state.attenuation ^= True
if symbol == pyglet.window.key.L:
state.lighting ^= True
if symbol == pyglet.window.key.F:
state.postprocessing ^= True
if symbol == pyglet.window.key.S:
pyglet.image.get_buffer_manager().get_color_buffer().save('out.png')
if symbol == pyglet.window.key.Q:
window.close()
window.push_handlers(on_key_press)
def axes(size=1, width=1):
"""draw 3d axes"""
gl.glLineWidth(width)
pyglet.graphics.draw(6, gl.GL_LINES,
('v3f', (0, 0, 0, size, 0, 0,
0, 0, 0, 0, size, 0,
0, 0, 0, 0, 0, size)),
('c3f', (1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1, 0, 0, 1,
))
)
def frustum(intrinsics):
"""draw camera's frustum"""
w, h = intrinsics.width, intrinsics.height
batch = pyglet.graphics.Batch()
for d in range(1, 6, 2):
def get_point(x, y):
p = rs.rs2_deproject_pixel_to_point(intrinsics, [x, y], d)
batch.add(2, gl.GL_LINES, None, ('v3f', [0, 0, 0] + p))
return p
top_left = get_point(0, 0)
top_right = get_point(w, 0)
bottom_right = get_point(w, h)
bottom_left = get_point(0, h)
batch.add(2, gl.GL_LINES, None, ('v3f', top_left + top_right))
batch.add(2, gl.GL_LINES, None, ('v3f', top_right + bottom_right))
batch.add(2, gl.GL_LINES, None, ('v3f', bottom_right + bottom_left))
batch.add(2, gl.GL_LINES, None, ('v3f', bottom_left + top_left))
batch.draw()
def grid(size=1, n=10, width=1):
"""draw a grid on xz plane"""
gl.glLineWidth(width)
s = size / float(n)
s2 = 0.5 * size
batch = pyglet.graphics.Batch()
for i in range(0, n + 1):
x = -s2 + i * s
batch.add(2, gl.GL_LINES, None, ('v3f', (x, 0, -s2, x, 0, s2)))
for i in range(0, n + 1):
z = -s2 + i * s
batch.add(2, gl.GL_LINES, None, ('v3f', (-s2, 0, z, s2, 0, z)))
batch.draw()
@window.event
def on_draw():
window.clear()
gl.glEnable(gl.GL_DEPTH_TEST)
gl.glEnable(gl.GL_LINE_SMOOTH)
width, height = window.get_size()
gl.glViewport(0, 0, width, height)
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.gluPerspective(60, width / float(height), 0.01, 20)
gl.glMatrixMode(gl.GL_TEXTURE)
gl.glLoadIdentity()
# texcoords are [0..1] and relative to top-left pixel corner, add 0.5 to center
gl.glTranslatef(0.5 / image_data.width, 0.5 / image_data.height, 0)
# texture size may be increased by pyglet to a power of 2
tw, th = image_data.texture.owner.width, image_data.texture.owner.height
gl.glScalef(image_data.width / float(tw),
image_data.height / float(th), 1)
gl.glMatrixMode(gl.GL_MODELVIEW)
gl.glLoadIdentity()
gl.gluLookAt(0, 0, 0, 0, 0, 1, 0, -1, 0)
gl.glTranslatef(0, 0, state.distance)
gl.glRotated(state.pitch, 1, 0, 0)
gl.glRotated(state.yaw, 0, 1, 0)
if any(state.mouse_btns):
axes(0.1, 4)
gl.glTranslatef(0, 0, -state.distance)
gl.glTranslatef(*state.translation)
gl.glColor3f(0.5, 0.5, 0.5)
gl.glPushMatrix()
gl.glTranslatef(0, 0.5, 0.5)
grid()
gl.glPopMatrix()
psz = max(window.get_size()) / float(max(w, h)) if state.scale else 1
gl.glPointSize(psz)
distance = (0, 0, 1) if state.attenuation else (1, 0, 0)
gl.glPointParameterfv(gl.GL_POINT_DISTANCE_ATTENUATION,
(gl.GLfloat * 3)(*distance))
if state.lighting:
ldir = [0.5, 0.5, 0.5] # world-space lighting
ldir = np.dot(state.rotation, (0, 0, 1)) # MeshLab style lighting
ldir = list(ldir) + [0] # w=0, directional light
gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, (gl.GLfloat * 4)(*ldir))
gl.glLightfv(gl.GL_LIGHT0, gl.GL_DIFFUSE,
(gl.GLfloat * 3)(1.0, 1.0, 1.0))
gl.glLightfv(gl.GL_LIGHT0, gl.GL_AMBIENT,
(gl.GLfloat * 3)(0.75, 0.75, 0.75))
gl.glEnable(gl.GL_LIGHT0)
gl.glEnable(gl.GL_NORMALIZE)
gl.glEnable(gl.GL_LIGHTING)
gl.glColor3f(1, 1, 1)
texture = image_data.get_texture()
gl.glEnable(texture.target)
gl.glBindTexture(texture.target, texture.id)
gl.glTexParameteri(
gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
# comment this to get round points with MSAA on
gl.glEnable(gl.GL_POINT_SPRITE)
if not state.scale and not state.attenuation:
gl.glDisable(gl.GL_MULTISAMPLE) # for true 1px points with MSAA on
vertex_list.draw(gl.GL_POINTS)
gl.glDisable(texture.target)
if not state.scale and not state.attenuation:
gl.glEnable(gl.GL_MULTISAMPLE)
gl.glDisable(gl.GL_LIGHTING)
gl.glColor3f(0.25, 0.25, 0.25)
frustum(depth_intrinsics)
axes()
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.glOrtho(0, width, 0, height, -1, 1)
gl.glMatrixMode(gl.GL_MODELVIEW)
gl.glLoadIdentity()
gl.glMatrixMode(gl.GL_TEXTURE)
gl.glLoadIdentity()
gl.glDisable(gl.GL_DEPTH_TEST)
fps_display.draw()
def run(dt):
global w, h
window.set_caption("RealSense (%dx%d) %dFPS (%.2fms) %s" %
(w, h, 0 if dt == 0 else 1.0 / dt, dt * 1000,
"PAUSED" if state.paused else ""))
if state.paused:
return
success, frames = pipeline.try_wait_for_frames(timeout_ms=0)
if not success:
return
depth_frame = frames.get_depth_frame()
other_frame = frames.first(other_stream)
depth_frame = decimate.process(depth_frame)
if state.postprocessing:
for f in filters:
depth_frame = f.process(depth_frame)
# Grab new intrinsics (may be changed by decimation)
depth_intrinsics = rs.video_stream_profile(
depth_frame.profile).get_intrinsics()
w, h = depth_intrinsics.width, depth_intrinsics.height
color_image = np.asanyarray(other_frame.get_data())
colorized_depth = colorizer.colorize(depth_frame)
depth_colormap = np.asanyarray(colorized_depth.get_data())
if state.color:
mapped_frame, color_source = other_frame, color_image
else:
mapped_frame, color_source = colorized_depth, depth_colormap
points = pc.calculate(depth_frame)
pc.map_to(mapped_frame)
# handle color source or size change
fmt = convert_fmt(mapped_frame.profile.format())
global image_data
if (image_data.format, image_data.pitch) != (fmt, color_source.strides[0]):
empty = (gl.GLubyte * (w * h * 3))()
image_data = pyglet.image.ImageData(w, h, fmt, empty)
# copy image data to pyglet
image_data.set_data(fmt, color_source.strides[0], color_source.ctypes.data)
verts = np.asarray(points.get_vertices(2)).reshape(h, w, 3)
texcoords = np.asarray(points.get_texture_coordinates(2))
if len(vertex_list.vertices) != verts.size:
vertex_list.resize(verts.size // 3)
# need to reassign after resizing
vertex_list.vertices = verts.ravel()
vertex_list.tex_coords = texcoords.ravel()
# copy our data to pre-allocated buffers, this is faster than assigning...
# pyglet will take care of uploading to GPU
def copy(dst, src):
"""copy numpy array to pyglet array"""
# timeit was mostly inconclusive, favoring slice assignment for safety
np.array(dst, copy=False)[:] = src.ravel()
# ctypes.memmove(dst, src.ctypes.data, src.nbytes)
copy(vertex_list.vertices, verts)
copy(vertex_list.tex_coords, texcoords)
if state.lighting:
# compute normals
dy, dx = np.gradient(verts, axis=(0, 1))
n = np.cross(dx, dy)
# can use this, np.linalg.norm or similar to normalize, but OpenGL can do this for us, see GL_NORMALIZE above
# norm = np.sqrt((n*n).sum(axis=2, keepdims=True))
# np.divide(n, norm, out=n, where=norm != 0)
# import cv2
# n = cv2.bilateralFilter(n, 5, 1, 1)
copy(vertex_list.normals, n)
if keys[pyglet.window.key.E]:
points.export_to_ply('./out.ply', mapped_frame)
pyglet.clock.schedule(run)
try:
pyglet.app.run()
finally:
pipeline.stop()
结合改进:
import pyrealsense2 as rs
import numpy as np
import cv2
import os
# opencv-haar人脸检测
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# Configure depth and color streams
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
# Start streaming
pipe_profile = pipeline.start(config)
curr_frame = 0
try:
while True:
# Wait for a coherent pair of frames: depth and color
frames = pipeline.wait_for_frames()
depth_frame = frames.get_depth_frame()
color_frame = frames.get_color_frame()
if frames.size() < 2:
continue
if not depth_frame or not color_frame:
continue
# Intrinsics & Extrinsics
# 深度相机内参矩阵
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
# RGB相机内参矩阵
color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
# 深度图到彩图的外参RT
depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
color_frame.profile)
depth_value = 0.5
depth_pixel = [depth_intrin.ppx, depth_intrin.ppy]
depth_point = rs.rs2_deproject_pixel_to_point(depth_intrin, depth_pixel, depth_value)
print(depth_point)
# print(depth_intrin.ppx, depth_intrin.ppy)
# Convert images to numpy arrays
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# 将RGB对齐到深度,获取对应下的XYZ
#Color->Depth
align = rs.align(rs.stream.depth)
frameset = align.process(frames)
if frameset.size() < 2:
continue
depth_frame = frameset.get_depth_frame()
color_frame = frameset.get_color_frame()
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# 找到人脸
# find the human face in the color_image
gray = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
left = []
for (x, y, w, h) in faces:
# 当前帧大于100
if curr_frame > 100 and curr_frame % 40 == 10:
# 取出人脸的深度图和彩色图
roi_depth_image = depth_image[y:y+h, x:x+w]
roi_color_image = color_image[y:y+h, x:x+w]
# 新建
os.system('mkdir -p ./3d_output/%d' % curr_frame)
# 保存
cv2.imwrite('./3d_output/%d/depth.jpg' %
curr_frame, roi_depth_image)
cv2.imwrite('./3d_output/%d/color.jpg' %
curr_frame, roi_color_image)
# write the depth data in a depth.txt
with open('./3d_output/%d/depth.csv' % curr_frame, 'w') as f:
# W
cols = list(range(x, x+w))
# H
rows = list(range(y, y+h))
for i in rows: #H
for j in cols: #W
# 坐标变换一定要注意检查
# 此时获取的是真实世界坐标的深度
# https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/hpp/rs_frame.hpp#L810
depth = depth_frame.get_distance(j, i) # W,H
# 给定没有失真或反失真系数的图像中的像素坐标和深度,计算相对于同一相机的3D空间中的对应点
# https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/rsutil.h#L67
depth_point = rs.rs2_deproject_pixel_to_point(
depth_intrin, [j, i], depth)
text = "%.5lf, %.5lf, %.5lf\n" % (
depth_point[0], depth_point[1], depth_point[2])
f.write(text)
if i==rows[0]:
left.append(depth_point)
print("Finish writing the depth img")
temp = np.array(left)
index = np.where(temp != 0)[0]
#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]))
# // 计算两点之间的欧几里得距离
# return sqrt(pow(upoint[0] - vpoint[0], 2) +
# pow(upoint[1] - vpoint[1], 2) +
# pow(upoint[2] - vpoint[2], 2));
#这里的距离,收到环境的影响,因为我是直接计算框里面最左端到最右端的距离
#如果把背景框进来,那么你测的是两个背景的宽度
print("dist","---------------------", str(left[index[-1]][0] - left[index[0]][0]))
# 这里要做很多工作,离群噪声点的去除,去除后矩阵的真实大小判断 很多行,哪一行是最真实的距离
cv2.putText(color_image, str(left[index[-1]][0] - left[index[0]][0]),
(x, y - 30),
cv2.FONT_HERSHEY_COMPLEX, 1.5, (255, 255, 255))
cv2.rectangle(color_image, (x, y), (x+w, y+h), (255, 0, 0), 2)
# Apply colormap on depth image (image must be converted to 8-bit per pixel first)
depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
depth_image, alpha=0.03), cv2.COLORMAP_JET)
# Stack both images horizontally
images = np.hstack((color_image, depth_colormap))
# Show images
cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
cv2.imshow('RealSense', images)
cv2.waitKey(1)
curr_frame += 1
finally:
# Stop streaming
pipeline.stop()
修改版:
import pyrealsense2 as rs
import numpy as np
import cv2
import os
# opencv-haar人脸检测
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# Configure depth and color streams
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
# Start streaming
pipe_profile = pipeline.start(config)
curr_frame = 0
try:
while True:
# Wait for a coherent pair of frames: depth and color
frames = pipeline.wait_for_frames()
depth_frame = frames.get_depth_frame()
color_frame = frames.get_color_frame()
if frames.size() < 2:
continue
if not depth_frame or not color_frame:
continue
# Intrinsics & Extrinsics
# 深度相机内参矩阵
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
# RGB相机内参矩阵
color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
# 深度图到彩图的外参RT
depth_to_color_extrin = depth_frame.profile.get_extrinsics_to(
color_frame.profile)
depth_value = 0.5
depth_pixel = [depth_intrin.ppx, depth_intrin.ppy]
depth_point = rs.rs2_deproject_pixel_to_point(depth_intrin, depth_pixel, depth_value)
#print(depth_point)
# print(depth_intrin.ppx, depth_intrin.ppy)
# Convert images to numpy arrays
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# 将RGB对齐到深度,获取对应下的XYZ
#Color->Depth
align = rs.align(rs.stream.depth)
frameset = align.process(frames)
if frameset.size() < 2:
continue
depth_frame = frameset.get_depth_frame()
color_frame = frameset.get_color_frame()
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
color_intrin = color_frame.profile.as_video_stream_profile().intrinsics
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# 找到人脸
# find the human face in the color_image
gray = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
left = []
for (x, y, w, h) in faces:
# 当前帧大于100
if curr_frame > 100 and curr_frame % 40 == 10:
# 取出人脸的深度图和彩色图
roi_depth_image = depth_image[y:y+h, x:x+w]
roi_color_image = color_image[y:y+h, x:x+w]
# W
cols = list(range(x, x+w))
# H
rows = list(range(y, y+h))
for i in rows: #H
for j in cols: #W
# 坐标变换一定要注意检查
# 此时获取的是真实世界坐标的深度
# https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/hpp/rs_frame.hpp#L810
depth = depth_frame.get_distance(j, i) # W,H
# 给定没有失真或反失真系数的图像中的像素坐标和深度,计算相对于同一相机的3D空间中的对应点
# https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/rsutil.h#L67
depth_point = rs.rs2_deproject_pixel_to_point(
depth_intrin, [j, i], depth)
text = "%.5lf, %.5lf, %.5lf\n" % (
depth_point[0], depth_point[1], depth_point[2])
#f.write(text)
if i==rows[0]:
left.append(depth_point)
#print("Finish writing the depth img")
# temp = np.array(left)
# # 求均值
# _mean = np.mean(temp, axis=0)
# # 求方差
# _var = np.var(temp, axis=0)
# minmean = _mean - 1 * abs(_mean)
# maxmean = _mean + 1 * abs(_mean)
# minvar = _var - 1 * abs(_var)
# maxvar = _var + 1 * abs(_var)
def non_zero_mean(np_arr, axis):
exist = (np_arr != 0)
num = np_arr.sum(axis=axis)
den = exist.sum(axis=axis)
return num / den
temp = np.array(left)
# 求均值
_mean = non_zero_mean(temp, axis=0)
# 求方差
_var = np.var(temp, axis=0)
minmean = _mean - 1 * abs(_mean)
maxmean = _mean + 1 * abs(_mean)
minvar = _var - 1 * abs(_var)
maxvar = _var + 1 * abs(_var)
index = []
i = 0 # H
for j in range(len(cols)): # W
if temp[j][0] != 0 and temp[j][1] != 0 and temp[j][2] != 0:
if temp[j][0]>minmean[0] and temp[j][0] minmean[1] and temp[j][1] < maxmean[1]:
if temp[j][2] > minmean[2] and temp[j][2] < maxmean[2]:
index.append(j)
#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]))
# // 计算两点之间的欧几里得距离
# return sqrt(pow(upoint[0] - vpoint[0], 2) +
# pow(upoint[1] - vpoint[1], 2) +
# pow(upoint[2] - vpoint[2], 2));
#这里的距离,收到环境的影响,因为我是直接计算框里面最左端到最右端的距离
#如果把背景框进来,那么你测的是两个背景的宽度
if len(index) > (len(cols)/2):
# 新建
os.system('mkdir -p ./3d_output/%d' % curr_frame)
# 保存
cv2.imwrite('./3d_output/%d/depth.jpg' %
curr_frame, roi_depth_image)
cv2.imwrite('./3d_output/%d/color.jpg' %
curr_frame, roi_color_image)
print("dist","---------------------", str(left[index[-1]][0] - left[index[0]][0]))
# 这里要做很多工作,离群噪声点的去除,去除后矩阵的真实大小判断 很多行,哪一行是最真实的距离
cv2.putText(color_image, str(left[index[-1]][0] - left[index[0]][0]),
(x, y - 30),
cv2.FONT_HERSHEY_COMPLEX, 1.5, (255, 255, 255))
cv2.rectangle(color_image, (x, y), (x+w, y+h), (255, 0, 0), 2)
# Apply colormap on depth image (image must be converted to 8-bit per pixel first)
depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
depth_image, alpha=0.03), cv2.COLORMAP_JET)
# Stack both images horizontally
images = np.hstack((color_image, depth_colormap))
# Show images
cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
cv2.imshow('RealSense', images)
cv2.waitKey(1)
curr_frame += 1
finally:
# Stop streaming
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