CSI vs USB camera on JetsonTX2

1、为什么要用CSI camera

如果您希望获得最佳性能(较快的FPS,较高的分辨率和较少的CPU使用情况),或者需要对摄像机进行底层控制,并且您愿意买一个不错的摄像头,CSI摄像头应该是您所以这些性能的优质选项。

我个人使用CSI相机,因为我需要高分辨率的视频,同时保持可接受的帧率。 在TX2搭配 Leopard Imaging IMX377CS 摄像头,我轻松以〜20 fps的速度拖动4k视频, 实在太棒了。 我也喜欢CSI相机上具备更换镜头的能力,通常使用小型C-Mount或M12镜头。 由于GoPro的流行,有很多C/CS-Mount镜头以及用于将数码单反相机镜头转换为C-Mount的镜头转接器.
从另一方面来讲,USB摄像头的价格非常便宜,通常通过V4L2协议即可使用,对于不需要高性能视频的应用来说,它是一个很好的选择。 你可以用$20买到720p视频罗技C270,正如加州州立理工大学在他们有据可查的文件中所做的机器人套件,这足以让他们的机器人玩具车识别并收集物体、找到人脸、定位线等。

CSI camera与 USB camera的比较

一个在Nvidia开发人员论坛上发布了非常棒的文章用户Jazza指出USB和CSI相机之间的进一步比较:
USB相机:
· 优:很容易整合。
· 优:可以做很多的离线的图像工作(曝光控制,帧率等)。
· 优:提供输入/中断功能,可为您节省计算应用程序时间(例如,在新帧上中断)。
· 缺:由于USB总线使用CPU时间,如果使用高的CPU占用,这会影响您的应用程序。
· 缺:对于使用硬件视觉管线(硬件编码器等)不是最佳的。
· 优:可以长距离工作(最高可达USB标准)。
· 优:可以支持更大的图像传感器(1英寸或更高,以获得更好的图像质量和更少的噪音)。
CSI相机:
· 优:根据CPU和内存使用情况进行优化,以便将图像处理并存入内存。
· 优:可以充分利用硬件的视觉管线。
· 缺:支持较短距离(通常不超过10cm)。除非您使用序列化系统(GMSL,FPD Link,COAXPress,Ambarella),但这些系统目前尚不成熟并且需要定制。
· 缺:通常与手机相机模块的小型传感器一样,要不就得多花点钱去定制。通过TX1/2中的硬件去噪降低小传感器的额外噪音。
· 优:可执行底层访问与控制传感器/摄像头。


MIPI Camera Serial Interface 2 (MIPI CSI-2)
A widely adopted, simple, high-speed protocol primarily intended for point-to-point image and video transmission between cameras and host devices.


USB的最大问题是带宽处理能力
USB 3.0可以推送5Gbps,技术上足以接受60 fps/1080p或20fps/4K(3840p)未压缩的视频流。但是,这仅仅基于带宽,并没有揭示处理视频时额外处理和内存管理瓶颈的真相。 例如,See3CAM_CU130 USB 3.0相机应该可以达到60fps 1080p,但在TK1上真测结果,只能支持18 fps/1080p压缩格式,而未压缩的格式只有1fps。虽然在计算性能更强的机器上性能会更好,但这是问题的根源。
 
相反,Jetson TX1和TX2支持6个专用的MIPI CSI-2摄像机端口,每通道(lans)带宽可达2.5 Gb/s,双图像服务处理器(ISP)提供1.4 Gigapix/s处理能力,换句话说,它具有三个4k摄像机(或者六个30fps/1080p相机)带宽。当然,带宽并非全部,因为这些图像需要移动和处理,但通过使用硬件视觉管道,图像可以跳过加载到DRAM中,并通过独立于主CPU处理视频来减少CPU负载。根据我自己的经验,通过利用TX2上的这些硬件功能,我能够以接近20 fps速度运行4k视频。这就是为什么视频可以通过CSI摄像头如此高效地工作 - 专用于视频的独立硬件,就像GPU专门用于3D图形一样。

2、Jetson TX2可以使用那些CSI camera

3、如何高效地从CSI camera获取视频,处理视频

方法一:
《Get Started with the JetPack Camera API》中提供Jetson的多媒体硬件(包括CSI相机的端口)接口的最佳方式是通过其libargus C ++库

