本文共 9930 字,大约阅读时间需要 33 分钟。
dvg-utils是一组工具,可以帮助你使用OpenCV快速构建图像和视频处理管道。
在不同的平台和设备上进行计算机视觉和深度学习的实验带来了许多挑战,尤其是当你希望与团队共同维护一个代码库而不需要做重复的工作。从不同设备设置视频流的步骤基本上是一样的,该过程我们需要记录日志,读取配置文件,绘制带有标签的框,保存结果,收集一些指标等,为什么不将这些工作放在一起呢?这就是本文向你介绍dvg-utils的意义。
dvg-utils简介
设置
命令行工具
捕获视频
捕获图像
例子
指标
概要
资源
自从我写了第一篇关于为图像和视频处理创建一个模块化而且简单的管道的文章以来,差不多过去一年了,从那以后我也一直在学习,学到了很多东西。在这段时间里,我做了许多不同的项目,它们总是需要相同的步骤。
每个计算机视觉管道都需要以下代码块:
设置日志
读取配置文件
捕获图像或视频流
处理数据
可视化结果
显示结果
保存结果
收集指标
这些代码块中的大多数都是在每个项目中会反复出现的模板代码。
为了更轻松,更快速地设置计算机视觉项目,我在SławomirGilewski的帮助下创建了dvg-utils Python软件包。
dvg-utils:https://github.com/jagin/dvg-utils
SławomirGilewski:https://medium.com/u/1ddaceb8aa71
在开始之前,我建议使用Python虚拟环境。虚拟环境允许你在系统上运行独立的Python环境,更多请看一下RealPython上的这篇文章。
https://realpython.com/python-virtual-environments-a-primer/
我假设你正在使用具有Linux或MacOs系统的台式机/笔记本电脑(我没有机会在Windows平台上对其进行测试,但它应该可以运行)。
如果你想从Jetson设备运行一些示例,Jetpack的SDK已经安装了OpenCV,你可以跳过pip install opencv-contrib-python这一步骤。
对于树莓派用户,请在此文章的帮助下安装OpenCV 。
https://www.pyimagesearch.com/2019/09/16/install-opencv-4-on-raspberry-pi-4-and-raspbian-buster/
为了浏览库和用法示例,让我们克隆它并安装所需的软件包:
$ git clone https://github.com/jagin/dvg-utils.git$ cd ./dvg-utils$ pip install tqdm pyyaml numpy$ pip install opencv-contrib-python$ pip install dvg-utils
安装dvg-utils后,你可以访问dvg-utils工具命令:
将视频文件转换为一组图像
$ dvg-utils v2i -i assets/videos/faces.mp4 -o output --display
将一组帧图像转换为视频文件
$ dvg-utils i2v -i output -o output/my_new_file.avi --display
绘制指标(我将在本故事的后面部分对此进行详细介绍)
对于参数描述,请运行以下命令之一:
$ dvg-utils v2i -h$ dvg-utils i2v -h$ dvg-utils pm -h
如果可以分别处理每一帧,则将视频转换为图像并返回,你可以并行处理这些帧,然后将它们组合回带有可视注释的视频文件中。
dvg-utils的强大功能来自于从OpenCV cv2.VideoCapture和树莓派相机支持的所有源捕获视频流,使用单线:
video_capture = VideoCapture(conf["videoCapture"]).open()
技巧是使用conf["videoCapture"]
,其中包含我们的视频捕获配置的字典,该字典从YAML配置文件中读取,参考:https://medium.com/swlh/python-yaml-configuration-with-environment-variables-parsing-77930f4273ac (向Maria Karanasou致谢,她使用环境变量parsing进行了Python YAML配置)
videoCapture: capture: file file: src: assets/videos/cars_driving.mp4 # You can select the frame range for a video file # start_frame: 100 # end_frame: 500 camera: src: 0 fourcc: MJPG resolution: [640, 480] fps: 30 piCamera: src: 0 resolution: [640, 480] framerate: 30 settings: rotation: 180 stream: # Jetson Nano camera stream src: >- nvarguscamerasrc sensor-id=0 sensor_mode=3 ! video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12, framerate=(fraction)30/1 ! nvvidconv flip-method=2 ! video/x-raw, width=(int)640, height=(int)480, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink api_preference: CAP_GSTREAMER
我们可以定义不同的来源(file
,camera
,piCamera
,stream
),但我们想要选择的属性在videoCapture.capture
里面(在上面的例子中是assets/videos/cars_driving.mp4
文件)。
让我们运行./examples/capture_video.py
示例以查看实际效果:
$ python ./examples/capture_video.pyINFO: Load configuration from config/capture_video.ymlINFO: Capturing file: assets/videos/cars_driving.mp4INFO: Codec: avc1INFO: Resolution: 1280x720INFO: FPS: 50.0INFO: Capturing...INFO: 3000 it, 13.106 s, 0.004 s/it, 228.89 it/s3000it [00:13, 228.88it/s]
这个简单的例子是你学习视频处理管道的一个很好的起点。它已经包括:
配置文件 config/capture_video.yml
,它规定可在不同平台上使用的不同的视频源
记录器来显示可用信息:记录器选项在 logger.yml
文件中定义,我们通过 setup_logger()
从 dvgutil
包中调用函数来进行设置,
显示带有处理后的帧数和预测的FPS结果:dvgutils.vis
带有helper函数的程序包可以很好地放置一些文本,绘制覆盖矩形或调整图像大小,并保留长宽比或填充,
保存带注释的输出视频选项:包中有SaveVideo
和SaveImage
类,dvgutils.modules
可轻松保存视频和图像,
用于保存有关管道性能的指标选项:通过包中的Metrics
类,dvgutils.modules
可以收集指标(如迭代时间,每秒迭代次数,每次迭代的秒数),你可以使用dvg-utils pm
命令进行绘制。
这是完整的选项列表:
$ python ./examples/capture_video.py -husage: capture_video.py [-h] [-cf CONF] [-cfo CONF_OVERWRITES [CONF_OVERWRITES ...]] [-o OUTPUT] [--no-display] [--no-progress] [--pipeline] [--metrics METRICS] [--fps FPS]optional arguments: -h, --help show this help message and exit -cf CONF, --conf CONF Path to the input configuration file (default: config/capture_video.yml) -cfo CONF_OVERWRITES [CONF_OVERWRITES ...], --conf-overwrites CONF_OVERWRITES [CONF_OVERWRITES ...] -o OUTPUT, --output OUTPUT output video file name --no-display hide display window --no-progress don't display progress --pipeline run as pipeline --metrics METRICS metrics file name --fps FPS output video fps
之前我提到过,我们可以使用其他输入源来运行管道。如何实现呢?有两种方法:
在config/capture_video.yml
部分设置capture
属性videoCapture
到选定的源(file
,camera
,piCamera
,stream
)
使用选项-cfo videoCapture.capture=<selected_source>
执行管道,该选项将覆盖YAML配置中的设置。
要使用网络摄像头执行示例,请运行:
$ python ./examples/capture_video.py -cfo videoCapture.capture=camera
如果你在树莓派上运行示例,则需要在树莓派上运行pip install picamera
。
你可以通过在显示屏上按ESC(只是将其关闭或在终端中按Ctrl + C)来中断该处理,所有这些操作都在dvgutils.modules
的ShowImage
类中处理。
capture_video.py
示例包含两个不同的实现方式,用于说明目的。第一个是一个简单的while循环,其中我们使用dvg-utils包中的通用类处理视频帧:
# Setup processing modulesvideo_capture = VideoCapture(conf["videoCapture"]).open()save_video = SaveVideo(args["output"])show_image = ShowImage("Video")metrics = Metrics().start()progress = Progress(disable=not args["progress"])while True: # Grab the frame frame = video_capture.read() if frame is None: break ... # Do some processing and visualization save_video(frame) show = show_image(frame) if not show: break metrics.update() progress.update() idx += 1
第二个基于流水线的概念,在流水线的概念中,我们定义了处理块,并借助Python生成器将数据推送到该流(CaptureVideoPipe
是一个生成器,生成的帧数据通过管道步骤进行映射)。
# Setup pipeline stepscapture_video_pipe = CaptureVideoPipe(conf["videoCapture"])save_video_pipe = SaveVideoPipe("vis_image", args["output"])show_image_pipe = ShowImagePipe("vis_image", "Video")metrics_pipe = MetricsPipe()progress_pipe = ProgressPipe(disable=not args["progress"])# Create pipelinepipeline = Pipeline(capture_video_pipe)pipeline.map(...) # Do some processing and visualizationpipeline.map(save_video_pipe)pipeline.map(show_image_pipe)pipeline.map(metrics_pipe)pipeline.map(progress_pipe)# Process pipelinepipeline.run()
创建模块化管道可以使我们有机会在不同项目中重用通用块。
使用dvg-utils,你可以几乎以与视频帧相同的方式来处理图像。examples/capture_image.py
是一个很好的示例。
使用以下配置(config/capture_image.yml
):
imageCapture: path: assets/images/friends valid_ext: jpg #contains: some_string # Transform image transform: resize: width: 320 flip: 1 # 0 - vertical, 1 - horizontal, -1 - vertical and horizontal
你可以从assets/images/friends
目录中读取所有JPG文件,甚至在它们运行你的处理代码之前对其进行转换:
$ python ./examples/capture_image.py
dvg-utils包含许多示例,这些示例说明了如何构建图像或视频处理管道。让我们在 examples
文件夹中看看其中的一些示例。
我们可以使用以下命令运行对象检测示例:
$ python ./examples/detect_object_video.pyINFO: Load configuration from config/detect_object_video.ymlINFO: Capturing file: assets/videos/people_walking.mp4INFO: Codec: avc1INFO: Resolution: 402x300INFO: FPS: 30.0INFO: Capturing...INFO: 1283 it, 54.567 s, 0.043 s/it, 23.51 it/s1283it [00:54, 23.51it/s]
该示例默认情况下会检测行人。
只需进行少量配置,即可在需要时检测汽车:
$ python ./examples/detect_object_video.py -cfo videoCapture.file.src=assets/videos/cars_driving.mp4 objectDetector.caffe.classes=\["cars"\]
detect_object_video.py
在examples/modules/object_detector/caffe_object_detector.py
中使用Caffe MobileNet-SSD模型,并在config/detect_object_video.yml
中进行配置(请参阅objectDetector
部分)。
Caffe MobileNet-SSD:https://github.com/chuanqi305/MobileNet-SSD
要跟踪对象,我们需要先对其进行检测。我们已经有了对象检测器,可以在跟踪管道中重用它(此示例需要pip install scipy dlib
):
$ python ./examples/track_object_video.pyINFO: Load configuration from config/track_object_video.ymlINFO: Capturing file: assets/videos/people_walking.mp4INFO: Codec: avc1INFO: Resolution: 402x300INFO: FPS: 30.0INFO: Capturing...INFO: 1283 it, 11.233 s, 0.009 s/it, 114.21 it/s1283it [00:11, 114.17it/s]
在我们的例子中,我们可以使用管道来实现这两种目标跟踪算法。一个基于OpenCV Tracking API (默认使用KCF tracker),第二个基于Dlib包。你可以通过在config/track_object_video.yml
中改变objectTracker.tracker
设置来激活它,或者运行:
$ python ./examples/track_object_video.py -cfo objectTracker.tracker=dlib
以下文章对两种跟踪器都有很好的解释:
使用OpenCV跟踪对象
https://www.learnopencv.com/object-tracking-using-opencv-cpp-python/
使用dlib进行对象跟踪
https://www.pyimagesearch.com/2018/10/22/object-tracking-with-dlib/
这个例子说明了尝试不同算法是多么容易。
目标检测是跟踪的基础,目标跟踪是对被定义的虚拟线中的对象进行计数。这条线可能是商店的入口,而目标可能是一个人,所有这些我们都可以在不触及代码行的情况下进行配置。
要查看运行中的对象计数器,请执行以下操作:
$ python ./examples/count_object_video.pyINFO: Load configuration from config/count_object_video.ymlINFO: Capturing file: assets/videos/people_walking.mp4INFO: Codec: avc1INFO: Resolution: 402x300INFO: FPS: 30.0INFO: Capturing...INFO: 1283 it, 11.631 s, 0.009 s/it, 110.31 it/s1283it [00:11, 110.27it/s]
本文很好地描述了此示例的思想:
OpenCV人群计数
https://www.pyimagesearch.com/2018/08/13/opencv-people-counter/
但我将其扩展为可以在图像的任何位置定义任何行(多亏有dvgutils.vis
????),它在config/count_object_video.yml
中具有:
objectCounter: line: [10, 220, 290, 120] # x1, y1, x2, y2
使用不同的算法,解决方案或方法进行试验需要评估指标,通过评估指标我们可以知道哪种解决方案效果最好。
dvg-utils的dvgutils.modules
包含用于收集指标的Metrics类,例如:
迭代执行时间
每秒平均迭代次数
每次迭代的平均毫秒数
让我们运行带有--metrics选项的对象计数器示例:
$ python ./examples/count_object_video.py --metrics output/count_object_video.csv
将指标保存到output/count_object_video.csv
文件中。
为了显示算法在FPS(每秒处理的帧数或迭代数)上下文中的性能,我们使用dvg-utils命令行工具(此命令要求pip install matplotlib
):
$ dvg-utils pm output/count_object_video.csv -c ips
我们可以在对象计数器中使用Dlib跟踪器代替OpenCV的KCF :
$ python ./examples/count_object_video.py --metrics output/count_object_video_dlib.csv -cfo objectTracker.tracker=dlib
并比较结果:
$ dvg-utils pm -i output/count_object_video.csv -i output/count_object_video_dlib.csv -c ips
每秒执行117次迭代(即帧),而Dlib跟踪器平均只能以71 FPS的速度运行。
我希望本文可以引起你对使用dvg-utils作为OpenCV实验工具的兴趣,并能帮助你创建富有远见的想法。
使用dvg-utils的主要好处是你可以快速创建计算机视觉管道并在不同的来源(例如,台式网络摄像头,树莓派照相机,带有树莓派照相机的Jetson设备,图像和视频文件等)上对其进行测试,而无需更改代码,只需通过配置即可。
我一直在学习的两个主要的资源:
PyImageSearch
https://www.pyimagesearch.com/
学习OpenCV
https://www.learnopencv.com/
参考链接:https://medium.com/deepvisionguru/dvg-utils-a-swiss-army-knife-for-opencv-processing-pipeline-b680357c084b
☆ END ☆
如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 mthler」,每日朋友圈更新一篇高质量博文。
↓扫描二维码添加小编↓
转载地址:http://jvov.baihongyu.com/