将采用D415深度学习相机,连接全志OK527板子,通过mipi屏幕做一个人脸识别系统。
本文所做工作是将相机连接板子并在屏幕上输出画面。
此环节的流程大概是硬件连接后检查->是否识别到usb->dmesg看内核日志看是否绑定上对应驱动->检查设备文件,找到相机对应的设备文件->打开D415设备文件下对应的彩色节点->输出彩色画面。
1.检查是否识别到usb
相机通过USB3.0与板子连接,连上后需要检查是否识别到usb设备,输入命令:
input:lsusb output: Bus 003 Device 001: ID 1d6b:0002 Bus 001 Device 001: ID 1d6b:0002 Bus 004 Device 001: ID 1d6b:0001 Bus 002 Device 001: ID 1d6b:0003 Bus 003 Device 003: ID 8086:0ad3 Bus 003 Device 002: ID 1a40:0101Bus表示总线号,后面的Device代表根设备,观测输出查官方设备号表可知,8086:0ad3即为D415相机的设备号,其挂载在总线3下的003号根设备上,而Linux设定总线下的Device:001代表的ID后面四位表示其对应的USB代次,通过Bus 003 Device 001: ID 1d6b:0002可发现3号总线对应的是USB2.0,而相机是USB3.0,说明插错了usb口,随后重新插到USB3.0上。
2.观察是否绑定了对应驱动
而后需要查内核看是否绑定了对应驱动,输入命令:
input:dmesg | grep -iE 'uvc|8086|RealSense|video' output: usbcore: registered new interface driver uvcvideo//说明本板子中存在uvcvideo驱动设备 usb 3-1.3: New USB device found, idVendor=8086, idProduct=0ad3, bcdDevice=51.10 usb 3-1.3: Product: Intel(R) RealSense(TM) Depth Camera 415 usb 3-1.3: Manufacturer: Intel(R) RealSense(TM) Depth Camera 415 uvcvideo 3-1.3:1.1: Unknown video format 00000050-0000-0010-8000-00aa00389b71 usb 3-1.3: Found UVC 1.50 device Intel(R) RealSense(TM) Depth Camera 415 (8086:0ad3) input: Intel(R) RealSense(TM) Depth Ca as /devices/platform/soc@3000000/4200000.ehci1-controller/usb3/3-1/3-1.3/3-1.3:1.0/input/input19 usb 3-1.3: Found UVC 1.50 device Intel(R) RealSense(TM) Depth Camera 415 (8086:0ad3) # ← 这是 USB2 / EHCI(看上一行路径里的 ehci1-controller) usb 1-1: New USB device found, idVendor=8086, idProduct=0ad3, bcdDevice=51.10 usb 1-1: Product: Intel(R) RealSense(TM) Depth Camera 415 usb 1-1: Manufacturer: Intel(R) RealSense(TM) Depth Camera 415 uvcvideo 1-1:1.1: Unknown video format 00000050-0000-0010-8000-00aa00389b71 usb 1-1: Found UVC 1.50 device Intel(R) RealSense(TM) Depth Camera 415 (8086:0ad3) input: Intel(R) RealSense(TM) Depth Ca as /devices/platform/soc@3000000/12.usbc2/4d00000.xhci2-controller/xhci-hcd.23.auto/usb1/1-1/1-1:1.0/input/input20 usb 1-1: Found UVC 1.50 device Intel(R) RealSense(TM) Depth Camera 415 (8086:0ad3) # ← 这是 USB3 / xHCI(要用的;看上一行路径里的 xhci-hcd)由于内核日志太多,因此需要从全本日记里面筛关键词,-iE代表忽视大小写,而搜索uvc是因为USB 摄像头在 Linux 上几乎都走 UVC,驱动名是uvcvideo,8086是刚刚看到的id,RealSense是深度相机的厂家型号,video在摄像头文件里面涉及最广。
从日志输出来看,由于刚才误插入2.0后又改成插入3.0所以出现了两次插入历史。
usb 1-1: Found UVC 1.50 device Intel(R) RealSense(TM) Depth Camera 415 (8086:0ad3)表示挂载在总线1的1号口上,且已绑定uvc,并被当成了UVC1.5设备。
3.检查设备文件,找到相机对应的设备文件
目前确定了设备已经绑定了驱动之后,需要找到对应的设备文件才能进行后续的文件操作,输入:
input: ls -l /dev/video* which v4l2-ctl output: crw-rw---- 1 root video 81, 0 Jan 1 08:00 /dev/video0 crw-rw---- 1 root video 81, 37 Jan 1 08:02 /dev/video1 crw-rw---- 1 root video 81, 3 Jan 1 08:00 /dev/video12 crw-rw---- 1 root video 81, 4 Jan 1 08:00 /dev/video16 crw-rw---- 1 root video 81, 5 Jan 1 08:00 /dev/video17 crw-rw---- 1 root video 81, 38 Jan 1 08:02 /dev/video2 crw-rw---- 1 root video 81, 39 Jan 1 08:02 /dev/video3 crw-rw---- 1 root video 81, 1 Jan 1 08:00 /dev/video4 crw-rw---- 1 root video 81, 40 Jan 1 08:02 /dev/video5 crw-rw---- 1 root video 81, 41 Jan 1 08:02 /dev/video6 crw-rw---- 1 root video 81, 42 Jan 1 08:02 /dev/video7 crw-rw---- 1 root video 81, 2 Jan 1 08:00 /dev/video8 /usr/bin/v4l2-ctl通过ls可以初步确认存在video设备节点,但无法确认具体的设备节点是哪个,一般来说,给项目open()的设备文件都是挂载在/dev下面。通过时间戳其实也可以初步辨别再插上D415相机后出现了video1/2/3/5/6/7。然而不同的节点其功能不同,对于当前需要输出彩色画面,需要找到对应的彩色节点。
因此需要用到v4l2-ctl调试工具,V4L2 是 Linux 里摄像头(以及部分视频采集/输出设备)的标准接口。而v4l2-ctl 是在命令行里操作 V4L2 设备的工具,用于发现设备文件,查询并修改文件参数,还可以取走节点数据。
通过which命令找到了工具的位置,下面需要用工具找到对应的彩色节点。
4.找到D415设备文件下对应的彩色节点
输入:
input: v4l2-ctl --list-devices for d in /dev/video1 /dev/video2 /dev/video3 /dev/video5 /dev/video6 /dev/video7; do echo "==== $d" v4l2-ctl -d $d --list-formats-ext 2>/dev/null | head -n 25 done output: sunxi-vin (): /dev/video0 /dev/video4 /dev/video8 /dev/video12 /dev/video16 /dev/video17 Allwinner Vin (platform:sunxi-vin-media): /dev/media0 Intel(R) RealSense(TM) Depth Ca (usb-xhci-hcd.23.auto-1): /dev/video1 /dev/video2 /dev/video3 /dev/video5 /dev/video6 /dev/video7 /dev/media1 /dev/media2 ==== /dev/video1 ioctl: VIDIOC_ENUM_FMT Type: Video Capture [0]: 'Z16 ' (16-bit Depth) Size: Discrete 256x144 ... 90 fps Size: Discrete 480x270 / 640x360 / 640x480 / 848x480 / 1280x720 (各种帧率) ==== /dev/video2 ioctl: VIDIOC_ENUM_FMT Type: Video Capture (下面没有 [0],没有格式) ==== /dev/video3 ioctl: VIDIOC_ENUM_FMT Type: Video Capture [0]: 'GREY' (8-bit Greyscale) 480x270 / 640x360 / 640x480 / 848x480 / 1280x720 [1]: 'UYVY' (UYVY 4:2:2) (head 截断,只看到 480x270 开头) ==== /dev/video5 ioctl: VIDIOC_ENUM_FMT Type: Video Capture (同样没有格式) ==== /dev/video6 ioctl: VIDIOC_ENUM_FMT Type: Video Capture [0]: 'YUYV' (YUYV 4:2:2) 424x240(60/30/15/6 fps) 640x480(30/15/6 fps) 1280x720(15/10/6 fps) 1920x1080(8 fps) ==== /dev/video7 ioctl: VIDIOC_ENUM_FMT Type: Video Capture (没有格式)通过v4l2-ctl --list-devices指令能够按「哪台相机」把 /dev/video* 分组列出来,从输出可以看出有三组,sunxi代表全志片内的CSI/VIN摄像头接口,ALLwinner Vin代表同一套 VIN 的 媒体控制器节点,用来描述内部管线,相当于全志这块 VIN(视频输入)硬件内部怎么接线的说明书,在下面的Intel RealSense即表示深度相机设备,可以看出其对应的节点。
而下面的for.....命令则是对 D415 那几个节点逐个问「你会什么格式」,好从里面挑出彩色口,其具体解释如下:
for d in /dev/video1 /dev/video2 /dev/video3 /dev/video5 /dev/video6 /dev/video7; do 对列表里每一个路径,把名字存进变量 d,循环一遍。这里故意没写 video0/4/8/...,那些是空的 sunxi-vin。 echo "==== $d" 先打印 ==== /dev/video6 这类分隔,否则六段输出会糊成一坨。 v4l2-ctl -d $d --list-formats-ext 2>/dev/null | head -n 25 -d $d:问当前这个节点 --list-formats-ext:格式、分辨率、帧率 2>/dev/null:报错不刷屏(空节点常有 ioctl 失败) head -n 25:每个节点最多 25 行,避免某口分辨率特别多把串口刷爆 done 结束循环。通过输出可得知各个节点对应的含义,其中YUYV代表彩色节点,因此/dev/video6即为所要找的彩色节点,对应节点含义如下:
5.输出彩色画面
目前已经找到了彩色节点,下面需要对节点进行读取操作,不同于点灯程序的是,相机文件更加复杂,节点得到的元数据需要按照对应的协议进行解码转换输出才能最终得到彩色画面,一般来说,为了简便使用,可以直接调用GStreamer或者FFmeg框架,这些框架内部提供现成的程序帮助直接进行取流转换操作,输入命令:
input: which gst-launch-1.0 ffplay gst-play-1.0 export XDG_RUNTIME_DIR=/var/run output: /usr/bin/gst-play-1.0 /usr/bin/gst-launch-1.0用which命令查找是否存在对应框架程序,从输出可看出出厂镜像带 GStreamer,没有 ffplay。不必交叉编译预览程序。export用于给当前串口会话设环境变量,不设的话,管道往往取流成功但画不到 MIPI。不过其只对当前终端有效,重开 Xshell 或重启要再执行一次。
找到框架程序后,输入命令:
input: gst-launch-1.0 v4l2src device=/dev/video6 ! video/x-raw,format=YUY2,width=640,height=480,framerate=30/1 ! videoconvert ! waylandsink 对应含义: v4l2src device=/dev/video6:打开彩色口 video/x-raw,format=YUY2,width=640,height=480,framerate=30/1:指定 640×480@30(和 v4l2-ctl 列出的能力一致,适合 1024×600 小屏) videoconvert:转格式 waylandsink:画到 Weston/MIPI执行输入程序后,摄像头打开工作,按 Ctrl + C停止程序。
针对输入命令的最后一项。“waylandsink:画到 Weston/MIPI”代表通过 Wayland 协议,把相机帧交给 Weston,再显示到 MIPI。Weston是这块板上正在跑的图形桌面,Linux 上应用一般不直接操作屏幕,中间有一层「谁在管屏幕」,管屏幕的那个进程叫 Weston,而Wayland 是一套「应用程序怎么把窗口交给屏幕」的协议。而waylandsink是 GStreamer 里专门把画面交给Weston的出口插件。前面export XDG_RUNTIME_DIR=/var/run设置环境就是为了让waylandsink能找到Weston的Socket,将数据顺利传入进去。
不过由于在Xshell一次性粘贴命令时出现了长命令被撕碎的情况,且程序运行时反馈刷屏日志,因此对输入命令稍作修改如下:
intput: set +H dmesg -n 3 export XDG_RUNTIME_DIR=/var/run gst-launch-1.0 v4l2src device=/dev/video6 ! videoconvert ! waylandsink fullscreen=true set +H 关掉 bash 的历史展开。否则命令里的 ! 会被当成「重复上一条命令」,整句粘坏。只对当前串口会话有效。 dmesg -n 3 把往控制台打的内核日志压到级别 3。减轻 crtc 94 刷屏,方便看到 GStreamer 自己的字。 export XDG_RUNTIME_DIR=/var/run 告诉程序去 /var/run 找 Weston 的 Wayland 套接字。waylandsink 靠这个把窗口交给桌面。重开 Xshell 要再执行一次。