如何基于Choregraph与naoqi获取NAO6前置摄像头流并网络传输?
解决方案:Choregraphe自定义Python盒子实现高帧率摄像头流
一、核心思路:使用ALVideoDevice的视频订阅机制
NAOqi的ALVideoDevice提供视频订阅接口,比单次调用getImageLocal/Remote效率高得多,能稳定获取15-30fps的流(取决于摄像头配置)。我们可以在Choregraphe的自定义Python盒子里实现订阅、帧处理、网络传输的逻辑,无需额外安装ROS或GStreamer。
二、具体实现步骤
1. 新建Choregraphe自定义Python盒子
打开Choregraphe,拖入一个Python Script盒子,命名为CameraStreamSender。
2. 编写Python代码(盒子内部)
代码逻辑:
- 初始化时订阅前置摄像头
- 循环获取订阅的视频帧
- 将帧编码为JPEG(减少传输体积)
- 通过TCP发送到本地服务器
import naoqi import numpy as np import cv2 import socket from naoqi import ALProxy class CameraStreamSender(naoqi.ALModule): def __init__(self, name): naoqi.ALModule.__init__(self, name) # 初始化视频代理 self.video_proxy = ALProxy("ALVideoDevice") # 订阅前置摄像头:QVGA分辨率、BGR色彩空间、30fps self.camera_client = self.video_proxy.subscribeCamera( "CameraStreamClient", 0, # 0=前置摄像头,1=后置摄像头 naoqi.ALVideoDevice.kQVGA, naoqi.ALVideoDevice.kBGRColorSpace, 30 ) # 配置服务器连接:替换为你的本地服务器IP和端口 self.server_ip = "192.168.1.100" self.server_port = 5000 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((self.server_ip, self.server_port)) # 启动帧处理循环 self.is_running = True self.video_proxy.registerImageCallback(self.camera_client, self.getName(), "process_frame") def process_frame(self, frame_id, _, frame_data): if not self.is_running: return # 解析帧数据 width, height, _, buffer = frame_data # 转换为OpenCV格式 img = np.frombuffer(buffer, dtype=np.uint8).reshape((height, width, 3)) # JPEG编码降低传输体积 _, encoded_img = cv2.imencode('.jpg', img, [int(cv2.IMWRITE_JPEG_QUALITY), 80]) # 先发数据长度(解决粘包问题),再发图像数据 data_len = len(encoded_img) self.socket.sendall(data_len.to_bytes(4, byteorder='big')) self.socket.sendall(encoded_img.tobytes()) def onStop(self): # 停止时清理资源 self.is_running = False self.video_proxy.unsubscribe(self.camera_client) self.socket.close()
3. 本地服务器接收脚本
在本地PC运行以下代码,用于接收摄像头流并进行姿态追踪:
import socket import cv2 import numpy as np server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(("0.0.0.0", 5000)) server_socket.listen(1) print("等待NAO机器人连接...") client_socket, addr = server_socket.accept() print(f"已连接:{addr}") while True: # 接收数据长度 len_data = client_socket.recv(4) if not len_data: break data_len = int.from_bytes(len_data, byteorder='big') # 接收完整图像数据 img_data = b'' while len(img_data) < data_len: chunk = client_socket.recv(min(data_len - len(img_data), 4096)) if not chunk: break img_data += chunk # 解码为OpenCV图像 img = cv2.imdecode(np.frombuffer(img_data, dtype=np.uint8), cv2.IMREAD_COLOR) # 在此添加你的人体姿态追踪逻辑 cv2.imshow("NAO Camera Stream", img) if cv2.waitKey(1) & 0xFF == ord('q'): break client_socket.close() server_socket.close() cv2.destroyAllWindows()
4. Choregraphe工程配置
- 将Python盒子拖入主流程,放在后台循环任务中,确保机器人在自主模式下持续运行该模块。
- 运行前确认机器人与本地PC在同一局域网,且先启动服务器脚本。
- 可按需调整摄像头分辨率(如
kVGA即640x480)或JPEG质量,平衡帧率与画质。
三、关键优化点
- 分辨率选择:QVGA(320x240)足以满足姿态追踪需求,且帧率稳定;更高分辨率会降低帧率。
- 色彩空间:使用BGR格式直接兼容OpenCV,减少转换开销。
- 传输协议:TCP比UDP更可靠,适合对帧完整性要求高的姿态追踪场景。
- 资源清理:必须在盒子停止时取消摄像头订阅、关闭socket,避免机器人资源泄漏。
内容的提问来源于stack exchange,提问作者fluxt
相关产品推荐
相关产品推荐

