opencv中使用cuda加速图像处理

news2024/11/28 2:54:33

opencv大多数只使用到了cpu的版本,实际上对于复杂的图像处理过程用cuda(特别是高分辨率的图像)可能会有加速效果。是否需要使用cuda需要思考:

  • 1、opencv的cuda库是否提供了想要的算子。在CUDA-accelerated Computer Vision你可以看到cv的cuda库提供了哪些方法。
  • 2、如果要使用cv的cuda库,会涉及到数据从cpu和gpu之间的交换。一张图片首先会被cpu读取到内存中,然后通过api将cpu中的数据搬运到gpu中,而cpu和gpu之间的数据搬运也是很耗时的,比如gpu_dst.download(dst_cpu)将gpu_dst数据搬运到dst_cpu,数据是8976*4960*3,耗时约37ms,如果你的图像处理比较简单,说不定数据搬运的耗时比直接在cpu上运行更长。

1、带cuda的opencv安装

这里的前提是你的nvidia驱动、cuda以及cudnn都安装完成,可以正常使用。

首先下载版本一致的opencv和opencv-contrib(cuda库所在包),然后解压待用。

然后查询你显卡的Compute Capability,进入opencv-4.8.1后创建build文件夹,终端在build中打开后,执行:

cmake \ 
-D CMAKE_BUILD_TYPE=RELEASE \ 
-D BUILD_CUDA_STUBS=ON \         
-D WITH_CUDA=ON \                   
-D CUDA_ARCH_BIN=8.9 \ 
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.8.1/modules .. 

注意,CUDA_ARCH_BIN是你查询到自己显卡的Compute Capability,OPENCV_EXTRA_MODULES_PATH指向你的opencv_contrib-4.8.1/modules。(最后的..不能省略)
在这里插入图片描述
可以看到成功检测到我的11.8的cuda,但是没有cuDNN。不知道是不是新版的原因,我安装好cudnn后通过命令cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2查询cudnn版本没有任何输出,但是确实存在cudnn.h,并在在使用cuda时也没有问题,就没有(后面在opencv使用cuda也没有报错)。

然后:sudo make –j15,表示使用15个线程make,因cpu而异。
最后sudo make install

后续的操作参考ubuntu20.04+opencv+vscode添加环境变量。

2、测试

编写c++代码测试:

#include <opencv2/opencv.hpp>
#include <opencv2/core/cuda.hpp>

int main()
{
    cv::cuda::printCudaDeviceInfo(cv::cuda::getDevice());

    int count = cv::cuda::getCudaEnabledDeviceCount();

    printf("GPU Device Count : %d \n", count);

    return 0;
}

在这里插入图片描述
如果是不支持cuda的cv,则会报错:error: (-216:No CUDA support) The library is compiled without CUDA support in function 'throw_no_cuda'

3、在gpu上旋转图像

实际上,在gpu上使用cv总体分为三步:1)将内存中的数据搬运到gpu上;2)使用cuda方法进行图像处理;3)将处理结果搬运到cpu上;

下面是一个将图像逆时针旋转90度的代码,其中Timer类是一个计时器,从创建起计时,到离开作用域被销毁时的耗时。对于4960*8976\的图像进行测试,RGB指3通道,Gray指单通道,测量upload、rotate和download三个阶段的耗时:

RGB(ms)Gray(ms)
upload93
rotate43
download3712

可以看到对于简单的操作实际上耗时在数据的上传和下载。

#include <opencv2/opencv.hpp>
#include <opencv2/cudawarping.hpp>
#include "timer.h"

int main(int argc, char *argv[])
{
    if (argc != 2)
    { // 检查是否传入图片路径
        std::cout << "参数错误" << std::endl;
    }

    // 以灰度图模式读取输入图像
    cv::Mat src = cv::imread(argv[1]);
    if (src.empty())
    {
        std::cerr << "Failed to read input image!" << std::endl;
        return -1;
    }

    cv::Mat dst_cpu; // 在cpu创建一个Mat,接受处理后的图像结果

    cv::cuda::GpuMat gpu_src, gpu_dst;   // 在gpu创建两个Mat,分别储存旋转前后的图像(因为旋转前后尺寸不一样,所以必须要两个Mat)
    gpu_dst.create(8976, 4960, CV_8UC3); // 定义旋转后图像尺寸的Mat

    cv::Mat colorImage(8976, 4960, CV_8UC3); // 在cpu创建Mat,一个将灰度图转为RGB图的Mat
    {

        {
            Timer time("upload");
            gpu_src.upload(src); // 将cpu上的src搬运到gpu的gpu_src中
        }
        {
            Timer time("rotate"); // 计时器,从此刻计时直到离开作用域被销毁
                                  // 逆时针旋转90度,将4960*8976转8976*4960,流程是按左上角旋转后,向下平移8976,然后用8976*4960的Mat接受
            cv::cuda::rotate(gpu_src, gpu_dst, gpu_dst.size(), 90, 0, 8976);
        }

        // 将gpu的gpu_dst数据搬运到dst_cpu中(好像只有gpu的数据才有方法)
        {
            Timer time("download");
            gpu_dst.download(dst_cpu); // gpu到cpu搬运数据很耗时,RGB数据耗时37ms,Gray数据耗时12ms
        }
    }
    return 0;
}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
set(CMAKE_BUILD_TYPE Debug)
project(MyProject)

