CUDA小白 - NPP(4) 图像处理 Data Exchange and Initialization(1)

cuda小白
原始API链接 NPP

GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》

常见的NppStatus,可以看这里。

如有问题,请指出,谢谢

Image Set Operations

当前模块主要功能是set图像中的像素值,主要分为三个大类:将ROI区域内的所有像素设置为一个特殊的值(Set),mask赋值(Masked Set),以及单通道赋值(Channel Set)。
三个大类分别以一个三通道的uint8_t为例子简单介绍一下。

// ROI区域内的三通道设置为aValue
NppStatus nppiSet_8u_C3R(const Npp8u aValue[3],Npp8u *pDst,int nDstStep,NppiSize oSizeROI);
// 通过mask控制ROI区域内的那些像素会被set
NppStatus nppiSet_8u_C3MR(const Npp8u aValue[3],Npp8u *pDst,int nDstStep,NppiSize oSizeROI,const Npp8u *pMask,int nMaskStep);	
// 通过pointer的起始位置区别,选择某通道设置为固定值
NppStatus nppiSet_8u_C3CR(Npp8u nValue,Npp8u *pDst,int nDstStep,NppiSize oSizeROI);
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }int main() {std::string directory = "../";// =============== load image ===============cv::Mat image_dog = cv::imread(directory + "dog.png");int image_width = image_dog.cols;int image_height = image_dog.rows;int image_size = image_width * image_height;// =============== device memory ===============uint8_t *out_ptr1, *out_ptr2, *out_ptr3;cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t));cudaMalloc((void**)&out_ptr2, image_size * 3 * sizeof(uint8_t));cudaMalloc((void**)&out_ptr3, image_size * 3 * sizeof(uint8_t));cudaMemcpy(out_ptr1, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);cudaMemcpy(out_ptr2, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);cudaMemcpy(out_ptr3, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);cv::Mat mask = cv::Mat::zeros(image_height, image_width, CV_8UC1);cv::Mat mask1 = cv::Mat::ones(image_height * 3 / 4, image_width * 3 / 4, CV_8UC1);cv::Rect rc1 = cv::Rect(image_width / 4, image_height / 4, image_width * 3 / 4, image_height * 3 / 4);mask1.copyTo(mask(rc1));uint8_t *gpu_mask;cudaMalloc((void**)&gpu_mask, image_size * sizeof(uint8_t));cudaMemcpy(gpu_mask, mask.data, image_size * sizeof(uint8_t), cudaMemcpyHostToDevice);NppiSize roi1, roi2;roi1.width = image_width;roi1.height = image_height;roi2.width = image_width / 2;roi2.height = image_height / 2;cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);NppStatus status;// =============== nppiSet_8u_C3R ===============uint8_t value[3] = { 255, 0, 0 };status = nppiSet_8u_C3R(value, out_ptr1, image_width * 3, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiSet_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "set.jpg", out_image);// =============== nppiSet_8u_C3R ===============uint8_t value2[3] = { 0, 0, 255 };status = nppiSet_8u_C3MR(value2, out_ptr2, image_width * 3, roi1, gpu_mask, image_width);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiSet_8u_C3MR failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyD![请添加图片描述](https://img-blog.csdnimg.cn/9da721ce7d4649839ef40228bb3937e1.png)
eviceToHost);cv::imwrite(directory + "set_mask.jpg", out_image);// greenstatus = nppiSet_8u_C3CR(255, out_ptr3 + image_width * 3 * 200 + 1, image_width * 3, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiSet_8u_C3CR failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr3, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "set_channel.jpg", out_image);// freeCUDA_FREE(out_ptr1)CUDA_FREE(out_ptr2)CUDA_FREE(out_ptr3)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")add_executable(test test.cpp)
target_link_libraries(test${OpenCV_LIBS}${CUDA_LIBS}
)
result

请添加图片描述
注意:

  1. mask使用的是单通道的,仅表示那些像素需要进行set,那些不需要
  2. 通道的set,通过指针来表示是针对那个通道进行转换。输入指针表示开始set的起始位置,对于三通道的图像而言,则是隔两个set一次。

Image Copy Operations