方法二:
Nvidia不支持CSI相机的V4L2视频协议
但是可以使用 Gstreamer框架, NV提供了很多功能强大,效率很高的插件
例如:
nvcamerasrc  camera 图像获取

通过 gst-inspect-1.0 | grep omxgst-inspect-1.0 | grep nv命令,可以查看系统中有哪些硬件加速的插件和nv提供的插件

从CSI相机获取视频的关键在于能够
(1)在程序中使用gstreamer
(2)使用高效的管道。

关于驱动程序的注意事项:在任何GStreamer功能甚至可以正常工作之前,您很可能需要安装相机的驱动程序。 由于CSI相机的市场规模较小,因此您可能无法在网上找到指南,但应该能够从制造商处获得。例如,Leopard Imaging提供了一个很好的指导(通过电子邮件)来设置他们的驱动程序,但它让我只能在终端中使用GStreamer。

例如gst-launch

示例1:

//查看相机的1080p视频
gst-launch-1.0 nvcamerasrc ! 'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, \
format=(string)I420, framerate=(fraction)60/1' ! \
nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)I420' ! \
nvoverlaysink -e
##示例2:查看相机的1080p视频并将真实的fps输出到控制台。
gst-launch-1.0 nvcamerasrc ! 'video/x-raw(memory:NVMM),  \
width=(int)1920, height=(int)1080, format=(string)I420, framerate=(fraction)60/1'  \
! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)I420' ! \
fpsdisplaysink text-overlay=false -v


将捕获的video 送出,比如转成 BGR格式送入OpenCV

nvcamerasrc ! video/x-raw(memory:NVMM), width=1920, height=(int)1080,\
 format=(string)I420, framerate=(fraction)30/1 ! \
 nvvidconv flip-method=2 ! video/x-raw, format=(string)BGRx ! \
 videoconvert ! video/x-raw, format=(string)BGR ! appsink

CSI相机获得高质量性能的关键之一就是使用最高效的gstreamer管线。这通常意味着以正确的格式输出.
这里非常重要的部分是video/x-raw, format=(string)BGRx ! videoconvert ! video /x-raw, format=(string)BGR,它确保来自CSI相机的原始视频转换为BGR色彩空间。
 
在OpenCV和许多其他程序里,图像都是按照BGR格式存储。如果不转换,后面无法使用
通过图像管道预转换为BGR,我们确保使用这些硬件模块来转换图像而不是CPU。
如果不使用转换的管道会导致性能严重的下降,在TX2上1080p视频的最高速度只有10fps。

//gstreamer_view.cpp

/*
  Example code for displaying gstreamer video from the CSI port of the Nvidia Jetson in OpenCV.
  Created by Peter Moran on 7/29/17.
  https://gist.github.com/peter-moran/742998d893cd013edf6d0c86cc86ff7f
*/

#include 

std::string get_tegra_pipeline(int width, int height, int fps) {
    return "nvcamerasrc ! video/x-raw(memory:NVMM), width=(int)" + std::to_string(width) + ", height=(int)" +
           std::to_string(height) + ", format=(string)I420, framerate=(fraction)" + std::to_string(fps) +
           "/1 ! nvvidconv flip-method=2 ! video/x-raw, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink";
}

int main() {
    // Options
   int WIDTH = 1920;
   int HEIGHT = 1080;
   int FPS = 30;

    // Define the gstream pipeline
    std::string pipeline = get_tegra_pipeline(WIDTH, HEIGHT, FPS);
    std::cout << "Using pipeline: \n\t" << pipeline << "\n";

    // Create OpenCV capture object, ensure it works.
    cv::VideoCapture cap(pipeline, cv::CAP_GSTREAMER);
    if (!cap.isOpened()) {
        std::cout << "Connection failed";
        return -1;
    }

    // View video
    cv::Mat frame;
    while (1) {
        cap >> frame;  // Get a new frame from camera

        // Display frame
        imshow("Display window", frame);
        cv::waitKey(1); //needed to show frame
    }
}

//Nvidia的nvcamerasrc接口定义一个高效的流水线,
//并确保我们预转换为BGR色彩空间。
//然后我们定义一个使用GStreamer的捕获对象。
//最后,我们捕获每一帧并以无限循环显示它

参考文档
Gstreamer pipelines for Tegra X1

你可能感兴趣的:(gstreamer,流媒体开发)