CUDA小白 - NPP(8) 图像处理 Morphological Operations
cuda小白
原始API链接 NPP
GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》
常见的NppStatus,可以看这里。
7 是图像的傅里叶变换,还在学习中
本文主要讲述的是形态学变换
Dilation
膨胀操作(对二值化物体边界点进行扩充,将与物体接触的所有背景点合并到该物体中,使边界向外部扩张。如果两个物体间隔较近,会将两物体连通在一起。)
// 返回mask下的最大像素值作为输出的pixel,如果mask的值为0,则不参与最大值查询
NppStatus nppiDilate_8u_C3R(const Npp8u *pSrc,Npp32s nSrcStep,Npp8u *pDst,Npp32s nDstStep,NppiSize oSizeROI,const Npp8u *pMask,NppiSize oMaskSize,NppiPoint oAnchor);
// 与前一个接口的区别是多了一个borderType的类型指定
/*
NppiBorderType {NPP_BORDER_UNDEFINED,NPP_BORDER_NONE,NPP_BORDER_CONSTANT,NPP_BORDER_REPLICATE,NPP_BORDER_WARP,NPP_BORDER_MIRROR
};
*/
NppStatus nppiDilateBorder_8u_C3R(const Npp8u *pSrc,Npp32s nSrcStep,NppiSize oSrcSize,NppiPoint oSrcOffset,Npp8u *pDst,Npp32s nDstStep,NppiSize oSizeROI,const Npp8u *pMask,NppiSize oMaskSize,NppiPoint oAnchor,NppiBorderType eBorderType);
// 特定大小的kernel
NppStatus nppiDilate3x3_8u_C3R(const Npp8u *pSrc,Npp32s nSrcStep,Npp8u *pDst,Npp32s 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 = "../";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 ===============// inputuint8_t *in_image;cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);// outputuint8_t *out_ptr1, *out_ptr2;cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t)); // 三通道cudaMalloc((void**)&out_ptr2, image_size * 3 * sizeof(uint8_t)); // 三通道NppiSize in_size;in_size.width = image_width;in_size.height = image_height;NppiRect rc;rc.x = 0;rc.y = 0;rc.width = image_width;rc.height = image_height;int mask_size = 10;cv::Mat mat_mask = cv::Mat::ones(mask_size, mask_size, CV_8UC1);uint8_t *mask;cudaMalloc((void**)&mask, mask_size * mask_size * sizeof(uint8_t));cudaMemcpy(mask, mat_mask.data, mask_size * mask_size * sizeof(uint8_t), cudaMemcpyHostToDevice);cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);NppStatus status;NppiSize npp_mask_size;npp_mask_size.width = mask_size;npp_mask_size.height = mask_size;NppiPoint pt;pt.x = 0;pt.y = 0;// =============== nppiDilate_8u_C3R ===============status = nppiDilate_8u_C3R(in_image, image_width * 3, out_ptr1, image_width * 3, in_size, mask, npp_mask_size, pt);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiDilate_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "dilate.jpg", out_image);// =============== nppiDilateBorder_8u_C3R ===============NppiPoint src_pt;src_pt.x = 100;src_pt.y = 100;status = nppiDilateBorder_8u_C3R(in_image, image_width * 3, in_size, src_pt, out_ptr2, image_width * 3, in_size, mask, npp_mask_size, pt, NPP_BORDER_REPLICATE);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiDilateBorder_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "dilate_border.jpg", out_image);// freeCUDA_FREE(in_image)CUDA_FREE(out_ptr1)CUDA_FREE(out_ptr2)
}
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

