参考:https://jkjung-avt.github.io/tx2-camera-with-python/

参考:http://blog.iotwrt.com/media/2017/08/23/opencv-gstreamer/

硬解码就是利用硬件芯片来解码的,TX2有单独的解码模块,NVDEC。软解码是用软件程序来解码,比较占用CPU资源。截止当前,nvidia的硬件编码官方提供了nvenc的方法,且在ffmpeg中已经增加了对nvenc的编码库。对于硬件解码,官方提供了基于cuda的解码方法,但是ffmpeg中还没有相应的解码库。

查看cpu gpu 以及编解码模块的使用: sudo ~/tegrastats

首先,要先讨论下为什么需要在OpenCV上用上Gstreamer, 比如我直接一个摄像头 v4l2 图像传给 OpenCV 不行吗?

Gstreamer是嵌入式平台处理Media的首选组件, 像Nvdia/TI/NXP/Rockchip平台, 都是使用Gstreamer来整合Media应用. 在Rockchip平台上, 我们已经有为Gstreamer开发了像Decode/Encode/ISP-Camera/2D加速器/DRM-Display-sink这些的Plugin。所以OpenCV如果链接上Gstreamer,输入源就不仅仅是摄像头, 还可以是RTSP/本地视频;输出显示的代码可以不用写, 让Gstreamer来显示; 转换格式让Gstreamer来转, 利用硬件加速; 处理的图像送回Gstreamer编码。

本文转载自JK Jung的帖子,在本贴中,贴主分享了如何使用python 代码及 OpenCV在Jetson TX2上抓取和显示摄像头视频,包括IP摄像头, USB 网络摄像头和Jetson板载摄像头,这个简单代码也同样可以在Jetson TX1上运行。

准备条件

  1. 需要在Jetson TX2上安装 GStreamer 支持的 python和OpenCV(opencv-3.4.0方法)
  2. 如果你是用 IP CAM, 你必须构建好,并且知道它的RTSP URI, 比如. rtsp://admin:XXXXX@192.168.1.64:554.
  3. 如果你是用USB 网络摄像头(I 使用的是罗技 C920),这个USB摄像头通常安装在 /dev/video1, 因为 Jetson 板载摄像头已经占用了 /dev/video0.
  4. 安装 gstreamer1.0-plugins-bad ,这个包含了 h264parse 元素. 这是为了解码来自IP摄像头的H.264 RTSP stream 所需要的(方法:sudo apt-get install gstreamer1.0-plugins-bad)

使用方法

OpenCV安装方法

参照buildOpenCVTX2的sh脚本进行手动编译。

注意-DWITH_GSTREAMER=ON要打开,如果要使用python3,则将-DBUILD_opencv_python3=OFF改为ON

代码下载

