opencv如何使用GPU的三种方法

news2024/12/23 3:23:29

我在工作实验涉及到图像和视频处理时,通常使用opencv提供的库来做处理,虽然OpenCV是一个广泛使用的库,它提供了丰富的功能和工具。然而,有时候在处理大量图片或视频时,我们可能会面临速度受限的问题。

opencv执行图像处理,就跟我们电脑一样,打游戏CPU是来加载处理数据的,显卡(GPU)是来渲染图像。下面由我助理来介绍如何本文的内容吧

在这里插入图片描述

numpy运算加速

一开始我其实考虑使用python其他库来加速图像处理的计算,因为在计算机视角下的图像是可以等价为numpy类型的数值,在Python中,有几个库可以加速NumPy运算。其中最常用的库是NumPy本身,它已经高度优化,可以提供快速的数值计算。但是,如果你需要进一步加速NumPy运算,可以考虑下面这个库:

Numba:Numba是一个即时(just-in-time)编译器,可以将Python函数编译成高效的机器码。它支持在NumPy数组上进行加速运算。你可以使用装饰器@numba.jit将函数编译为机器码,以提高其性能。

以下是一个使用Numba加速NumPy运算的示例代码:

import numba
import numpy as np



def cpu_function(a):
    # 在这里编写需要加速的NumPy运算代码
    trace = 0
    # 假设输入变量是numpy数组
    for i in range(a.shape[0]):   # Numba 擅长处理循环
        trace += np.tanh(a[i, i])  # numba喜欢numpy函数
    return a + trace

@numba.jit(nopython=True)
def gpu_function(a):
    # 在这里编写需要加速的NumPy运算代码
    trace = 0
    # 假设输入变量是numpy数组
    for i in range(a.shape[0]):   # Numba 擅长处理循环
        trace += np.tanh(a[i, i])  # numba喜欢numpy函数
    return a + trace
    


# 调用加速后的函数
x = np.arange(10000).reshape(100, 100)


print('cpu执行时间:')
% timeit cpu_function(x)
print('gpu执行时间:')
% timeit gpu_function(x)
cpu执行时间:
199 µs ± 1.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
gpu执行时间:
4.18 µs ± 32.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

1 微秒(us)=0.000001 秒

但这种方法对于读取视频速度还是没有影响的,为了解决这个问题,我们可以利用GPU加速来提高图像和视频的读取速度。使用OpenCV的cuda模块,我们可以将解码和处理操作从CPU转移到GPU上,以利用GPU的并行计算能力。这种方式可以显著提高处理速度,特别是在大规模图像和视频处理的情况下。下面我将介绍三种opencv使用GPU的方法

opencv内置函数运算

在OpenCV的Python绑定中,可以使用一些内置函数来利用GPU进行加速。以下是使用GPU加速的方法和原理:

  1. 安装正确的依赖项:与使用DNN模块相同,首先需要确保在系统上安装了与GPU加速相关的依赖项,包括CUDA和cuDNN。
  2. 创建GPU加速的函数:在OpenCV中,某些函数可以利用GPU进行加速,例如图像处理函数(如滤波、图像变换等)和矩阵操作函数(如矩阵乘法、转置等)。这些函数在使用时需要将数据传递到GPU上进行处理。
  3. 分配GPU内存:在使用GPU加速函数之前,需要为输入和输出数据在GPU上分配内存。可以使用cv2.cuda.alloc()函数来为输入和输出数据创建GPU内存。
  4. 将数据传输到GPU:将输入数据从主机内存(CPU)传输到GPU内存。可以使用cv2.cuda_GpuMat.upload()函数将数据从CPU内存上传到GPU内存。
  5. 执行GPU加速函数:调用相应的GPU加速函数,传递GPU上的输入数据作为参数,并在GPU上进行计算。这些函数将直接在GPU上执行,以获得加速的效果。
  6. 从GPU中下载数据:如果需要将结果数据从GPU内存下载到主机内存,可以使用cv2.cuda_GpuMat.download()函数。这样,就可以在主机上进行后续的处理或输出。