# 添加可执行文件
add_executable(draft draft.cpp src/timer.cpp)

# 设置包含目录
target_include_directories(draft PRIVATE src)

# 查找 OpenCV 库
find_package(OpenCV REQUIRED)

# 将 OpenCV 库链接到可执行文件
target_link_libraries(draft PRIVATE ${OpenCV_LIBS} opencv_cudawarping)

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

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

相关文章

Sklearn、TensorFlow 与 Keras 机器学习实用指南第三版(三)

原文&#xff1a;Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第六章&#xff1a;决策树 决策树是多功能的机器学习算法&#xff0c;可以执行分类和回归任务&#xff0c;甚至多输出任务。它们…

Android BitmapShader setLocalMatrix缩放Bitmap高度重新onMeasure,Kotlin

Android BitmapShader setLocalMatrix缩放Bitmap高度重新onMeasure&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://sc…

Kubernetes基础(十一)-CNI网络插件用法和对比

1 CNI概述 1.1 什么是CNI&#xff1f; Kubernetes 本身并没有实现自己的容器网络&#xff0c;而是借助 CNI 标准&#xff0c;通过插件化的方式来集成各种网络插件&#xff0c;实现集群内部网络相互通信。 CNI&#xff08;Container Network Interface&#xff0c;容器网络的…

JavaScript原型和原型链是什么

JavaScript原型和原型链是Web前端技术中的重要概念&#xff0c;了解它们可以帮助开发者更好地理解JavaScript对象的创建和继承机制。本文将深入探讨JavaScript原型和原型链&#xff0c;并提供相关的示例代码和解析。 首先&#xff0c;让我们了解一下JavaScript中的原型。每个J…

ubuntu 18.04修改网卡名称

1.原来网卡配置 现在要把enp3s0的名称改为eth0 2. 总共修改三个文件 第一个修改 sudo vi /etc/default/grub 添加最后一行 GRUB_CMDLINE_LINUX"net.ifnames0 biosdevname0" 第二个修改sudo vi /etc/udev/rules.d/70-persistent-net.rules 如果没有就新建文件&a…

用通俗易懂的方式讲解:12 个大模型 RAG 痛点及解决方案

受 Barnett 等人的论文《工程检索增强生成系统时的七个失败点》启发&#xff0c;让我们在本文中探讨论文中提到的七个失败点以及开发 RAG 管道时的五个常见痛点。 论文&#xff1a;https://arxiv.org/pdf/2401.05856.pdf 更重要的是&#xff0c;我们将深入探讨这些 RAG 痛点的…

vue基本语法总结大全

vue基本语法 文章目录 vue基本语法基本用法内容渲染指令属性绑定指令使用js表达式事件绑定指令条件渲染指令v-else和v-else-if指令列表渲染指令v-for中的key 组件化开发安装详细讲解 第三方组件1. 组件间的传值2. element-ui介绍3. 组件的使用4. 图标的使用 Axios网络请求1. Ax…

Redis-缓存问题及解决方案

本文已收录于专栏 《中间件合集》 目录 概念说明缓存问题缓存击穿问题描述解决方案 缓存穿透问题描述解决方案 缓存雪崩问题描述解决方案提高缓存可用性过期时间配置熔断降级 总结提升 概念说明 Redis是一个开源的内存数据库&#xff0c;也可以用作缓存系统。它支持多种数据结构…

网络攻防模拟与城市安全演练 | 图扑数字孪生