注意:
- nppiDilateBorder_8u_C3R 仅支持border的模式为 NPP_BORDER_REPLICATE,其他模式会报错,错误码为-9999。
Erode
腐蚀操作
NppStatus nppiErode_8u_C3R(const Npp8u *pSrc,Npp32s nSrcStep,Npp8u *pDst,Npp32s nDstStep,NppiSize oSizeROI,const Npp8u *pMask,NppiSize oMaskSize,NppiPoint oAnchor);
NppStatus nppiErodeBorder_8u_C3R(const Npp8u *pSrc,Npp32s nSrcStep,NppiSize oSrcSize,NppiPoint oSrcOffset,Npp8u *pDst,Npp32s nDstStep,NppiSize oSizeROI,const Npp8u *pMask,NppiSize oMaskSize,NppiPoint oAnchor,NppiBorderType eBorderType);
// 固定大小的Erode
NppStatus nppiErode3x3_8u_C3R(const Npp8u *pSrc,Npp32s nSrcStep,Npp8u *pDst,Npp32s nDstStep,NppiSize oSizeROI);
// nppiErode3x3Border_8u_C3R 不详细介绍了
再此使用上一个实验膨胀之后的图像作为腐蚀的输入。
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 = "../";cv::Mat image_dog = cv::imread(directory + "dilate.jpg");int image_width = image_dog.cols;int image_height = image_dog.rows;int image_size = image_width * image_height;// =============== device memory ===============// inputuint8_t *in_image;cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);// outputuint8_t *out_ptr1, *out_ptr2;cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t)); // 三通道cudaMalloc((void**)&out_ptr2, image_size * 3 * sizeof(uint8_t)); // 三通道NppiSize in_size;in_size.width = image_width;in_size.height = image_height;NppiRect rc;rc.x = 0;rc.y = 0;rc.width = image_width;rc.height = image_height;int mask_size = 10;cv::Mat mat_mask = cv::Mat::ones(mask_size, mask_size, CV_8UC1);uint8_t *mask;cudaMalloc((void**)&mask, mask_size * mask_size * sizeof(uint8_t));cudaMemcpy(mask, mat_mask.data, mask_size * mask_size * sizeof(uint8_t), cudaMemcpyHostToDevice);cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);NppStatus status;NppiSize npp_mask_size;npp_mask_size.width = mask_size;npp_mask_size.height = mask_size;NppiPoint pt;pt.x = 0;pt.y = 0;// =============== nppiErode_8u_C3R ===============status = nppiErode_8u_C3R(in_image, image_width * 3, out_ptr1, image_width * 3, in_size, mask, npp_mask_size, pt);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiErode_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "erode.jpg", out_image);// =============== nppiErodeBorder_8u_C3R ===============NppiPoint src_pt;src_pt.x = 100;src_pt.y = 100;status = nppiErodeBorder_8u_C3R(in_image, image_width * 3, in_size, src_pt, out_ptr2, image_width * 3, in_size, mask, npp_mask_size, pt, NPP_BORDER_REPLICATE);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiErodeBorder_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyDeviceToHost);cv::imwrite(directory + "erode_border.jpg", out_image);// freeCUDA_FREE(in_image)CUDA_FREE(out_ptr1)CUDA_FREE(out_ptr2)
}
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