下面是一个结合前面的计时器类的示例代码,展示了如何使用OpenCV的cv2.calcOpticalFlowFarneback函数进行图像的光流计算预处理,并通过CPU和GPU实现对比执行速度:

import cv2
import time

# 图像预处理函数(CPU实现)
def preprocess_image_cpu(img):
    # 在这里进行图像预处理
    # 转换为灰度图像  
	gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
	  
	# 直方图均衡化  
	equalized = cv2.equalizeHist(gray)  
	  
	# Sobel锐化  
	sobelx = cv2.Sobel(equalized, cv2.CV_64F, 1, 1, ksize=3)  
	sobely = cv2.Sobel(equalized, cv2.CV_64F, 0, 1, ksize=3)  
	sober = np.sqrt(sobelx ** 2 + sobely ** 2) 

	# 显示原图、直方图均衡化后的图像、Sobel锐化后的图像  
	cv2.imshow('Original', img)  
	cv2.imshow('Equalized', equalized)  
	cv2.imshow('Sober', sober)  
	  
	cv2.waitKey(0)  
	cv2.destroyAllWindows() 


# 图像预处理函数(GPU实现)
def preprocess_image_gpu(img):
    if not cv2.cuda.getCudaEnabledDeviceCount():
        print("CUDA is not available. Please make sure CUDA drivers are installed.")
        return

    gpu_image = cv2.cuda_GpuMat()
    gpu_image.upload(img)

    # 在这里进行图像预处理(GPU实现)
    # 转换为灰度图像  
	gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
	  
	# 直方图均衡化  
	equalized = cv2.equalizeHist(gray)  
	  
	# Sobel锐化  
	sobelx = cv2.Sobel(equalized, cv2.CV_64F, 1, 1, ksize=3)  
	sobely = cv2.Sobel(equalized, cv2.CV_64F, 0, 1, ksize=3)  
	sober = np.sqrt(sobelx ** 2 + sobely ** 2) 

	# 显示原图、直方图均衡化后的图像、Sobel锐化后的图像  
	cv2.imshow('Original', img)  
	cv2.imshow('Equalized', equalized)  
	cv2.imshow('Sober', sober)  
	  
	cv2.waitKey(0)  
	cv2.destroyAllWindows() 

# 读取图像
image_path = "path/to/image.jpg"
image = cv2.imread(image_path)

print('cpu执行时间:')
% timeit preprocess_image_cpu(image)
print('gpu执行时间:')
% timeit preprocess_image_gpu(image)

openCV DNN 模块

在OpenCV的Python绑定中,DNN模块可以利用GPU加速来进行深度神经网络的推理。以下是使用GPU加速的方法和原理:

  1. 安装正确的依赖项:首先,确保你的系统上安装了与GPU加速相关的依赖项。这通常包括安装CUDA(Compute Unified Device Architecture)和cuDNN(CUDA Deep Neural Network)。
  2. 配置OpenCV编译选项:在编译OpenCV时,需要确保启用了GPU加速选项。可以使用CMake进行编译配置,通过启用相关的CUDA选项来启用GPU加速支持。
  3. 加载模型和权重:使用OpenCV的DNN模块加载深度神经网络模型和相应的权重文件。例如,可以使用cv2.dnn.readNet()函数加载模型。
  4. 设置推理设备:使用cv2.dnn_DNN_BACKEND_CUDA和cv2.dnn.DNN_TARGET_CUDA参数设置推理设备为CUDA。
  5. 配置网络:为了使用GPU加速,需要将网络配置为使用CUDA。可以使用net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)和net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)方法设置网络的后端和目标。
  6. 进行推理:现在,可以使用GPU加速进行深度神经网络的推理。使用net.forward()方法来运行前向传播,并获取网络的输出。

下面是一个结合计时器的示例代码,展示了如何使用OpenCV的dnn模块进行图像处理,并通过CPU和GPU实现对比执行速度:

import cv2
import time

# 图像处理函数(CPU实现)
def process_image_cpu(image):
    # 在这里进行图像处理(CPU实现)
    # ...

    return processed_image