在数字化浪潮的推动下&#xff0c;网络攻防模拟和城市安全演练成为维护社会稳定的不可或缺的环节。基于数字孪生技术我们能够在虚拟环境中进行高度真实的网络攻防模拟&#xff0c;为安全专业人员提供实战经验&#xff0c;从而提升应对网络威胁的能力。同时&#xff0c;在城市安…

UE中对象创建方法示例和类的理解

对象创建方法示例集 创建Actor示例 //创建一个护甲道具 AProp* armor GetWorld()->SpawnActor<AProp>(pos, rotator); 创建Component示例 UCapsuleComponent* CapsuleComponent CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleComponent&qu…

【HarmonyOS应用开发】HTTP数据请求(十四)

文章末尾含相关内容源代码 一、概述 日常生活中我们使用应用程序看新闻、发送消息等&#xff0c;都需要连接到互联网&#xff0c;从服务端获取数据。例如&#xff0c;新闻应用可以从新闻服务器中获取最新的热点新闻&#xff0c;从而给用户打造更加丰富、更加实用的体验。 那么…

【Linux网络编程三】Udp套接字编程网络应用场景

【Linux网络编程三】Udp套接字编程网络应用场景 应用场景一&#xff1a;远程命令执行应用场景二&#xff1a;与Windos端相互通信应用场景三&#xff1a;简单聊天1.多线程化2.输入输出分开 应用场景一&#xff1a;远程命令执行 简单的服务器上一篇已经完成&#xff0c;接下来我…

前端小案例——动态导航栏文字(HTML + CSS, 附源码)

一、前言 实现功能: 这案例是一个具有动态效果的导航栏。导航栏的样式设置了一个灰色的背景&#xff0c;并使用flex布局在水平方向上平均分配了四个选项。每个选项都是一个li元素&#xff0c;包含一个文本和一个横向的下划线。 当鼠标悬停在选项上时&#xff0c;选项的文本颜色…

flask+pyinstaller实现mock接口,并打包到exe运行使用postman验证

flask代码 from flask import Flask, request, jsonifyapp Flask(__name__)app.route("/login", methods[POST]) def login():username request.json.get("username").strip() # 用户名password request.json.get("password").strip() # 密…

FastAdmin青动CRM-E售后

应用介绍 一款基于FastAdminThinkPHP和uniapp开发的CRM售后管理系统&#xff0c;旨在助力企业销售售后全流程精细化、数字化管理&#xff0c;主要功能&#xff1a;客户、合同、工单、任务、报价、产品、库存、出纳、收费&#xff0c;适用于&#xff1a;服装鞋帽、化妆品、机械机…

随机森林超参数的网格优化(机器学习的精华--调参)

随机森林超参数的网格优化&#xff08;机器学习的精华–调参&#xff09; 随机森林各个参数对算法的影响 影响力参数⭐⭐⭐⭐⭐几乎总是具有巨大影响力n_estimators&#xff08;整体学习能力&#xff09;max_depth&#xff08;粗剪枝&#xff09;max_features&#xff08;随机…

STM32--SPI通信协议(3)SPI通信外设

前言 硬件SPI&#xff1a;通过硬件电路实现&#xff0c;所以硬件SPI速度更快&#xff0c;有专门的寄存器和 库函数 &#xff0c;使用起来更方便。 软件SPI&#xff1a;也称模拟SPI&#xff0c;通过程序控制IO口电平模拟SPI时序实现&#xff0c;需要程序不断控制IO电平翻转&am…

网工每日一练(2月4日)

试题1 通过HFC网络实现宽带接入&#xff0c;用户端需要的设备是&#xff08;A&#xff09;&#xff0c;局端用于控制和管理用户的设备是&#xff08;D&#xff09;。 &#xff08;1&#xff09;A.Cable Modem B.ADSL Modem C.OLT D.CMTS &#xff08;2&#xff09;A. Cable Mo…

代码编辑器1.9.0

多线程&#xff01;&#xff01;&#xff01; #include <winsock2.h> #include <windows.h> #include <iostream> #include <stdlib.h> #include <string.h> #include <fstream> #include <conio.h> #include <stdio.h> #incl…

实现屏蔽 Ctrl + Alt + Del 、Ctrl + Shift + Esc 等热键(二)

目录 前言 一、概述 Winlogon 的 RPC 例程 二、Handler 函数的消息处理机制 三、讨论如何安全执行 HOOK 代码 3.1 挂钩例程解决方案 3.2 脱钩例程解决方案 3.3 钩子例程解决方案 3.4 地址信息查询函数 3.5 简单保护加载的模块 四、模块如何安全地注入&#xff1f; 4…