用Numba加速OpenCV Python视频处理代码,提升6.5倍性能
使用Numba对OpenCV Python视频处理代码加速。性能提升6.5倍
1、目标问题:
在 OpenCV Python 中视频处理是比较耗资源的,从而造成画面卡顿,如果跳帧处理可能造成丢失关键数据。用 Numba对 OpenCV代码加速是1个较好的改进方法。
Numba是1个Python编译器,主要功能是对数组类型(Array, Numpy, bytes等)、数值类型的函数进行加速,支持GPU计算,以及能避开GIP限制。使用只须加入简单的导入与函数装饰器代码即可,非常方便。
实际效果如何呢? 本文将通过实例代码来比较,对于 OpenCV显示与处理视频流的代码,未优化前,与 Numba 优化后的速度来进行对比分析。
2、Numba安装与使用方式简介
2.1 安装Numba库
pip install numba
2.2 Numba 的使用方式
2.2.1 基本使用方式
Numba的使用,间通过在函数代码前加个装饰器,如下
# 导入相当包
from numba import jit
import numpy as np@jit # jit装饰器
def sum(a, b):return a + b
2.2.2 No GIL模式
如果函数内运算量比较大,而调用者希望尽可能短时间处理,可以采用多CPU来运算, 装饰器内添加参数 nogil=True
@jit(nogil=True)
def sum(a, b):return a + b
2.2.3 No python 模式
即用git装饰的函数在运行时,不需要解释器介入,直接以机器码的方式运行,其实就是按C的方式运行,这种方式最快。装饰器传入参数 nopython=True。 示例
@jit(nopython=True)
def sum(a, b):return a + b
3、项目要求
OpenCV中的视频帧都是由NumPy数组表示的图像。在此示例中,使用网络摄像头捕获视频流,并对视频流上实时进行计算和修改,这样对每帧的处理时间提出了很高的要求。
为了保持流畅的视频,需要在 1/25 秒内显示每一帧。这样,每一帧最多需要 0.04 秒,从捕获、处理和使用视频流更新窗口。
虽然捕获和更新窗口需要时间,但它留下了很大的不确定性,帧处理(计算和修改)的速度应该有多快,但上限是每帧 0.04 秒。
4、对每帧进行计算和修改
为了测试。增加1个对图像处理方法,功能如下。
- 计算。我们将每帧划分为6×16像素的小区域,并计算每个区域的平均颜色。为了获得平均颜色,我们计算每个通道的平均值(BGR)。
- 修改。对于每个区域,我们将更改每个区域的颜色,并完全用平均颜色填充它。
这可以通过添加此功能来处理每一帧来完成。
def process(frame, box_height=6, box_width=16):height, width, _ = frame.shapefor i in range(0, height, box_height):for j in range(0, width, box_width):roi = frame[i:i + box_height, j:j + box_width]b_mean = np.mean(roi[:, :, 0])g_mean = np.mean(roi[:, :, 1])r_mean = np.mean(roi[:, :, 2])roi[:, :, 0] = b_meanroi[:, :, 1] = g_meanroi[:, :, 2] = r_meanreturn frame
画面将划分为矩形区域(box_height x box_width)。对于每个框(roi:感兴趣区域)3个颜色通道(b_mean,g_mean,r_mean)中每个的平均值,并将该区域覆盖为颜色平均值
5、测试处理函数的性能
为了估计函数过程中花费的时间,使用了cProfile 库。它提供了每个函数调用所花费时间的分析。
import cv2
import numpy as np
import cProfiledef process(frame, box_height=6, box_width=16):height, width, _ = frame.shapefor i in range(0, height, box_height):for j in range(0, width, box_width):roi = frame[i:i + box_height, j:j + box_width]b_mean = np.mean(roi[:, :, 0])g_mean = np.mean(roi[:, :, 1])r_mean = np.mean(roi[:, :, 2])roi[:, :, 0] = b_meanroi[:, :, 1] = g_meanroi[:, :, 2] = r_meanreturn framedef main(iterations=300):# Get the webcam (default webcam is 0)cap = cv2.VideoCapture(0)# If your webcam does not support 640 x 480, this will find another resolutioncap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)for _ in range(iterations):# Read the a frame from webcam_, frame = cap.read()# Flip the frameframe = cv2.flip(frame, 1)frame = cv2.resize(frame, (640, 480))frame = process(frame)# Show the frame in a windowcv2.imshow('WebCam', frame)# Check if q has been pressed to quitif cv2.waitKey(1) == ord('q'):break# When everything done, release the capturecap.release()cv2.destroyAllWindows()
cProfile.run("main()")
输出
ncalls tottime percall cumtime percall filename:lineno(function)300 7.716 0.026 50.184 0.167 test_numba.py:8(process)
从输出中可以看出,process函数中每次调用使用 0.026 秒,而主循环中其他函数的开销累积到 0.014 秒。
ncalls tottime percall cumtime percall filename:lineno(function)300 5.132 0.017 5.132 0.017 {method 'read' of 'cv2.VideoCapture' objects}300 0.073 0.000 0.073 0.000 {resize}300 2.848 0.009 2.848 0.009 {waitKey}300 0.120 0.000 0.120 0.000 {flip}300 0.724 0.002 0.724 0.002 {imshow}
另外,每次迭代中从读取、调整大小、翻转、显示和 waitKey 调用中产生大约 0.028 秒 (0.017 + 0.009 + 0.002) 的开销。
每帧处理时间,加起来总共为每帧 0.054 秒,或者只能达到每秒 18.5 帧 (FPS) 的帧速率,这太慢了,无法达到每秒24帧的平滑播放。
当然,cProfile 会增加一些开销来测量时间,暂时忽略。
6、引入 Numba 以优化性能
Numba 库旨优势在于编译代码,使 NumPy 循环更快。而 opencv-python图像正是以numpy数组与运算为基础,所以非常适合用Numba来加速。下面是添加了number语句的代码。
import cv2
import numpy as np
from numba import jit
import cProfile@jit(nopython=True)
def process(frame, box_height=6, box_width=16):height, width, _ = frame.shapefor i in range(0, height, box_height):for j in range(0, width, box_width):roi = frame[i:i + box_height, j:j + box_width]b_mean = np.mean(roi[:, :, 0])g_mean = np.mean(roi[:, :, 1])r_mean = np.mean(roi[:, :, 2])roi[:, :, 0] = b_meanroi[:, :, 1] = g_meanroi[:, :, 2] = r_meanreturn framedef main(iterations=300):# Get the webcam (default webcam is 0)cap = cv2.VideoCapture(0)# If your webcam does not support 640 x 480, this will find another resolutioncap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)for _ in range(iterations):# Read the a frame from webcam_, frame = cap.read()# Flip the frameframe = cv2.flip(frame, 1)frame = cv2.resize(frame, (640, 480))frame = process(frame)# Show the frame in a windowcv2.imshow('WebCam', frame)# Check if q has been pressed to quitif cv2.waitKey(1) == ord('q'):break# When everything done, release the capturecap.release()cv2.destroyAllWindows()
main(iterations=1)
cProfile.run("main(iterations=300)")
输出。
ncalls tottime percall cumtime percall filename:lineno(function)300 1.187 0.004 1.187 0.004 test_numba.py:7(pixels)
每次调用需要 0.004 秒。这导致每次迭代的总时间为 0.032 秒 (0.028 + 0.004)。这足以保持每秒 24 帧 (FPS) 以上的性能。
此外,这将性能提高了 6.5 倍 (7.717 / 1.187)。
7、结论
从网络摄像头捕获实时流并处理及显示,使用 Numba 来加速后。处理速度提升约为 6.5 倍。
上述测试基于集成显卡电脑。如果电脑配置有支持CUDA的显卡,速度提升更加明显,请自行测试。
后续将继续推出 cython对opencv-python代码优化后对性能提升测试, 敬请关注作者
用Numba加速OpenCV Python视频处理代码,提升6.5倍性能相关推荐
- python视频处理代码_python如何实现视频转代码视频
本文实例为大家分享了python如何实现视频转代码视频的具体代码,供大家参考,具体内容如下 # -*- coding:utf-8 -*- #coding:utf-8 import argparse i ...
- opencv+python视频实时质心显示
利用opencv+python实现以下功能: 1)获取实时视频,分解帧频: 2)将视频做二值化处理: 3) 将视频做滤波处理(去除噪点,获取准确轮廓个数): 4)识别图像轮廓: 5)计算质心: 6)描 ...
- OpenCV—Python视频的读取及保存
运行环境 Anaconda=5.3 | python=3.7 一.从摄像头中获取视频 创建一个VideoCapture对象.它的参数可以是设备索引或视频文件的名称(下面会讲到).设备索引只是指定哪台摄 ...
- 答题卡识别任务--opencv python(附代码)
答题卡识别 项目理论和源码来自唐宇迪opencv项目实战 记一篇python-opencv 完成答题卡识别 项目的学习笔记 输入一张特定格式的答题卡图片(答题卡中题目数量和选项个数是固定的),能够输出 ...
- OpenCV—python 视频分析背景提取与前景提取
文章目录 一.算法 二.代码 MOG2(Mixture of Gaussian) 与 KNN对比 Kmeans 行人检测代码 OpenCV中支持的两种背景提取算法都是 基于模型密度评估,然后在 像素级 ...
- 光流 | OpenCV中的Lucas-Kanade光流与稠密光流:基于Opencv+Python(附代码)
===================================================== github:https://github.com/MichaelBeechan CSDN: ...
- 计算机视觉与深度学习 | ORB特征提取:基于OpenCV+Python(附代码)
===================================================== github:https://github.com/MichaelBeechan CSDN: ...
- 大道至简,仅需4行代码提升多标签分类性能!ICCV21 南大提出Residual Attention
▊ 写在前面 多标签图像识别是一项具有挑战性的计算机视觉任务.然而,目前解决这一任务的方法复杂.计算量大.缺乏直观解释 .为了能够有效地感知不同类别物体所占据的空间区域,作者提出了一个非常简单的模块, ...
- 运行opencv保存视频时出现错误的解决方法
运行repo代码时,用opencv保存结果视频的时候,如果出现以下问题: 一.明明有写opencv保存的代码,但是就是没保存视频 解决方法:这时候就要定位到opencv保存视频的代码里去,一般保存视频 ...
最新文章
- Qt设置QLabel的样式
- matlab中real函数,Matlab中del2()函数学习笔记
- Django生命周期
- PyQt5简介及demo
- 北风设计模式课程---2、工厂方法模式
- 前端判断数据类型的通用方法
- JavaScript 第一课 JavaScript简史
- arcgis双标准纬线等角圆锥投影_世界地图是怎么制作出来的,各投影算法的来历...
- 点击网页跟踪php代码的工具,使用ltrace工具跟踪PHP库函数调用的方法
- python调用nacos账号密码_python-nacos-sdk
- php表单选择题代码,php 表单代码
- Vue3.0 + Ts 项目框架搭建二:路由 Router
- 加载JDBC驱动程序
- 相似矩阵对角化 | 找到一个可逆矩阵 P 使得 P^(-1)AP 成为一个对角矩阵
- YOLACT论文阅读及解析
- 罗辑思维2017-2018跨年演讲摘要
- 企业邮箱如何发送国外邮件?2021知名企业邮箱网站排名
- 惊了,深圳房价比北京还高。。。
- 如何在指定网站搜索内容
- android代码控制组件的移动,Android自定义控件实现随手指移动的小球