在之前的这篇博客中,我们介绍了在Jetson Nano上使用树莓派CSI相机的基本知识。在这篇博客中,我们将重点介绍Jetson平台中跟相机有关的一些框架和API。
1.Jetson平台相机架构
Jetson平台的Camera Architecture Stack如下,图片来自于官方文档。 这个架构可以分为硬件层(Hardware)、内核(Kernel)和用户空间(Userspace),绿色代表是NVIDIA实现的,蓝色代表非NVIDIA实现的。就蓝色的NVIDIA实现的部分而言,主要包含三个部分:
- libargus:用户空间中重要的组件。它的核心作用是提供了一个低层级的API来对相机进行控制,该API由Camera Core Stack支撑。
- nvarguscamerasrc:用户空间中重要的组件。它是一个由NVIDIA基于GStreamer实现的的插件,通过Argus API来控制ISP。
- v4l2src:用户空间中重要的组件。它是一个标准的Linux V4L2应用程序,使用IOCTL来直接和V4L2交互。
需要注意的是,上图中的箭头并不是可以任意连接的,他是把不同条件下的连接关系画到了一起。这上面提到了两个新的名词,一个是Gstreamer,一个是V4L2。下面简单介绍。
1.1 Gstreamer
Gstreamer是一个跨平台的多媒体框架,应用程序可以通过管道(Pipeline)的方式实现各种多媒体处理需求。它的官网是这里。Gstreamer框架的应用分层如下,图片来自官方文档。
可以看到,主要分为三层,最上层是一些Gstreamer tools和多媒体应用,中间是Gstreamer核心框架,最下面是Gstreamer自己或者第三方的插件。比如我们在之前博客中获取树莓派CSI相机数据使用到的gst-launch-1.0 nvarguscamerasrc
前半部分就是Gstreamer自带的工具,后半部分则是NVIDIA自己开发的Gstreamer插件。
1.2 V4L2
V4L2其实我们在之前这篇笔记中已经介绍过了,此处不再赘述。简单来说他是Linux内核提供给应用程序访问音视频驱动的统一接口,提供了一整套设备驱动和API的合集,让应用程序和用户可以方便的访问USB相机等各种设备。他的相机架构示意如下,图片来自上面提到的笔记。 在上面Gstreamer的架构中,可以看到V4L2是作为Gstreamer的一个插件而存在的。所以换句话说,Gstreamer相比于V4L2更加高层次一些。
2.Jetson平台Camera API
2.1 支持的连接方式与软件
在Jetson平台中,主要可以以两种方式连接相机,第一种是利用MIPI CSI(Camera Serial Interface)相机。比如Jetson Nano有专门的CSI接口可以用于连接CSI相机。第二种方式利用USB端口,连接普通的USB相机。下图是Jetson平台上相机API的简单介绍。 如前面这篇笔记提到的,Jetson板子一般都自带了一些加速多媒体处理的ISP,以达到更高效率。所以这里就有几种情况。如果使用CSI相机(比如树莓派相机模块V2),我们可以使用libargus、GStreamer(GST-nvarguscamerasrc)、V4L2三种方式来获取数据。区别在于,前两种方式会使用Jetson的ISP,而后一种方式不会使用Jetson的ISP。如果使用USB相机,那么在Jetson平台上,只能够通过V4L2来获取数据。从这个图中,我们可以得到以下三个结论:
- 普通的USB相机是没办法使用libargus的,只有CSI接口的相机才可以使用
- Jetson硬件一般自带ISP,官方推荐使用libargus控制相机,以获得更好的性能
- 从可玩性和开发性角度来说,要想使用libargus、Gstreamer等一系列功能,必须用CSI相机而非USB相机
所以,结合上面的描述和之前博客,我们可以对相机获取相机数据进行一个简单的总结。
对于CSI相机:
- 基于libargus库开发程序,获取数据
- 使用NVIDIA开发的Gstreamer插件nvarguscamerasrc获取数据(本质上是调用Argus API)
- 使用NVIDIA开发的Gstreamer插件v4l2src获取数据(本质上是调用V4L2)
- 使用NVIDIA开发的Gstreamer应用nvstcapture获取数据(本质上是调用Argus API)
- 使用OpenCV开发获取数据(本质上调用nvarguscamerasrc插件)
- 使用V4L2获取数据
对于USB相机:
- 使用NVIDIA开发的Gstreamer应用nvstcapture获取数据(本质上是调用V4L2)
- 使用NVIDIA开发的Gstreamer插件v4l2src获取数据(本质上是调用V4L2)
- 使用OpenCV开发获取数据(本质上调用V4L2)
- 使用V4L2获取数据
所以,对于USB相机而言,他的流程应该是如下所示。
最后,关于nvstcapture更多相关信息可以参考这个网页和这个网页。关于nvarguscamerasrc和v4l2src可以参考这个网页和这个网页。关于libargus库相关信息可以参考这个网页。关于V4L2可以参考之前这篇博客。
2.2 支持的相机传感器
在NVIDIA官方的这个网页中,给出了目前Jetson“认可”的相机模块,如下所示。 因此,如果想选购相机在Jetson平台上做开发,最好先来这里查一查看要买的相机是否被Jetson官方支持,不然有可能买回来用不了。比如没有合适的驱动、相机接口不兼容、获取不了特定格式的数据(比如Bayer Raw)等问题。在这个网页中也说,为了能够使用Jetson自带的ISP,我们必须使用CSI接口相机(To be able to utilize ISP, we need a camera with CSI interface)。因为CSI接口是相机向Jetson发送数据的关键,这个过程可以使用libargus(CSI interface is the key feature to send data from a camera to Jetson with a possibility to utilize ISP libargus for image processing)。
对于非CSI相机(比如USB相机),我们是没有办法直接使用Jetson的ISP的,进而使用一些更高级的功能。当然,也有一些SDK提供对非CSI相机的支持,比如Fastvideo SDK,官网是这个。这是一个基于CUDA开发的影像视频处理框架,覆盖从raw数据解析到各类常见处理函数,如下。 它的使用流程示意如下。 不过这里还是需要说明一点,尽管如Fastvideo等SDK可以支持raw数据的处理,但假如相机本身不支持raw数据输出,那么Fastvideo SDK再支持也无济于事。因此如果想用Fastvideo SDK处理USB相机的raw数据,那么一定要先确保相机本身支持raw数据输出。
2.3 CSI相机与USB相机的比较
在前面,我们介绍了Jetson平台对于CSI相机和USB相机的支持情况。在这里,我们进一步比较一下两者的异同。本部分主要参考这个网页。两种相机的特点如下:
USB相机特点:
- 优:方便集成、即插即用、使用广泛
- 优:可依靠自身ISP进行影像工作(如曝光、帧率控制),而无需依赖主机,减轻主机负担
- 优:可以以比较长的距离工作(相比于CSI数据线,USB数据线可以做的更长)
- 优:有更多更大感光元件的摄像头传感器可以选择(得益于USB相机的广泛普及)
- 优:可以通过制造商或平台提供的各种API在更抽象(和硬件无关)层次控制相机
- 缺:一定程度上会占用CPU资源,因为其依赖的USB总线会占用一定CPU资源
- 缺:不能充分利用主机的视觉加速硬件(如编码器等)
CSI相机特点:
- 优:针对CPU和内存的操作进行了专门优化,性能更高
- 优:可以充分利用主机视觉加速硬件
- 优:可以对传感器/相机进行更底层的控制,自定义性更强(相比于USB相机)
- 缺:相比于USB相机工作距离较短(CSI数据线不容易做长,否则需要较高成本)
- 缺:大多数CSI相机的感光元件较小,成像可能不如USB相机(高端或定制的感光元件除外)
选择建议:
- 如果有高性能需求(高帧率、高分辨率等)并且需要在底层控制相机,那么CSI相机更合适。
- 如果需求比较简单,只需要能拍照,没有特殊要求,USB相机会是最方便的选择。
所以可以看出来,普遍而言,CSI相机会取得比USB相机更好的表现。下面进行解释。关于CSI、USB相机更多的描述,可以参考这个网页。
2.4 为什么CSI相机比USB相机表现更好
一般而言,限制USB相机的主要因素是USB的带宽。尽管USB3.0理论带宽可以达到5Gbps,但是在实际应用中很可能是达不到理论值的,造成了USB相机表现下降。而对于CSI相机而言,一方面可以提供较高的带宽专门用于相机数据,另一方面可以充分利用主机自带的ISP进行处理。这样的好处就是减轻了主机CPU的负载,同时避免了数据在内存之间的来回拷贝,提升了效率。相机数据在拍摄以后,直接交给ISP,处理完成后再给CPU。一句话总结就是CSI相机利用了专门用于影像视频处理的硬件,显著提升了性能。
3.参考资料
- [1] https://jetsonhacks.com/2022/02/02/in-practice-usb-cameras-on-jetson/
- [2] https://gstreamer.freedesktop.org/
- [3] https://gstreamer.freedesktop.org/documentation/application-development/introduction/gstreamer.html?gi-language=c
- [4] https://developer.nvidia.com/embedded/learn/tutorials/first-picture-csi-usb-camera
- [5] https://developer.ridgerun.com/wiki/index.php/JetsonTX2/GStreamer/nvgstcapture-1.0
- [6] https://docs.nvidia.com/jetson/archives/l4t-archived/l4t-325/index.html#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/jetson_xavier_camera_soft_archi.html#
- [7] https://docs.nvidia.com/jetson/l4t-multimedia/index.html
- [8] https://developer.ridgerun.com/wiki/index.php?title=NVIDIA_Jetson_ISP_Control#NVIDIA_Jetson_ISP_Control_Description
- [9] https://www.fastcompression.com/blog/jetson-image-processing.htm
- [10] https://www.fastcompression.com/products/sdk.htm
- [11] https://developer.nvidia.com/embedded/jetson-partner-supported-cameras?t1_supported-jetson-products=Orin
- [12] https://on-demand.gputechconf.com/gtc/2016/webinar/getting-started-jetpack-camera-api.pdf
- [13] https://petermoran.org/csi-cameras-on-tx2/
- [14] https://forums.developer.nvidia.com/t/best-cameras-for-jetson/49494/5
- [15] https://elinux.org/Jetson/Cameras
本文作者原创,未经许可不得转载,谢谢配合