cmvr-es/python/realsense/detect_red_point.py

136 lines
4.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import pyrealsense2 as rs
import numpy as np
import cv2
def init_realsense():
"""
初始化 RealSense 管道并返回 pipeline 和 align 对象
"""
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth, 848, 480, rs.format.z16, 30)
config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
profile = pipeline.start(config)
align = rs.align(rs.stream.color)
return pipeline, align
def get_closest_red_point(pipeline, align, warmup=100):
"""
获取最近红色圆点的 3D 坐标。
返回 (x, y, z) 或 None如果没检测到
"""
# 丢掉前几帧,让相机稳定
for _ in range(warmup):
pipeline.wait_for_frames()
frames = pipeline.wait_for_frames()
aligned_frames = align.process(frames)
depth_frame = aligned_frames.get_depth_frame()
color_frame = aligned_frames.get_color_frame()
if not depth_frame or not color_frame:
return None
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
hsv = cv2.cvtColor(color_image, cv2.COLOR_BGR2HSV)
lower_red1 = np.array([0, 100, 100])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([160, 100, 100])
upper_red2 = np.array([179, 255, 255])
mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
mask = cv2.bitwise_or(mask1, mask2)
mask_blur = cv2.GaussianBlur(mask, (9, 9), 2)
circles = cv2.HoughCircles(mask_blur, cv2.HOUGH_GRADIENT, dp=1.2, minDist=20,
param1=50, param2=15, minRadius=5, maxRadius=50)
closest_point = None
min_depth = float('inf')
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
u, v, r = i
depth = depth_frame.get_distance(u, v)
if 0 < depth < min_depth:
min_depth = depth
closest_point = rs.rs2_deproject_pixel_to_point(depth_intrin, [u, v], depth)
return closest_point
def show_frames(pipeline, align):
"""
显示 RGB 和 Depth 图像,同时标记最近红点(实时窗口)。
'q' 退出。
"""
while True:
frames = pipeline.wait_for_frames()
aligned_frames = align.process(frames)
depth_frame = aligned_frames.get_depth_frame()
color_frame = aligned_frames.get_color_frame()
if not depth_frame or not color_frame:
continue
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
depth_intrin = depth_frame.profile.as_video_stream_profile().intrinsics
hsv = cv2.cvtColor(color_image, cv2.COLOR_BGR2HSV)
lower_red1 = np.array([0, 100, 100])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([160, 100, 100])
upper_red2 = np.array([179, 255, 255])
mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
mask = cv2.bitwise_or(mask1, mask2)
mask_blur = cv2.GaussianBlur(mask, (9, 9), 2)
circles = cv2.HoughCircles(mask_blur, cv2.HOUGH_GRADIENT, dp=1.2, minDist=20,
param1=50, param2=15, minRadius=5, maxRadius=50)
closest_point = None
closest_pixel = None
closest_radius = 0
min_depth = float('inf')
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
u, v, r = i
depth = depth_frame.get_distance(u, v)
if 0 < depth < min_depth:
min_depth = depth
closest_point = rs.rs2_deproject_pixel_to_point(depth_intrin, [u, v], depth)
closest_pixel = (u, v)
closest_radius = r
if closest_point is not None:
cv2.circle(color_image, closest_pixel, closest_radius, (0, 255, 0), 2)
cv2.circle(color_image, closest_pixel, 2, (255, 0, 0), 3)
cv2.imshow("RGB Image with Closest Red Circle", color_image)
depth_colormap = cv2.convertScaleAbs(depth_image, alpha=0.03)
depth_colormap = cv2.applyColorMap(depth_colormap, cv2.COLORMAP_JET)
cv2.imshow("Depth Image", depth_colormap)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if __name__ == "__main__":
pipeline, align = init_realsense()
try:
# 调用获取最近红点
point_3d = get_closest_red_point(pipeline, align)
print("Closest red 3D point:", point_3d)
# 调用显示函数(实时窗口显示)
show_frames(pipeline, align)
finally:
pipeline.stop()
cv2.destroyAllWindows()