注意点:
- nppiErodeBorder_8u_C3R 仅支持border的模式为 NPP_BORDER_REPLICATE,其他模式会报错,错误码为-9999。
ComplexImageMorphology
复杂图像形态学,暂时不做介绍,后续视情况而定
<<<链接>>>
相关文章:
CUDA小白 - NPP(8) 图像处理 Morphological Operations
cuda小白 原始API链接 NPP GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus…...
java获取音频,文本准转语音时长
jar 以上传到资源中 <dependency><groupId>it.sauronsoftware</groupId><artifactId>jave</artifactId><version>1.0.2</version></dependency> mvn install:install-file -DfileD:\xxx\xxx\jave-1.0.2.jar -DgroupIdit.sauro…...
基于串口通讯的多电机控制技术研究
基于STM32CubeMX生成keil工程 基于proteus 8.7版本进行程序验证 采用了简单的串口通讯协议 基本效果如图 先对电机旋转方向进行指令设置 :221 :320 分别实现对第二个电机正转、第三个电机反转设置 为了方便观测,程序对接受到的串口数据会进行回显。 然后使能电…...
【深入解读Redis系列】(五)Redis中String的认知误区,详解String数据类型
有时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,请认准https://blog.zysicyj.top 首发博客地址 系列文章地址 需求描述 现在假设有这样一个需求,我们要开发一个图像存储系统。要求如下: 该系统能快…...
段指导-示例
RDBMS 19.20 参考文档: Database Administrator’s Guide 19 Managing Space for Schema Objects 19.3.2.4 Running the Segment Advisor Manually 针对表SOE.CUSTOMERS进行段指导 -- 创建段指导 variable id number; begindeclarename varchar2(100);descr …...
LeetCode 面试题 04.02. 最小高度树
文章目录 一、题目二、C# 题解 一、题目 给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树。 点击此处跳转题目。 示例: 给定有序数组: [-10,-3,0,5,9], 一个可能的答案是:[0,-3,9,-10…...
华为云云耀云服务器L实例评测|初始化centos镜像到安装nginx部署前端vue、react项目
文章目录 ⭐前言⭐购买服务器💖 选择centos镜像 ⭐在控制台初始化centos镜像💖配置登录密码 ⭐在webstorm ssh连接 服务器⭐安装nginx💖 wget 下载nginx💖 解压运行 ⭐添加安全组⭐nginx 配置⭐部署vue💖 使用默认的ng…...
python项目制作docker镜像,加装引用模块,部署运行!
一、创建Dockerfile # 基于python:3.10.4版本创建容器 FROM python:3.10.4 # 在容器中创建工作目录 RUN mkdir /app # 将当前Dockerfile目录下的所有文件夹和文件拷贝到容器/app目录下 COPY . /app# 由于python程序用到了requests模块和yaml模块, # python:3.10.4基…...
Redis缓存设计与性能优化
多级缓存架构 缓存设计 缓存穿透 缓存穿透是指查询一个根本不存在的数据, 缓存层和存储层都不会命中, 通常出于容错的考虑, 如果从存储层查不到数据则不写入缓存层。缓存穿透将导致不存在的数据每次请求都要到存储层去查询, 失去…...
免杀对抗-Python-混淆算法+反序列化-打包生成器-Pyinstall
Python-MSF/CS生成shellcode-上线 cs上线 1.生成shellcode-c或者python 2.打开pycharm工具,创建一个py文件,将原生态执行代码复制进去 shellcode执行代码: import ctypesfrom django.contrib.gis import ptr#cs#shellcodebytearray(b"生…...
C#__线程池的简单介绍和使用
/*线程池原理:(有备无患的默认备用后台线程)特点:线程提前建好在线程池;只能用于运行时间较短的线程。*/class Program{static void Main(string[] args){for (int i 0; i < 10; i){ThreadPool.QueueUserWorkItem(Download); …...
安全员(岗位职责)
一、 安全员 是工程项目安全生产、文明施工的直接管理者和责任人,在业务上向 公司 负责; 二、贯彻安全条例和文明施工标准是安全员 工作 准则,执行相关规章、规程是安全员的责任; 三、办理开工前安全监审和安全开工审批,编制项目工程安全监督计划,上报安全措施和分项工程安全施…...
unity 使用声网(Agora)实现语音通话
第一步、先申请一个声网账号 [Agora官网链接](https://console.shengwang.cn/) 第二步在官网创建项目 ,选择无证书模式,证书模式需要tokenh和Appld才能通话 第三步 官网下载SDK 然后导入到unity,也可以直接在unity商店…...
vue2.X 中使用 echarts5.4.0实现项目进度甘特图
vue2.X 中使用 echarts5.4.0实现项目进度甘特图 效果图: 左侧都是名称,上面是时间,当中的内容是日志内容 组件: gantt.vue <template><div id"main" style"width: 100%; height: 100%"></…...
《PostgreSQL与NoSQL:合作与竞争的关系》
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🐅🐾猫头虎建议程序员必备技术栈一览表📖: 🛠️ 全栈技术 Full Stack: 📚…...
【FAQ】视频监控管理平台/视频汇聚平台EasyCVR安全检查相关问题及解决方法3.0
智能视频监控系统/视频云存储/集中存储/视频汇聚平台EasyCVR具备视频融合汇聚能力,作为安防视频监控综合管理平台,它支持多协议接入、多格式视频流分发,视频监控综合管理平台EasyCVR支持海量视频汇聚管理,可应用在多样化的场景上&…...
Java 8 新特性解读及应用实践
Java 8 新特性解读及应用实践 一、简介二、Lambda表达式三、流式编程四、日期/时间API1. 概述2. LocalDate、LocalTime、LocalDateTime等类的使用3. 格式化与解析 五、重复注解和类型注解1. 概念与作用2. 重复注解实例3. 类型注解实例 六、小结回顾 一、简介 Java 8带来了众多…...
C++项目实战——基于多设计模式下的同步异步日志系统-④-日志系统框架设计
文章目录 专栏导读模块划分日志等级模块日志消息模块日志消息格式化模块日志消息落地模块日志器模块日志器管理模块异步线程模块 模块关系图 专栏导读 🌸作者简介:花想云 ,在读本科生一枚,C/C领域新星创作者,新星计划导…...
计算机专业毕业设计项目推荐02-个人医疗系统(Java+原生Js+Mysql)
个人医疗系统(Java原生JsMysql) **介绍****系统总体开发情况-功能模块****各部分模块实现** 介绍 本系列(后期可能博主会统一为专栏)博文献给即将毕业的计算机专业同学们,因为博主自身本科和硕士也是科班出生,所以也比较了解计算机专业的毕业设计流程以…...
Nginx__高级进阶篇之LNMP动态网站环境部署
动态网站和LNMP(LinuxNginxMySQLPHP)都是用于建立和运行 web 应用程序的技术。 动态网站是通过服务器端脚本语言(如 PHP、Python、Ruby等)动态生成网页内容的网站。通过这种方式,动态网站可以根据用户的不同请求生成不…...
告别编译踩坑:详解GMP交叉编译中DESTDIR和.la文件的那些‘坑’与正确用法
告别编译踩坑:详解GMP交叉编译中DESTDIR和.la文件的那些‘坑’与正确用法 交叉编译是嵌入式开发和跨平台构建中的常见需求,但其中隐藏的陷阱往往让开发者头疼不已。特别是像GMP这样的基础数学库,一旦编译或部署环节出现问题,可能导…...
MRM-MOT4X3.6CAN电机驱动库:工业级CAN总线电机控制抽象层
1. 项目概述mrm-mot4x3.6can是一款面向工业级电机控制场景的专用 CAN 总线驱动库,专为 MRMS(Modular Robotic Motor Systems)公司推出的MRM-MOT4X3.6CAN 四通道直流电机控制器设计。该控制器集成 4 路独立 H 桥驱动单元,每路持续输…...
SystemVerilog内存操作实战:手把手教你实现AXI VIP中的backdoor读写
SystemVerilog内存操作实战:AXI VIP中的backdoor读写技术解析 在硬件验证领域,AXI总线协议因其高性能和灵活性已成为行业标准。验证工程师经常需要与AXI VIP(Verification IP)交互,其中内存操作是最基础也最关键的环节…...
日志分散难管理?用Visual Syslog Server实现企业级日志集中监控的5个实战方案
日志分散难管理?用Visual Syslog Server实现企业级日志集中监控的5个实战方案 【免费下载链接】visualsyslog Syslog Server for Windows with a graphical user interface 项目地址: https://gitcode.com/gh_mirrors/vi/visualsyslog 痛点诊断:日…...
Uvicorn与Couchbase Analytics Service集成:构建高性能数据分析API的终极指南
Uvicorn与Couchbase Analytics Service集成:构建高性能数据分析API的终极指南 【免费下载链接】uvicorn An ASGI web server, for Python. 🦄 项目地址: https://gitcode.com/GitHub_Trending/uv/uvicorn 在现代数据驱动的应用开发中,…...
Flowable 7.x 实战:手把手教你从数据库里捞出BPMN2.0 XML并优雅展示(Vue3 + Spring Boot)
Flowable 7.x 实战:从数据库提取BPMN2.0 XML的工程化实现(Vue3 Spring Boot全链路解析) 在流程引擎的实际应用中,BPMN2.0 XML作为流程定义的标准化载体,其可视化展示能力直接影响开发调试效率。本文将完整演示如何构建…...
Qwen3.5-4B-Claude-Opus部署教程:supervisor托管+健康检查全流程详解
Qwen3.5-4B-Claude-Opus部署教程:supervisor托管健康检查全流程详解 1. 模型介绍 Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF 是一个基于 Qwen3.5-4B 的推理蒸馏模型,重点强化了结构化分析、分步骤回答、代码与逻辑类问题的处理能力。该版本…...
从零开始手搓一个xv6内核页表:跟着MIT 6.S081源码一步步理解虚拟内存初始化
从零构建xv6内核页表:深入解析RISC-V虚拟内存初始化实战 在MIT 6.S081操作系统的学习过程中,xv6作为教学用精简内核,其虚拟内存实现是理解现代计算机内存管理的关键。本文将带您从第一行代码开始,完整复现xv6内核页表的构建过程&…...
【AI重塑科研】无需通读全文,三步教你用大模型高效产出文献综述
1. 为什么你需要AI辅助文献综述? 每次打开文献库看到上百篇待读论文就头皮发麻?我完全理解这种感受。去年准备开题报告时,导师要求我两周内完成50篇核心文献的综述,当时差点崩溃。直到我发现用大模型处理文献可以节省90%的时间&am…...
3KW无线充电系统设计:开环控制与闭环控制的MATLAB Simulink仿真模型,采用双边L...
3KW无线充电系统设计(MATLAB simulink仿真模型) 控制方式:开环控制闭环控制 拓扑结构:双边LCC拓扑结构 输入电压:750V 输出电压:400V 传输功率:3KW 最近在折腾一个3KW无线充电系统的仿真项目&am…...
