JetsonNano+OpenCV+Gstreamer 实现摄像头捕获的构建方法和工作原理

JetsonNano+OpenCV+Gstreamer 实现摄像头捕获的构建方法和工作原理

入手 Nano 后发现官方镜像包含的 OpenCV 并不支持 python3。眼看 python2 要退出时代潮流了,这里整理了重新构建 OpenCV 的流程步骤,并简单解释了 JetsonNano+OpenCV+Gstreamer 结构的工作原理。

I. 参考文档

https://jkjung-avt.github.io/setting-up-nano/
https://github.com/jkjung-avt/jetson_nano
https://jkjung-avt.github.io/opencv-on-nano/
https://www.jetsonhacks.com/2019/04/02/jetson-nano-raspberry-pi-camera/
https://github.com/JetsonHacksNano/CSI-Camera
https://blog.csdn.net/u011337602/article/details/81485246
https://developer.download.nvidia.cn/embedded/L4T/r31_Release_v1.0/Docs/Accelerated_GStreamer_User_Guide.pdf

II. 环境搭建

假如,你的 Nano 是刚刷的镜像,运行环境没有大的改变,那么搭建 OpenCV+Gstreamer 的过程非常简单。
1、当然,首先已经有了一个 Nano,并完成了初始环境的搭建。参考步骤
2、然后,要有一个摄像头,为了节省 USB 接口(用它们的地方出乎想象的多),还是买一个板载摄像头吧,已经测试可用的型号是 IMX-219。参考步骤
3、值得庆幸的是官方的镜像包含 Gstreamer 不需要重新安装。这里安装的是 opencv-3.4.6 版本,安装步骤非常简单:

$ sudo nvpmodel -m 0   # 把 Nano 性能开到最大模式(10W)
$ sudo jetson_clocks   
$ cd ${HOME}/project   # 开始安装
$ git clone https://github.com/jkjung-avt/jetson_nano.git
$ cd ${HOME}/project/jetson_nano
$ ./install_opencv-3.4.6.sh

4、安装过程中会遇到卡点:由于网络问题 get-pip.py 以及后面通过 pip 安装依赖包的过程中,都会因为 timeout 而屡屡失败,可以尝试通过修改 ~/.pip/pip.conf 中的 timeout 来避免失败,但是下载速度还是惨不忍睹。参考步骤

wget https://bootstrap.pypa.io/get-pip.py -O $folder/get-pip.py
sudo python3 $folder/get-pip.py
sudo python2 $folder/get-pip.py
sudo pip3 install protobuf
sudo pip2 install protobuf
sudo pip3 install -U numpy matplotlib
sudo pip2 install -U numpy matplotlib

我的解决方案是,复制在安装过程中显示的下载连接,直接下载安装包(可能需要 FanQiang),然后通过 pip3 install numpy-1.17.2.zip
5、如果安装过程中发生失败,脚本执行中断,没有关系,重新跑一边就行。如果有心研究,也可以自己复制文件中的脚本,逐行执行。

jetsonnano:~/Jetson-Nano/RoBFang/opencv$ sudo pip3 install -U numpy matplotlib
Collecting numpy
  Downloading https://files.pythonhosted.org/packages/ac/36/325b27ef698684c38b1fe2e546e2e7ef9cecd7037bcdb35c87efec4356af/numpy-1.17.2.zip (6.5MB)

III. 测试代码

1、安装完成后,迫不及待要测试一把,先在命令行分别单独测试:

# 测试摄像头
$ gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM),width=3820, height=2464, framerate=21/1, format=NV12' ! nvvidconv flip-method=2 ! 'video/x-raw,width=960, height=616' ! nvvidconv ! nvegltransform ! nveglglessink -e
# 测试 OpenCV
$ python3 -c 'import cv2; print("python3 cv2 version: %s" % cv2.__version__)'
$ python2 -c 'import cv2; print("python2 cv2 version: %s" % cv2.__version__)'

2、然后,找一个基于 OpenCV 的 识别人脸 的代码试试:

wget https://github.com/JetsonHacksNano/CSI-Camera/archive/master.zip -O CSI-Camera.zip
unzip CSI-Camera.zip
cd CSI-Camera
python3 face_detect.py

这里应该会遇到一个错误,因为检测器的文件路径不对,使用 locate haarcascade_eye.xml 找一下就好。

face_detect.py:
    face_cascade = cv2.CascadeClassifier(
        "~YourPath~/haarcascade_frontalface_default.xml"
    )
    eye_cascade = cv2.CascadeClassifier(
        "~YourPath~/haarcascade_eye.xml"
    )

IV. 工作原理

1、在测试代码中我们可以看到,即使不用 OpenCV,简单实用 gst-launch-1.0 就能展示摄像头拍到的视频。所以,不难理解,它们的关系是:Gstreamer 捕获摄像头的原始视频流数据;OpenCV 以帧(frame)为单位,进行处理(面部识别等)和运算后展现出来。
2、Gstreamer 的 pipeline 是由多个 element 串连起来,数据流从 src 到 sink 参考文档

1# nvarguscamerasrc ! 
2# 'video/x-raw(memory:NVMM), width=3820, height=2464, framerate=21/1, format=NV12' ! 
3# nvvidconv flip-method=2 ! 
4# 'video/x-raw,width=960, height=616' ! 
5# nvvidconv ! 
6# nvegltransform ! 
7# nveglglessink -e
标号角色作用
1src element通过ARGUS API获取相机数据
2capabilities约定数据源原有格式(3820x2464),NVMM 指定应在连续内存中分配缓冲区
3common element格式转换:垂直翻转图像
4capabilities约定数据输出格式(960x616)
5common element格式转换
6common element转换为 EGLimage,EGL 是渲染 API 和原生窗口系统之间的接口
7end element向 X11 桌面系统显示 EGL 视频

3、OpenCV 面部识别 代码地址

face_cascade = cv2.CascadeClassifier("~YourPath~/haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier("~YourPath~/haarcascade_eye.xml")
cap = cv2.VideoCapture(gstreamer_pipeline(), cv2.CAP_GSTREAMER)
if cap.isOpened():
    cv2.namedWindow("Face Detect", cv2.WINDOW_AUTOSIZE)
    while cv2.getWindowProperty("Face Detect", 0) >= 0:
        ret, img = cap.read()
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
            roi_gray = gray[y : y + h, x : x + w]
            roi_color = img[y : y + h, x : x + w]
            eyes = eye_cascade.detectMultiScale(roi_gray)
            for (ex, ey, ew, eh) in eyes:
                cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)
        cv2.imshow("Face Detect", img)
        keyCode = cv2.waitKey(30) & 0xFF
        # Stop the program on the ESC key
        if keyCode == 27:
            break
函数名作用
CascadeClassifier加载特征分类器(人脸/人眼)
VideoCapture读取视频
namedWindow新建一个显示窗口
getWindowProperty窗口是否关闭(返回 -1 为关闭)
cvtColor改变色彩空间
rectangle画一个矩形
face_cascade.detectMultiScale检测出图片中所有的人脸
eye_cascade.detectMultiScale检测出图片中所有的人眼
imshow把图片显示出来
waitKey等待按键(ESC) 30ms
  • 3
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值