在GitHub上下载tegra-cam.py 源代码 ,代码如下

  1. import sys
  2. import argparse
  3. import cv2
  4. WINDOW_NAME = 'CameraDemo'
  5. def parse_args():
  6. # Parse input arguments
  7. desc = 'Capture and display live camera video on Jetson TX2/TX1'
  8. parser = argparse.ArgumentParser(description=desc)
  9. parser.add_argument('--rtsp', dest='use_rtsp',
  10. help='use IP CAM (remember to also set --uri)',
  11. action='store_true')
  12. parser.add_argument('--uri', dest='rtsp_uri',
  13. help='RTSP URI, e.g. rtsp://192.168.1.64:554',
  14. default=None, type=str)
  15. parser.add_argument('--latency', dest='rtsp_latency',
  16. help='latency in ms for RTSP [200]',
  17. default=200, type=int)
  18. parser.add_argument('--usb', dest='use_usb',
  19. help='use USB webcam (remember to also set --vid)',
  20. action='store_true')
  21. parser.add_argument('--vid', dest='video_dev',
  22. help='device # of USB webcam (/dev/video?) [1]',
  23. default=1, type=int)
  24. parser.add_argument('--width', dest='image_width',
  25. help='image width [1920]',
  26. default=1920, type=int)
  27. parser.add_argument('--height', dest='image_height',
  28. help='image height [1080]',
  29. default=1080, type=int)
  30. args = parser.parse_args()
  31. return args
  32. def open_cam_rtsp(uri, width, height, latency):
  33. gst_str = ('rtspsrc location={} latency={} ! '
  34. 'rtph264depay ! h264parse ! omxh264dec ! '
  35. 'nvvidconv ! '
  36. 'video/x-raw, width=(int){}, height=(int){}, '
  37. 'format=(string)BGRx ! '
  38. 'videoconvert ! appsink').format(uri, latency, width, height)
  39. return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
  40. def open_cam_usb(dev, width, height):
  41. # We want to set width and height here, otherwise we could just do:
  42. # return cv2.VideoCapture(dev)
  43. gst_str = ('v4l2src device=/dev/video{} ! '
  44. 'video/x-raw, width=(int){}, height=(int){}, '
  45. 'format=(string)RGB ! '
  46. 'videoconvert ! appsink').format(dev, width, height)
  47. return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
  48. def open_cam_onboard(width, height):
  49. # On versions of L4T prior to 28.1, add 'flip-method=2' into gst_str
  50. gst_str = ('nvcamerasrc ! '
  51. 'video/x-raw(memory:NVMM), '
  52. 'width=(int)2592, height=(int)1458, '
  53. 'format=(string)I420, framerate=(fraction)30/1 ! '
  54. 'nvvidconv ! '
  55. 'video/x-raw, width=(int){}, height=(int){}, '
  56. 'format=(string)BGRx ! '
  57. 'videoconvert ! appsink').format(width, height)
  58. return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
  59. def open_window(width, height):
  60. cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL)
  61. cv2.resizeWindow(WINDOW_NAME, width, height)
  62. cv2.moveWindow(WINDOW_NAME, 0, 0)
  63. cv2.setWindowTitle(WINDOW_NAME, 'Camera Demo for Jetson TX2/TX1')
  64. def read_cam(cap):
  65. show_help = True
  66. full_scrn = False
  67. help_text = '"Esc" to Quit, "H" for Help, "F" to Toggle Fullscreen'
  68. font = cv2.FONT_HERSHEY_PLAIN
  69. while True:
  70. if cv2.getWindowProperty(WINDOW_NAME, 0) < 0:
  71. # Check to see if the user has closed the window
  72. # If yes, terminate the program
  73. break
  74. _, img = cap.read() # grab the next image frame from camera
  75. if show_help:
  76. cv2.putText(img, help_text, (11, 20), font,
  77. 1.0, (32, 32, 32), 4, cv2.LINE_AA)
  78. cv2.putText(img, help_text, (10, 20), font,
  79. 1.0, (240, 240, 240), 1, cv2.LINE_AA)
  80. cv2.imshow(WINDOW_NAME, img)
  81. key = cv2.waitKey(10)
  82. if key == 27: # ESC key: quit program
  83. break
  84. elif key == ord('H') or key == ord('h'): # toggle help message
  85. show_help = not show_help
  86. elif key == ord('F') or key == ord('f'): # toggle fullscreen
  87. full_scrn = not full_scrn
  88. if full_scrn:
  89. cv2.setWindowProperty(WINDOW_NAME, cv2.WND_PROP_FULLSCREEN,
  90. cv2.WINDOW_FULLSCREEN)
  91. else:
  92. cv2.setWindowProperty(WINDOW_NAME, cv2.WND_PROP_FULLSCREEN,
  93. cv2.WINDOW_NORMAL)
  94. def main():
  95. args = parse_args()
  96. print('Called with args:')
  97. print(args)
  98. print('OpenCV version: {}'.format(cv2.__version__))
  99. if args.use_rtsp:
  100. cap = open_cam_rtsp(args.rtsp_uri,
  101. args.image_width,
  102. args.image_height,
  103. args.rtsp_latency)
  104. elif args.use_usb:
  105. cap = open_cam_usb(args.video_dev,
  106. args.image_width,
  107. args.image_height)
  108. else: # by default, use the Jetson onboard camera
  109. cap = open_cam_onboard(args.image_width,
  110. args.image_height)
  111. if not cap.isOpened():
  112. sys.exit('Failed to open camera!')
  113. open_window(args.image_width, args.image_height)
  114. read_cam(cap)
  115. cap.release()
  116. cv2.destroyAllWindows()
  117. if __name__ == '__main__':
  118. main()

板载相机

按照下面步骤利用Jetson板载摄像头抓取和显示影像。默认分辨率为 1920x1080 @ 30fps.

python tegra-cam.py

USB摄像头

