121 lines
3.7 KiB
Python
121 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
实时检测红色圆点并获取 3D 坐标 (m)。
|
||
深度图对齐到彩色图。
|
||
"""
|
||
|
||
import cv2
|
||
import numpy as np
|
||
import pyrealsense2 as rs
|
||
import sys
|
||
import time
|
||
from pathlib import Path
|
||
|
||
# 把.so所在目录加入 Python 路径
|
||
sys.path.append("/home/lgv/cmvr/cmvr-es/cmake-build-debug/example")
|
||
|
||
# 导入机器人控制模块
|
||
from robot_wrapper import Robot
|
||
|
||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||
ROBOT_CONFIG = str(REPO_ROOT / "cmvr-es/config/cmvr_es.pb.txt")
|
||
|
||
|
||
def init_realsense():
|
||
"""初始化 RealSense 管道并返回 pipeline 和 align 对象"""
|
||
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)
|
||
profile = pipeline.start(config)
|
||
align = rs.align(rs.stream.color)
|
||
return pipeline, align
|
||
|
||
|
||
def get_closest_red_point(pipeline, align, vis_path=None, warmup=30,
|
||
hough_params=None):
|
||
"""
|
||
获取最近红色圆点的 3D 坐标。
|
||
返回 (x, y, z) 或 None(如果没检测到)。
|
||
"""
|
||
if hough_params is None:
|
||
hough_params = dict(dp=1.2, minDist=20,
|
||
param1=50, param2=15,
|
||
minRadius=5, maxRadius=50)
|
||
|
||
# 丢掉前几帧,让相机稳定
|
||
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 并提取红色区域
|
||
hsv = cv2.cvtColor(color_image, cv2.COLOR_BGR2HSV)
|
||
lower_red1, upper_red1 = np.array([0, 100, 100]), np.array([10, 255, 255])
|
||
lower_red2, upper_red2 = np.array([160, 100, 100]), np.array([179, 255, 255])
|
||
mask = cv2.inRange(hsv, lower_red1, upper_red1) | cv2.inRange(hsv, lower_red2, upper_red2)
|
||
|
||
# 平滑处理再检测圆
|
||
mask_blur = cv2.GaussianBlur(mask, (9, 9), 2)
|
||
circles = cv2.HoughCircles(mask_blur, cv2.HOUGH_GRADIENT, **hough_params)
|
||
|
||
closest_point, min_depth = None, float('inf')
|
||
|
||
if circles is not None:
|
||
circles = np.uint16(np.around(circles))
|
||
for u, v, r in circles[0, :]:
|
||
depth = depth_frame.get_distance(int(u), int(v))
|
||
if 0 < depth < min_depth:
|
||
min_depth = depth
|
||
closest_point = rs.rs2_deproject_pixel_to_point(depth_intrin, [int(u), int(v)], depth)
|
||
if vis_path:
|
||
cv2.circle(color_image, (u, v), r, (0, 255, 0), 2)
|
||
cv2.circle(color_image, (u, v), 6, (0, 0, 255), -1)
|
||
|
||
if vis_path and closest_point is not None:
|
||
cv2.imwrite(vis_path, color_image)
|
||
|
||
return closest_point
|
||
|
||
|
||
def main(serial="243122075614", avg_window=3, loop=True):
|
||
pipeline, align = init_realsense()
|
||
# robot = Robot(ROBOT_CONFIG, "hc01")
|
||
|
||
try:
|
||
while True:
|
||
point_3d = get_closest_red_point(pipeline, align, vis_path="red_point.png")
|
||
if point_3d:
|
||
print("Closest red 3D point:", np.round(point_3d, 4))
|
||
else:
|
||
print("未检测到红点")
|
||
|
||
if not loop:
|
||
break
|
||
|
||
key = cv2.waitKey(1)
|
||
if key == 27: # ESC 键退出
|
||
break
|
||
|
||
except Exception as e:
|
||
print("Error:", e)
|
||
|
||
finally:
|
||
pipeline.stop()
|
||
cv2.destroyAllWindows()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|