# 图像处理函数(GPU实现)
def process_image_gpu(image):
    if not cv2.cuda.getCudaEnabledDeviceCount():
        print("CUDA is not available. Please make sure CUDA drivers are installed.")
        return

    net = cv2.dnn.readNetFromCaffe("path/to/caffe/prototxt", "path/to/caffe/model")
    blob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size=(300, 300), mean=(104.0, 177.0, 123.0), swapRB=True)

    gpu_blob = cv2.cuda_GpuMat()
    gpu_blob.upload(blob)

    net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
    net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)

    gpu_net = cv2.dnn_DetectionModel(net)
    gpu_net.setInput(gpu_blob)

    start_time = time.time()
    gpu_detection = gpu_net.forward()
    end_time = time.time()
    gpu_execution_time = end_time - start_time

    # 在这里进行图像处理(GPU实现)
    # ...

    gpu_processed_image = gpu_blob.download()
    return gpu_processed_image, gpu_execution_time

# 读取图像
image_path = "path/to/image.jpg"
image = cv2.imread(image_path)


print('cpu执行时间:')
% timeit preprocess_image_cpu(image)
print('gpu执行时间:')
% timeit preprocess_image_gpu(image)

在上述代码中,我们定义了两个图像处理函数:process_image_cpu和process_image_gpu,分别表示CPU和GPU的实现方式。

读取视频

在Python中使用OpenCV读取视频时,可以使用GPU加速来提高读取速度。为此,你可以使用OpenCV的cuda模块以及支持CUDA的显卡驱动和CUDA工具包。

下面是一个示例代码,展示如何使用GPU加速在OpenCV中读取视频的每一帧:

import cv2

# 检查是否支持CUDA
if not cv2.cuda.getCudaEnabledDeviceCount():
    print("CUDA is not available. Please make sure CUDA drivers are installed.")
    exit()

# 创建GPU设备对象
gpu_id = 0  # 选择GPU设备的ID
device = cv2.cuda.Device(gpu_id)
ctx = device.createContext()

# 打开视频文件
video_path = "path/to/video/file.mp4"
cap = cv2.VideoCapture(video_path)

# 检查视频文件是否成功打开
if not cap.isOpened():
    print("Failed to open the video file.")
    exit()

# 设置GPU加速
cap.set(cv2.CAP_PROP_CUDA_MPS, 1)

# 循环读取视频的每一帧
while True:
    # 使用GPU加速读取一帧
    ret, frame = cap.read(cv2.CAP_CUDA)

    # 检查是否成功读取帧
    if not ret:
        break

    # 在这里进行你希望执行的操作
    # ...

# 释放资源
cap.release()
cv2.destroyAllWindows()

在上述代码中,首先检查是否支持CUDA,然后创建一个指定GPU设备的上下文(context)。接着打开视频文件,设置GPU加速,并循环读取视频的每一帧。读取过程中,使用cv2.CAP_CUDA作为参数来启用GPU加速。你可以在读取帧后的代码块中执行你希望的操作,例如对帧进行处理或展示。

请确保你的系统中已经正确安装了支持CUDA的显卡驱动和CUDA工具包,以及适用于GPU加速的OpenCV版本。同时,根据实际情况修改代码中的视频文件路径和GPU设备的ID。

下面是一个示例案例,演示了如何使用CPU和GPU分别读取视频,并使用time库计算二者读取视频的时间,并进行对比:

import cv2
import time

# 用CPU读取视频
def read_video_cpu(video_path):
    cap = cv2.VideoCapture(video_path)

    while True:
        ret, frame = cap.read()

        if not ret:
            break

        # 在这里进行你希望执行的操作
        # ...
    cap.release()


# 用GPU读取视频
def read_video_gpu(video_path):
    if not cv2.cuda.getCudaEnabledDeviceCount():
        print("CUDA is not available. Please make sure CUDA drivers are installed.")
        return

    gpu_id = 0
    device = cv2.cuda.Device(gpu_id)
    ctx = device.createContext()

    cap = cv2.VideoCapture(video_path)

    cap.set(cv2.CAP_PROP_CUDA_MPS, 1)

    while True:
        ret, frame = cap.read(cv2.CAP_CUDA)

        if not ret:
            break

        # 在这里进行你希望执行的操作
        # ...

    cap.release()