按照下面步骤使用 USB 网络摄像头,并且把分辨率设置为1280x720. 注意‘–vid 1’意思是使用 /dev/video1.

python tegra-cam.py --usb --vid 1 --width 1280 --height 720

IP摄像头

按照下面步骤使用IP摄像头,把最后的RTSP URI 参数设置为你自己的IP CAM.

python tegra-cam.py --rtsp --uri "rtsp://192.168.171.199:554/user=admin&password=&channel=1&stream=0.sdp?"

如果使用上述指令报错,则输入以下指令,首先确认相机没有问题,然后再查找其他原因

gst-launch-1.0 rtspsrc location="rtsp://192.168.171.199:554/user=admin&password=&channel=1&stream=0.sdp?" ! rtph264depay ! h264parse ! omxh264dec ! nveglglessink

讨论

这个tegra-cam.py 脚本的关键是依靠GStreamer pipelines 我用来call cv.VideoCapture(). 在我的经验里,使用 nvvidconv 做图像缩放,用BGR做颜色格式转换(注意: OpenCV 需要 BGR 作为最后的输出) 在帧速率方面会有更好效果。

  1. def open_cam_rtsp(uri, width, height, latency):
  2. gst_str = ("rtspsrc location={} latency={} ! rtph264depay ! h264parse ! omxh264dec ! "
  3. "nvvidconv ! video/x-raw, width=(int){}, height=(int){}, format=(string)BGRx ! "
  4. "videoconvert ! appsink").format(uri, latency, width, height)
  5. return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
  6. def open_cam_usb(dev, width, height):
  7. # We want to set width and height here, otherwise we could just do:
  8. # return cv2.VideoCapture(dev)
  9. gst_str = ("v4l2src device=/dev/video{} ! "
  10. "video/x-raw, width=(int){}, height=(int){}, format=(string)RGB ! "
  11. "videoconvert ! appsink").format(dev, width, height)
  12. return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
  13. def open_cam_onboard(width, height):
  14. # On versions of L4T previous to L4T 28.1, flip-method=2
  15. # Use Jetson onboard camera
  16. gst_str = ("nvcamerasrc ! "
  17. "video/x-raw(memory:NVMM), width=(int)2592, height=(int)1458, format=(string)I420, framerate=(fraction)30/1 ! "
  18. "nvvidconv ! video/x-raw, width=(int){}, height=(int){}, format=(string)BGRx ! "
  19. "videoconvert ! appsink").format(width, height)
  20. return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)

这是我的Jetson TX2用IP摄像头运行tegra - cam的截图。

左图是公司高大上的机器人,右图显示了CPU占用情况,实际占用率比较高,与想象中GPU硬解情况不同,还不太清楚是什么原因,需要进一步分析

20180522更新:找到了CPU占用情况高的原因,是因为OpenCV显示占用CPU资源,如果关闭显示,或者将显示的内容变小,则CPU占用情况会下降

20180604更新:感谢楼下maxhn0的提示“cpu占用高的原因是硬解码解码出来的数据格式是nv12(待考证),而调用videoconvert这个插件实际上是在cpu上做的 nv12到 mat类型的bgr转换,这一步是最费CPU的步骤 显示只是gpu占用大”

20180611更新:在开发OpenCV + Gstreamer的过程中, 一定要尽量避免拷贝的发生, 如果一定要有, 也不能是由CPU来做. (替代可以是2D加速器, GPU) (当然这里用2D加速拷出来后buffer,默认还是uncached的,还是不适合CPU直接在上面处理,就算改成cache的,cache刷新的时间也要10ms+。。不过如果你的算法需要CPU去实时处理每帧的话,我想一般的ARM CPU都做不到吧)。根据以上原则, 开发的时候要避免调用到OpenCv的cvtcolor和clone这些函数, 因为每次拷贝都会消耗大量的CPU资源。

转载自: https://blog.csdn.net/zong596568821xp/article/details/80306987

