随着人工智能的不断发展,机器人越来越被用来解放人类,使其免受检查危险地点或例行视觉监控枯燥工作的风险。为了提供一定程度的自主决策,机器人通常配备连接到搭载Linux计算机的摄像头,比如英伟达Jetson或x86单板计算机(SBC)。
如果应用需要实时360度视频,有两种方法。第一种更复杂的方法是使用多个摄像头,在计算机上拼接视频,或者分别处理每个视频源。使用的摄像头数量取决于每个摄像头的视场。如果机器人使用两个能展示超过180度的鱼眼镜头,只需要两个摄像头。通常使用三到四个摄像头。
更简单的方法是使用消费者360°摄像头。在自由独立的theta360.guide开发者社区上,开发者讨论的最热门话题之一是如何将360°视野添加到他们的机器人原型中,并将视频传输到OpenCV。
尽管有多种方法可以将360°相机的视频传输到Linux计算机,但最流行的方法是使用USB电缆。WiFi和以太网并不那么流行。RICOH THETA V、X和Z1型号可以在Linux计算机上显示为USB网络摄像头。然而,在Linux上需要进行一些工作。MacOS计算机可以直接使用RICOH THETA相机。对于Windows,RICOH提供了一个驱动程序。对于Linux,RICOH在GitHub上提供了一个名为libuvc-theta的修改版本的libuvc。
为了将相机显示为OpenCV的视频设备,RICOH提供了一个名为libuvc-theta-sample的示例程序。这可以与v4l2loopback一起使用,将一个/dev/video*
设备提供给OpenCV。
为了测试相机与Linux计算机的连接,首先将相机与Linux计算机连接,然后运行以下步骤:
git clone https://github.com/ricohapi/libuvc-theta.git
sudo apt install libjpeg-dev
cd libuvc-theta
mkdir build
cd build
cmake ..
make
sudo make install
cd ../..
git clone https://github.com/ricohapi/libuvc-theta-sample.git
cd libuvc-theta-sample/gst
make
# 必须将THETA插入计算机,并处于
# 实时流模式
./gst_viewer
使用gstreamer显示360°视频相机
如果编译失败,可能需要额外的gstreamer库。这将安装所有库。
sudo apt-get install \
libgstreamer1.0-0 \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
gstreamer1.0-doc \
gstreamer1.0-tools \
gstreamer1.0-x \
gstreamer1.0-alsa \
gstreamer1.0-gl \
gstreamer1.0-gtk3 \
gstreamer1.0-qt5 \
gstreamer1.0-pulseaudio \
libgstreamer-plugins-base1.0-dev
此外,由于缺乏4K H.264硬件解码支持,树莓派4将无法使用。
设置/dev/video*
要将libuvc设备作为视频设备可用,我们可以使用v4l2loopback。libuvc-theta-sample应用程序将使用gstreamer将视频发送到v4l2。
如果您的计算机上只有一个视频摄像头,则应在构建之前修改这一行。下面的行用于连接RICOH THETA作为唯一网络摄像头的计算机:
"v4l2sink device=/dev/video0 sync=false";
从OpenCV访问
为了测试摄像头是否可以从OpenCV中使用,让我们从一个简单的帧调整开始。
import cv2
cap = cv2.VideoCapture(0)
# 检查摄像头是否正确打开
if not cap.isOpened():
raise IOError("Cannot open webcam")
while True:
ret, frame = cap.read()
frame = cv2.resize(frame, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA)
cv2.imshow('Input', frame)
c = cv2.waitKey(1)
if c == 27:
break
cap.release()
cv2.destroyAllWindows()
摄像头延迟
延迟是社区讨论中的一个重要问题。THETA摄像头的延迟约为350毫秒。对于许多需要机器人快速反应的应用程序来说,这个延迟太高了。如果您在控制一个绕过障碍物移动的无人机,那么这个延迟也太高了。延迟是由于摄像头内部两个镜头的拼接造成的。拼接无法在视频传输中禁用。
v4l2loopback的替代方案
由于v4l2loopback增加了复杂性和开销,gstthetauvc软件包可用于直接从gstreamer访问摄像头。
以下是使用gstthetauvc进行相同测试的示例。
import cv2
# 以下管道有效
# cap = cv2.VideoCapture("thetauvcsrc \
# ! decodebin \
# ! autovideoconvert \
# ! video/x-raw,format=BGRx \
# ! queue ! videoconvert \
# ! video/x-raw,format=BGR ! queue ! appsink")
# 感谢nickel110提供的管道建议
# 尝试强制硬件加速
# 在Ubuntu 22.04上使用旧的GTX 950测试了NVIDIA 510.73
cap = cv2.VideoCapture("thetauvcsrc \
! queue \
! h264parse \
! nvdec \
! gldownload \
! queue \
! videoconvert n-threads=0 \
! video/x-raw,format=BGR \
! queue \
! appsink")
if not cap.isOpened():
raise IOError('Cannot open RICOH THETA')
while True:
ret, frame = cap.read()
frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
cv2.imshow('frame', frame)
c = cv2.waitKey(1)
if c == 27:
break
cap.release()
cv2.destroyAllWindows()
360度视频实时反馈示例
以下是使用OpenCV进行颜色转换和边缘检测的示例。
# 转换为灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 模糊图像以获得更好的边缘检测效果
img_blur = cv2.GaussianBlur(img_gray, (3,3), 0)
# Canny边缘检测
edges = cv2.Canny(image=img_blur, threshold1=100, threshold2=200) # Canny边缘检测
# 显示Canny边缘检测图像
cv2.imshow('Canny Edge Detection', edges)
检测现场人员和显示器。
相机有两个镜头。快门按钮相反的一侧是后置镜头,将放置在场景中心。当物体位于等距投影视图的中心时,对象检测最为准确。
人物位于后置镜头中心
然而,当人类处于等距投影视图的边缘时,检测效果还算不错,即使在夜晚也是如此。您可能需要在鱼眼镜头或360°图像数据库上训练您的模型。
在等距投影视图边缘检测到人类
提高检测准确度
现在您已经在来自实时360°视频源的等距投影帧上实现了基本检测,您可以尝试不同的技术来提高准确度。一种方法是从每一帧创建多个展平场景,然后在每个场景中检测物体。misoji工程师的视频在ROS2 rviz2和KR260中的360°目标检测(Yolo)提供了这种技术的很好演示。还有一种针对全景视频修改过的YOLO版本。请参考论文PV-YOLO:基于YOLOv4的全景视频物体检测模型。
结论
使用消费级现成的360° 摄像头,您可以相当轻松地将360°视频显示为USB网络摄像头,以便软件如OpenCV能够访问。通过视频设备或通过gstreamer访问360°视频,标准的OpenCV或其他检测软件可以用于实时视频的等距投影帧。由于图像的失真,对象检测算法的效果不如标准的非360°网络摄像头。然而,即使没有修改,您仍然可以开始一些检测。
要实际将检测用于教育或研究项目之外的用途,您需要研究改进识别失真等距投影视图中物体的技术。
Source:
https://dzone.com/articles/opencv-integration-live-video-for-robotics