# 视频文件路径
video_path = "path/to/video/file.mp4"

print('cpu执行时间:')
% timeit read_video_cpu(video_path)
print('gpu执行时间:')
% timeit read_video_gpu(video_path)

使用GPU读取视频的原理是将视频解码和帧处理操作从CPU转移到GPU上进行加速。在这种情况下,GPU负责解码视频帧并执行任何与帧相关的处理操作,而CPU主要负责控制和协调工作流程。

具体实现方式是,通过OpenCV的cv2.VideoCapture函数设置参数cv2.CAP_CUDA来启用GPU加速。这将使用GPU进行视频解码,并将解码后的帧传输到GPU内存中。然后,在每一帧上进行处理时,GPU负责执行相应的操作,例如图像处理、计算等。CPU则不直接参与这些操作,而是仅在必要时与GPU进行通信和同步,以确保正确的工作流程和数据传输。

需要注意的是,虽然视频的解码和帧处理操作是由GPU完成的,但仍然需要CPU的参与来完成初始化、设置参数、控制流程以及与GPU的通信和同步。因此,在整个过程中,CPU和GPU是协同工作的。在Linux系统中使用top命令查看CPU利用率时,如果视频读取和处理操作主要由GPU执行,那么CPU利用率可能会较低

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/670907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringMvc拦截器入门

文章目录 前言五、拦截器入门1.拦截器简介2.拦截器入门案例3.拦截器参数4. 拦截器链配置 总结 前言 为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者…

管理Linux目录、用户、组以及文档的权限和归属

文章目录 一、管理Linux目录和文件1、查看及切换目录pwd:查看当前工作目录cd:切换工作目录ls:列出文档及属性alias:别名cat查看文件内容less分页显示长文件 2.新建目录/文件mkdir 创建目录touch创建文件 3.删除/移动/复制rm删除mv…

ai描述生成器绘画有哪些?ai绘画生成器描述介绍

从前,有一个名叫小华的画家,他是一位非常出色的艺术家,但是他总是感到自己还没有达到他理想中作品的水平。他一直在寻找一种方法来创造出高质量的艺术品。有一天,他听说了一种神奇的技术,可以让计算机通过人工智能生成…

MySQL全备+binlog恢复方法之伪装master

利用mysql全备 binlog server恢复方法之伪装master 单实例试验 一、试验环境 10.72.7.40 实例 mysql3306为要恢复的对象,mysql3306的全备binlog server(目录/data/mysql/mysql3306/backup) 实例mysql3307为伪装master 实例mysql3308为伪…

黑马程序员前端 Vue3 小兔鲜电商项目——(四)Home 页面布局

文章目录 Home 页面组件结构组件结构拆分Home 模块中引入组件 分类实现模板代码渲染数据 banner 轮播图实现模板代码封装接口渲染数据 面板组件封装创建公共组件复用抽取主题和副主题 新鲜好物实现模版代码封装接口渲染数据 人气推荐实现模板代码封装接口渲染数据 懒加载指令实…

Java实现加密(五)Base64编码

目录 一、Base64是怎么诞生的二、Base64定义三、Base64原理1.ASCII码转Base64(字节数 % 3 0)2.ASCII码转Base64(字节数 % 3 2)3.ASCII码转Base64(字节数 % 3 1)4.UTF-8转Base64 四、Java实现Base64编解码…

Android Binder通信原理(一):简介

源码基于:Android R 0. 前言 在Linux 系统中现有的进程间通信(IPC)方式: 管道(PIPE):在创建时分配一个page大小的内存,缓存区大小比较有限;命名管道(FIFO):考虑 PIPE_BUF 和原子操…

华为流程体系:IPD流程之敏捷开发(限制版)

目录 前言 敏捷 逐步采用敏捷原则 专栏列表 CSDN学院课程地址 前言 今天继续来谈谈 IPD 体系中敏捷开发所涉及的一些相关内容。 无论是硬件产品的开发过程,还是在应用或者是学习 IPD 的过程中。 瀑布式流程几乎都是标配。 这其实跟硬件产品或者是传统 IPD …