TX2+GStreamer+OpenCV读取显示网络摄像头相关推荐

  1. python opencv 拍照_在jupyter noteb中使用opencv显示网络摄像头中的图像

    我正在尝试显示网络摄像头拍摄的图像.但是,存储捕获图像的变量是空的.此问题仅在使用网络摄像头时出现,而不是在播放mp4等视频时出现.这个问题是由Python版本引起的吗?我的OpenCV版本是3.4. ...

  2. qt 关闭窗口的槽函数_勇哥的VC++应用框架学习之QT(1) 信号槽、按钮控件、opencv读取显示图片...

    前言勇哥对于C语言,C++早些年有一些接触,这个系列贴子就记载一下C++应用框架的学习经验. 在写程序时,UI.基础类库.应用程序框架对于vc来讲,只能依靠MFC和QT了. 勇哥对MFC有很强的抵触, ...

  3. Python OpenCV显示网络摄像头

    import cv2 url = "http://192.168.0.100:8081" # 打开网络摄像头 cap = cv2.VideoCapture(url)# 创建可以调节 ...

  4. 播放和保存视频,图像倒置纠正到本地文件夹(含ffmpeg ,pyav多线程读取多路网络摄像头)

    播放一段视频并显示 import cv2if __name__ == '__main__':input_video_file_1 = 'smoking_20191011_154214.mp4'# se ...

  5. opencv java 显示图片_【opencv三】利用opencv读取显示图片

    在opencv中读取显示图片的头文件是highgui.hpp. 整体代码如下,如要测试自己的图片,需要将代码段中的图片地址更改为自己图片的绝对路径. #include "opencv2/hi ...

  6. wxpython播放视频_使用wxpython显示网络摄像头视频闪烁

    我是python的新手.我正在尝试编写一个运动检测应用程序.目前,我正在尝试将网络摄像头视频显示在屏幕上.当前的代码现在没有闪烁,但在任何调整大小后,闪烁将会回来.任何线索?另外,为什么没有self. ...

  7. OpenCV读取显示图片报错size.width>0

    OpenCV读取图片时 error: (-215:Assertion failed) size.width>0 && size.height>0 in function ' ...

  8. 【opencv四】利用opencv读取显示视频

    在opencv中读取显示视频的头文件是highgui.hpp.视频图像处理头文件imgproc.hpp. 整体代码如下,如要测试自己的图片,需要将代码段中的图片地址更改为自己图片的绝对路径. #inc ...

  9. linux获取网络摄像头视频教程,在Linux中读取USB网络摄像头的输出

    我在C中用fread和fwrite进行了一些实验,所以我在C中写了这个小程序,从网络摄像头获取数据并将其转储到一个文件中.以下是来源: #include #include #define SIZE 3 ...

最新文章

  1. h5在手机端实现简单复制
  2. 实现DDD领域驱动设计: Part 1
  3. 云存储技术-JDK的安装
  4. 华为交换机命令_华为交换机常用命令
  5. ORA-02298: 无法验证 (约束) - 未找到父项关键字 解决办法
  6. python绘图库seaborn_Matplotlib Toolkits:python高级绘图库seaborn
  7. Nginx日志分割处理
  8. UOJ #357. 【JOI2017春季合宿】Sparklers
  9. 揭秘百度新治理结构:马东敏的谣言与李彦宏的用人观
  10. Linux SPI驱动(Linux驱动开发篇)
  11. 抓取微信小程序页面丶小程序源码
  12. Vue+el-table实现不规则表格
  13. 人类实体瘤临床细胞状态和生态系统图谱(EcoTpyer)
  14. 目前计算机常用的CPU型号,价格差异太大了!教你选择CPU型号及常见CPU后缀字母详解...
  15. IT数据中心第三方运维服务市场概况
  16. 如何进行实时频谱分析仪的二次开发——MATLAB、C++、labview开发环境的部署
  17. 一天测血压的最佳时间_一天内什么时间量血压最好?
  18. PMP考试 | 点击率最高 的100个主要知识点
  19. 建行u盾弹不出来_关于建设银行网银的问题```
  20. 编译型语言与解释型语言的区别及各自的优缺点

热门文章

  1. Pentaho Data Integration - Kettle 入门指南
  2. 使用ZooKeeper编程 - 一个基本教程
  3. RIP报文封装、OSPF封装、OSPF——cost值
  4. php获取apk中文应用名,php提取apk包信息 - 搜知道网 - 搜知道社区,C, iOS,Android,golang 等的知识....
  5. db platform mysql_xss-platform
  6. 一个WordPress站点绑定多个域名
  7. sysv-rc-conf --- Linux设置开机自动启动
  8. vue2学习计划1-2 浏览器跨域问题
  9. 记录一次可能的order by注入
  10. 因此,您处于if / else地狱中-这是摆脱困境的方法