除了比较常见的copy操作(copy,masked copy,channel copy)之外,还有一些planar和packed之间的来回拷贝,拷贝的同时伴随着border,以及Copy Sub-pixel(没接触过)

// 单纯的拷贝
NppStatus nppiCopy_8u_C3R(const Npp8u *pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI);	
// 依据mask有选择性的进行拷贝
NppStatus nppiCopy_8u_C3MR(const Npp8u *pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI,const Npp8u *pMask,int nMaskStep);	
// Channel Copy, 将一个多通道的某个通道拷贝到另外一个多通道图像的某一个channel
NppStatus nppiCopy_8u_C3CR(const Npp8u *pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI);	
// Extract Channel Copy, 将一个多通道的某个通道拷贝到另外一个单通道的图像
NppStatus nppiCopy_8u_C3C1R(const Npp8u * pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI);	
// Insert Channel Copy, 一个单通道的图像拷贝到多通道中的某一个通道
NppStatus nppiCopy_8u_C1C3R(const Npp8u * pSrc,int nSrcStep,Npp8u * pDst,int nDstStep,NppiSize oSizeROI);
// 剩下的接口平时接触较少,所以暂时不做详细介绍
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }int main() {std::string directory = "../";// =============== load image ===============cv::Mat image_dog = cv::imread(directory + "dog.png");cv::Mat image_dog_gray;cv::cvtColor(image_dog, image_dog_gray, CV_RGB2GRAY);int image_width = image_dog.cols;int image_height = image_dog.rows;int image_size = image_width * image_height;// =============== device memory ===============uint8_t *in_image, *in_img_gray;cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));cudaMalloc((void**)&in_img_gray, image_size * sizeof(uint8_t));cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);cudaMemcpy(in_img_gray, image_dog_gray.data, image_size * sizeof(uint8_t), cudaMemcpyHostToDevice);uint8_t *out_ptr1, *out_ptr2, *out_ptr3, *out_ptr4, *out_ptr5;cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t));  // 三通道cudaMalloc((void**)&out_ptr2, image_size * 3 * sizeof(uint8_t));  // 三通道cudaMalloc((void**)&out_ptr3, image_size * 3 * sizeof(uint8_t));  // 三通道cudaMalloc((void**)&out_ptr4, image_size * sizeof(uint8_t));  // 单通道cudaMalloc((void**)&out_ptr5, image_size * 3 * sizeof(uint8_t));  // 三通道// maskcv::Mat mask = cv::Mat::zeros(image_height, image_width, CV_8UC1);cv::Mat mask1 = cv::Mat::ones(image_height * 3 / 4, image_width * 3 / 4, CV_8UC1);cv::Rect rc1 = cv::Rect(image_width / 4, image_height / 4, image_width * 3 / 4, image_height * 3 / 4);mask1.copyTo(mask(rc1));uint8_t *gpu_mask;cudaMalloc((void**)&gpu_mask, image_size * sizeof(uint8_t));cudaMemcpy(gpu_mask, mask.data, image_size * sizeof(uint8_t), cudaMemcpyHostToDevice);NppiSize roi1, roi2;roi1.width = image_width;roi1.height = image_height;roi2.width = image_width / 2;roi2.height = image_height / 2;cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);cv::Mat out_single = cv::Mat::zeros(image_height, image_width, CV_8UC1);NppStatus status;// =============== nppiCopy_8u_C3R ===============status = nppiCopy_8u_C3R(in_image, image_width * 3, out_ptr1, image_width * 3, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiCopy_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "copy.jpg", out_image);// =============== nppiCopy_8u_C3MR ===============status = nppiCopy_8u_C3MR(in_image, image_width * 3, out_ptr2, image_width * 3, roi1, gpu_mask, image_width);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiCopy_8u_C3MR failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "copy_mask.jpg", out_image);// =============== nppiCopy_8u_C3CR ===============status = nppiCopy_8u_C3CR(in_image, image_width * 3, out_ptr3, image_width * 3, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiCopy_8u_C3CR failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr3, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "copy_channel.jpg", out_image);// =============== nppiCopy_8u_C3C1R ===============status = nppiCopy_8u_C3C1R(in_image, image_width * 3, out_ptr4, image_width, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiCopy_8u_C3C1R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_single.data, out_ptr4, image_size, cudaMemcpyDeviceToHost);cv::imwrite(directory + "copy_channel_extract.jpg", out_single);// =============== nppiCopy_8u_C1C3R ===============status = nppiCopy_8u_C1C3R(in_img_gray, image_width, out_ptr5, image_width * 3, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiCopy_8u_C1C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr5, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "copy_channel_insert.jpg", out_image);// freeCUDA_FREE(in_image)CUDA_FREE(in_img_gray)CUDA_FREE(out_ptr1)CUDA_FREE(out_ptr2)CUDA_FREE(out_ptr3)CUDA_FREE(out_ptr4)CUDA_FREE(out_ptr5)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")add_executable(test test.cpp)
target_link_libraries(test${OpenCV_LIBS}${CUDA_LIBS}
)
result

请添加图片描述
注意:

  1. 由于提取三个通道进行copy,存图的时候只有单个通道,因此呈现出来的结果是灰色的。

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

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

相关文章

二叉树(上)

“路虽远&#xff0c;行则将至” ❤️主页&#xff1a;小赛毛 目录 1.树概念及结构 1.1树的概念 1.2 树的相关概念 1.3 树的表示&#xff08;树的存储&#xff09; 2.二叉树概念及结构 2.1概念 2.2现实中的二叉树 2.3 特殊的二叉树&#xff1a; 2.4 二叉树的性质 3.二叉树的顺…

java 整合 swagger-ui 步骤

1.在xml 中添加Swagger 相关依赖 <!-- springfox-swagger2 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><!-- springfox-swa…

【Python从入门到进阶】35、selenium基本语法学习

接上篇《34、selenium基本概念及安装流程》 上一篇我们介绍了selenium技术的基础概念以及安装和调用的流程&#xff0c;本篇我们来学习selenium的基本语法&#xff0c;包括元素定位以及访问元素信息的操作。 一、元素定位 Selenium元素定位是指通过特定的方法在网页中准确定位…

Canape使用中遇到问题的解决办法

问题一、canape绘制目标时&#xff0c;二维结构体变量只能录制16个的解决办法 打开ASAP2 Studio 2.6 -Expert 软件。 把该软件中的设置项如下图进行修改。 然后用ASAP2 Studio 2.6 -Expert 软件 打开elf文件导出成A2L文件。 最后关闭该软件。 再在canape工程中重新加载刚才…

振弦采集仪应用地铁隧道安全监测详细解决方案

振弦采集仪应用地铁隧道安全监测详细解决方案 随着城市化进程的不断加快&#xff0c;地铁作为一种高效、便捷、环保的交通方式已经成为现代城市不可或缺的一部分。因此&#xff0c;对地铁的安全性也越来越重视&#xff0c;一般二三线以上的城市在不断发展中&#xff0c;地铁做…

c语言 2.0

1.数据类型 数据类型介绍 数据类型&#xff1a;c语言中数据类型有3种&#xff0c;分别是基本数据类型、构造数据类型、指针数据类型。 数据类型的作用&#xff1a;编译器预算数据分配的内存空间大小。 ps&#xff1a;可以通俗理解为&#xff1a;数据类型是用来规范内存的开销…

初识docker

目录 docker解决的问题1. 开发、测试和运维人员之间的矛盾2. 更轻量的虚拟化&#xff0c;节省了虚拟机的性能损耗 虚拟机与容器的区别1. 虚拟机2. 容器 Docker 系统架构 docker解决的问题 1. 开发、测试和运维人员之间的矛盾 “程序在我这跑得好好的&#xff0c;在你那怎么就…

C++之红黑树

红黑树 红黑树的概念红黑树的性质红黑树结点的定义红黑树的插入红黑树的验证红黑树与AVL树的比较 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上…

uniapp 在 onLoad 事件中 this.$refs 娶不到的问题

现象 本人想在主页面加载的时候调用子组件的方法。示例代码如下&#xff1a; 运行&#xff0c;发现 this.$refs 取不到。如下图所示&#xff1a; 解决方法&#xff0c;把onLoad 换为 onReady 就可以了。

【Linux】管道

管道命令 #include <unistd.h> int pipe(int pipefd[2]); 在Linux中&#xff0c;管道&#xff08;pipe&#xff09;的返回值是一个整数数组&#xff0c;包含两个文件描述符。这两个文件描述符分别代表管道的读端和写端。 当成功创建一个管道时&#xff0c;pipe() 系统调用…

K8S:kubectl陈述式及声明式资源管理

文章目录 一.陈述式资源管理方法1.陈述式资源管理概念2.基本信息查看&#xff08;1&#xff09;查看版本信息&#xff08;2&#xff09;查看资源对象简写&#xff08;3&#xff09;查看集群信息&#xff08;4&#xff09;配置kubectl自动补全&#xff08;5&#xff09;node节点…

基于Linux并结合socket网络编程的ftp服务器的实现

项目需求 客户端能够通过调用“get”指令&#xff0c;来获取服务器的文件客户端能通过“server_ls”指令&#xff0c;来获取服务器路径下的文件列表客户端能通过“server_cd”指令&#xff0c;进入服务器路径下的某文件夹客户端可以通过“upload”指令&#xff0c;上传自己的本…

Redis发布订阅机制学习

【IT老齐151】Redis发布订阅机制是如何实现的&#xff1f;_哔哩哔哩_bilibili go-redis的发布与订阅 - 知乎 (zhihu.com) 前置&#xff1a; 先输入 redis-server.exe 启动redis&#xff0c;否则对应接口不开放 再输入 redis-cli 命令启动客户端服务 1.机制示意图 当一…

AR产业变革中的“关键先生”和“关键力量”

今年6月的WWDC大会上&#xff0c;苹果发布了头显产品Vision Pro&#xff0c;苹果CEO库克形容它&#xff1a; 开启了空间计算时代。 AR产业曾红极一时&#xff0c;但因为一些技术硬伤又减弱了声量&#xff0c;整个产业在起伏中前行。必须承认&#xff0c;这次苹果发布Vision P…

七大排序算法

目录 直接插入排序 希尔排序 直接选择排序 堆排序 冒泡排序 快速排序 快速排序优化 非递归实现快速排序 归并排序 非递归的归并排序 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作. 常见的排序算法有插入排序(直接插入…

队列(Queue)的顶级理解

目录 1.队列(Queue) 的概念 2.单链表模拟实现队列 2.1创建队列 2.2入队列 2.3判断是否为空 2.4出队列 2.5获取队头元素 2.6完整代码&#xff1a; 2.7双向链表模拟实现队列代码 3.数组模拟实现队列代码 3.1创建队列 3.2判断是否为满 3.3检查是否为空 3.4插入元素 3…

ctfshow 反序列化

PHP反序列化前置知识 序列化和反序列化 对象是不能在字节流中传输的&#xff0c;序列化就是把对象转化为字符串以便存储和传输&#xff0c;反序列化就是将字符串转化为对象 魔术方法 __construct() //构造&#xff0c;当对象new时调用 __wakeup() //执行unserialize()时&am…

mysql 增量备份与恢复使用详解

目录 一、前言 二、数据备份策略 2.1 全备 2.2 增量备份 2.3 差异备份 三、mysql 增量备份概述 3.1 增量备份实现原理 3.1.1 基于日志的增量备份 3.1.2 基于时间戳的增量备份 3.2 增量备份常用实现方式 3.2.1 基于mysqldump增量备份 3.2.2 基于第三方备份工具进行增…

【QT】QMessageBox消息框的使用(16)

在实际项目中&#xff0c;弹出消息框是一个很常见的操作&#xff0c;包含错误信息提示、警告信息提示、关于信息提示、还包括判断信息选择等操作&#xff0c;那么今天通过这一节来好好了解下消息框的使用方法。 一.环境配置 1.python 3.7.8 可直接进入官网下载安装&#xf…

前端基础5——UI框架Layui

文章目录 一、基本使用二、管理后台布局2.1 导航栏2.2 主题颜色2.3 字体图标 三、栅格系统四、卡片面板五、面包屑六、按钮七、表单八、上传文件九、数据表格9.1 table模块常用参数9.2 创建表格9.3 表格分页9.4 表格工具栏9.5 表格查询9.5.1 搜索关键字查询9.5.2 选择框查询 9.…