ROS:配置VScode

目录 前言一、下载二、vscode 安装三、vscode 集成 ROS 插件四、vscode 使用4.1 创建 ROS 工作空间4.2启动 vscode4.3vscode 中编译 ros4.4创建 ROS 功能包4.5C 实现4.6python 实现4.7配置 CMakeLists.txt4.8编译4.9执行 前言 VSCode 全称 Visual Studio Code,是微…

关于华为云服务器安装宝塔面板后,点击终端无响应解决方案

问题再现: 下面是我沟通宝塔客服后,给的解决方案。 我在百般无奈的情况下、卸载了宝塔后,最终躺平,选择了问宝塔官方客服 1、从华为提供的远程登录方式选一种 二、输入服务器密码通过ssh远程登录 服务器 二、执行宝塔官方提供的 命令执…

电影《闪电侠》观后感

上周看了电影《闪电侠》,主要是闪电侠这个人成长过程,与以往英雄题材类还是有些不太一样的,像之前蜘蛛侠和钢铁侠,都是讲主人公怎么成为那个英雄的,而本部电影是一个类似倒叙,他自己本身就已经是闪电侠了&a…

zookeeper安装使用及工作原理分析

1. Zookeeper概念简介 Zookeeper是一个分布式协调服务;就是为用户的分布式应用程序提供协调服务,它是集群的管理者,监视着集群中各个节点的状态,根据节点提交的反馈进行下一步合理操作。 具体介绍: A、zookeeper是为…

Electron详解(二):基本使用与项目打包

一、electron的基本使用 创建一个 electron 项目 在使用Electron进行开发之前,您需要安装 Node.js,最低工作版本为 14.x,低于 14 的版本在后面的打包过程中可能会报错。 (注意,因为 Electron 将 Node.js 嵌入到其二…

嵌入式系统与大数据:选择哪个方向更好?

嵌入式系统和大数据是两个不同的领域,各有其独特的优势和发展前景。选择嵌入式系统还是大数据方向,应根据个人兴趣、技能背景以及市场需求进行综合评估。 嵌入式系统方向的优势:我资料有嵌入式、plc、单片机资料需要得可以私我 物联网&#…

在 ZBrush 中雕刻漫画风格的蝙蝠侠半身像

今天瑞云渲染小编给大家带来Rishikesh Nandlaskar分享蝙蝠侠造型背后的制作过程,解释了 ZBrush 和 Substance 3D Painter 中的工作流程,并分享了 Arnold 中的渲染设置。 介绍 我叫 Rishikesh Nandlaskar,是伦敦 Framestore VFX 工作室的高级…

使用数据泵+ogg同步oracle数据

本次迁移背景: 机房要搬迁,新搭建了一套oracle数据库,计划不停机迁移,将源端旧库的数据迁移到目标端新库里。 原本想用RMAN方式迁移,但是由于旧库是AIX系统,新库是linux系统,用RMAN迁移会有问…

SpringBoot2.3集成Spring Security(二) JWT认证

项目背景 紧接上文,我们已经完成了 SpringBoot中集成Spring Security,并且用户名帐号和密码都是从数据库中获取。但是这种方式还是不能满足现在的开发需求。 使用JWT的好处: 无状态认证:JWT本身包含了认证信息和声明&#xff0…

仓库管理软件哪个好?一键解决仓库出入库、管理库存,选这些软件

仓库管理软件哪个好? 仓库管理企业进销存的重要组成部分之一,现代物流中不可缺少的重要环节,对于企业管理的重要性不言而喻。 到底该如何选择仓库管理软件?让进销存老研究员帮你搞定 选择一个好的软件,首先明白他的作用。 向你…

【操作系统】生产者消费者问题实现

目录 实验原理: 实验内容: 实验器材(设备、元器件): 实验步骤: 实验数据及结果分析: 实验原理: 考虑n个缓冲区的缓冲池作为一个共享资源,当生产者进程从数据源—文…