CUDA小白 - NPP(6) 图像处理 Geometry Transforms (2)

news2025/1/11 22:48:11

cuda小白
原始API链接 NPP

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

常见的NppStatus,可以看这里。

Affine Transform

仿射变换
在这里插入图片描述

// 仿射变换
NppStatus nppiWarpAffine_8u_C3R(const Npp8u *pSrc,
								NppiSize oSrcSize,
								int nSrcStep,
								NppiRect oSrcROI,
								Npp8u *pDst,
								int nDstStep,
								NppiRect oDstROI,
								const double aCoeffs[2][3],
								int eInterpolation);
// 同样的2x3的矩阵的逆仿射变换
NppStatus nppiWarpAffineBack_8u_C3R(const Npp8u *pSrc,
									NppiSize oSrcSize,
									int nSrcStep,
									NppiRect oSrcROI,
									Npp8u *pDst,
									int nDstStep,
									NppiRect oDstROI,
									const double aCoeffs[2][3],
									int eInterpolation);
// 源图像的四边形 仿射变换到 目标的四边形,平时使用较少,后续不进行测试
NppStatus nppiWarpAffineQuad_8u_C3R(const Npp8u *pSrc,
									NppiSize oSrcSize,
									int nSrcStep,
									NppiRect oSrcROI,
									const double aSrcQuad[4][2],
									Npp8u *pDst,
									int nDstStep,
									NppiRect oDstROI,
									const double aDstQuad[4][2],
									int eInterpolation);
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 ===============
  // input
  uint8_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);

  // output
  uint8_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));  // 三通道

  double angle = 30.0;
  double scale = 0.6;
  cv::Point center = cv::Point(image_width / 2, image_height / 2);
  cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, scale);
  double coeffs[2][3] = { rot_mat.at<double>(0, 0),
                          rot_mat.at<double>(0, 1),
                          rot_mat.at<double>(0, 2),
                          rot_mat.at<double>(1, 0),
                          rot_mat.at<double>(1, 1),
                          rot_mat.at<double>(1, 2)};

  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;

  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  // =============== nppiWarpAffine_8u_C3R ===============
  status = nppiWarpAffine_8u_C3R(in_image, in_size, image_width * 3, rc, out_ptr1, image_width * 3, 
                                 rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpAffine_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "affine.jpg", out_image);

   // =============== nppiWarpAffineBack_8u_C3R ===============
  status = nppiWarpAffineBack_8u_C3R(out_ptr1, in_size, image_width * 3, rc, out_ptr2, image_width * 3, 
                                     rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpAffineBack_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "affine_back.jpg", out_image);

  // free
  CUDA_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

请添加图片描述

Perspective Transform

透视变换

NppStatus nppiWarpPerspective_8u_C3R(const Npp8u *pSrc,
									 NppiSize oSrcSize,
									 int nSrcStep,
									 NppiRect oSrcROI,
									 Npp8u *pDst,
									 int nDstStep,
									 NppiRect oDstROI,
									 const double aCoeffs[3][3],
									 int eInterpolation);

NppStatus nppiWarpPerspectiveBack_8u_C3R(const Npp8u *pSrc,
									     NppiSize oSrcSize,
								         int nSrcStep,
										 NppiRect oSrcROI,
										 Npp8u *pDst,
										 int nDstStep,
										 NppiRect oDstROI,
										 const double aCoeffs[3][3],
										 int eInterpolation);
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 ===============
  // input
  uint8_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);

  // output
  uint8_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));  // 三通道

  cv::Point2f src_pts[4], dst_pts[4];
  src_pts[0].x = 0.0;
  src_pts[0].y = 0.0;
  src_pts[1].x = image_width - 1.0;
  src_pts[1].y = 0.0;
  src_pts[2].x = 0.0;
  src_pts[2].y = image_height - 1.0;
  src_pts[3].x = image_width - 1.0;
  src_pts[3].y = image_height - 1.0;

  dst_pts[0].x = image_width * 0.05;
  dst_pts[0].y = image_height * 0.05;
  dst_pts[1].x = image_width * 0.9;
  dst_pts[1].y = image_height * 0.1;
  dst_pts[2].x = image_width * 0.2;
  dst_pts[2].y = image_height * 0.8;
  dst_pts[3].x = image_width * 0.85;
  dst_pts[3].y = image_height * 0.85;

  cv::Mat warp_mat = cv::getPerspectiveTransform(src_pts, dst_pts);
  double coeffs[3][3] = { warp_mat.at<double>(0, 0),
                          warp_mat.at<double>(0, 1),
                          warp_mat.at<double>(0, 2),
                          warp_mat.at<double>(1, 0),
                          warp_mat.at<double>(1, 1),
                          warp_mat.at<double>(1, 2),
                          warp_mat.at<double>(2, 0),
                          warp_mat.at<double>(2, 1),
                          warp_mat.at<double>(2, 2) };
  
  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;

  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  // =============== nppiWarpPerspective_8u_C3R ===============
  status = nppiWarpPerspective_8u_C3R(in_image, in_size, image_width * 3, rc, out_ptr1, image_width * 3, 
                                      rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpPerspective_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "perspective.jpg", out_image);

  // =============== nppiWarpPerspectiveBack_8u_C3R ===============
  status = nppiWarpPerspectiveBack_8u_C3R(out_ptr1, in_size, image_width * 3, rc, out_ptr2, image_width * 3, 
                                          rc, coeffs, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiWarpPerspectiveBack_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr2, image_size * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "perspective_back.jpg", out_image);

  // free
  CUDA_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

请添加图片描述

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

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

相关文章

LeetCode 1282. Group the People Given the Group Size They Belong To【哈希表】1267

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

Python入门学习15(面向对象)

一、多态 多态&#xff0c;指的是&#xff1a;多种状态&#xff0c;即完成某个行为时&#xff0c;使用不同的对象会得到不同的状态。 同样的行为&#xff08;函数&#xff09;&#xff0c;传入不同的对象&#xff0c;得到不同的状态 class Animal:def speak(self):passclass …

NTP8928(20W内置DSP双通道D类功放芯片)

由工采网代理的韩国NF(耐福)NTP8928是一款内置DSP双通道D类音频功放芯片&#xff0c;芯片集成了多功能数字音频信号处理功能&#xff0c;高性能&#xff0c;高保真全数字PWM调制器和两个大功率全桥MOSFET。 该芯片工作电压范围&#xff1a;5V&#xff5e;28V&#xff1b;2通道…

基于antd+vue2来实现一个简单的工作流程图功能

简单流程图的实现&#xff08;基于antdvue2的&#xff09;代码很多哦~ 实现页面如下 1.简单操作如下 2.弹框中使用组件&#xff1a; <vfdref"vfd"style"background-color: white;":needShow"true":fieldNames"fieldNames"openUse…

深入《C++ Core Guidelines解析》:提升C++编程实践的关键指南

目录 1、写在前面2、推荐理由3、内容介绍4、作者介绍5、赠书 or 购买 1、写在前面 C Core Guidelines是一个正在进行的开源项目&#xff0c;通过将广泛认可的现代C上佳实践集中在一个地方来解决这些问题。Core Guidelines依赖于几十年的经验和早期的编码规则。它们与C本身共享一…

2d关键点转bvh fbx

本文使用的方法是把关键点转换成3d关键点&#xff0c;然后再使用脚本转换成bvh。bvh转fbx可以直接使用blender转。 环境准备 MotionBERT(2D关键点转换到3D关键点)AlphaPose(提取2D关键点)。转换脚本&#xff0c;https://github.com/TnoobT/pose2bvh/tree/main 步骤 安装好A…

Python经典游戏04:用tkinter给老板写一封拒绝不了的辞职信

★★★★★博文原创不易&#xff0c;我的博文不需要打赏&#xff0c;也不需要知识付费&#xff0c;可以白嫖学习编程小技巧。**如果使用代码的过程&#xff0c;有疑问的地方&#xff0c;欢迎大家指正留言交流。**喜欢的老铁可以多多帮忙点赞&#xff0c;小红牛在此表示感谢。★…

Azure + React + ASP.NET Core 项目笔记一:项目环境搭建(三)

有意义的标题 连接Azure SQL 数据库添加swagger新建数据库编写APIAPI连接更新 简单的前端搭建结束后&#xff0c;就到了后端搭建了 连接Azure SQL 数据库 解决方案 > 发布中 服务依赖项添加&#xff0c;这步不难&#xff0c;不放具体步骤了 成功是这样的 添加swagger Nu…

Kotlin中函数的基本用法以及函数类型

函数的基本用法 1、函数的基本格式 2、函数的缺省值 可以为函数设置指定的初始值&#xff0c;而不必要传入值 private fun fix(name: String,age: Int 2){println(name age) }fun main(args: Array<String>) {fix("张三") }输出结果为&#xff1a;张三2 …

Kotlin变量与控制条件的基本用法

一、变量与控制条件 1、var与val var&#xff1a;可修改变量 val&#xff1a;只读变量&#xff0c;只读变量并非绝对只读。 编译时常量只能在函数之外定义&#xff0c;因为函数内常量是在运行时赋值&#xff0c;编译时常量要在变量赋值前存在。并且值是无法修改的。 const…

maven配置问题之命令提示符显示JAVA_HOME有问题

在配置maven的环境变量时&#xff0c;命令提示符mvn -v显示错误 显示JAVA_HOME配置有问题 使用java -version查看java的配置时没反应 说明java的环境配置确实有问题 打开环境变量看了一下 JAVA_HOME的路径后面多了一个分号&#xff0c;把它删掉又试了试 木的问题了

ABB机器人如何利用示教器中的筛选功能查找IO信号?

ABB机器人如何利用示教器中的筛选功能查找IO信号? 如下图所示,点击左上角进入主菜单,点击选择“输入输出”, 如下图所示,点击右下角的“视图”,这里以数字输出DO为例进行说明,点击选择“数字输出”, 如下图所示,此时显示的是所有的数字输出信号,但是逐个查找太麻烦,…

优思学院|质量改进的关键:降低变异性

Quality means fitness for use. 质量&#xff0c;就是适用性&#xff0c;适用性是一个关键概念&#xff0c;涵盖了产品和服务的两个重要方面&#xff1a;设计质量和合规质量。无论何种商品或服务&#xff0c;都存在不同等级或质量水平。这些差异是有意的&#xff0c;因此适用的…

Web Scraping指南: 使用Selenium和BeautifulSoup

在当今信息时代&#xff0c;数据是无处不在的宝贵资源。对于许多企业、研究人员以及开发者来说&#xff0c;从互联网上获取准确且有价值的数据变得越来越重要。而Web scraping&#xff08;网络爬虫&#xff09;技术则成为了实现这一目标的关键工具。 本篇文章将向您介绍一个高…

【作为网工,你还只会Wireshark?那你就OUT了!】

Wireshark是非常流行的网卡抓包软件&#xff0c;具有强大的抓包功能。它可以截取各种网络数据包&#xff0c;并显示数据包详细信息。 这也就意味着&#xff0c;它可以查看所有网络的流量发生过什么。它适用的系统很多&#xff0c;而最受网络工程师欢迎的原因是&#xff0c;它是…

智元兔AI写作大师助你一分钟完成完美论文

你还在为能否畅爽写一篇满意的文章发愁吗&#xff1f; 你还在为论文开题写什么内容费尽脑汁吗&#xff1f; 你还在为论文的字数不足而感到困扰吗&#xff1f; 你还在为自己写的论文质量不高、论文过多的引用而烦恼吗? ...... 不要担心&#xff0c;智元兔写作大师可以帮助…

postgres源码解析56 Brin Index--3(update/delete/insert流程)

经过前两篇文章对brin index的讲解&#xff0c; 对brin index的构建更深入的认识&#xff0c;这些内容是理解索引更新流程的重点&#xff0c;相关知识点见postgres源码解析54 Brin Index–1   postgres源码解析55 Brin Index–2&#xff08;brinbuild流程&#xff09;。由于b…

当红语言模型利器:深度解析向量数据库技术及其应用

编者按&#xff1a;随着大语言模型的广泛应用&#xff0c;如何存储和高效检索这些模型产生的大量向量表示成为一个较为关键的问题。本文深入探讨了向量数据库在提升语言模型应用性能方面的作用&#xff0c;并介绍了不同类型向量数据库的特点。 本文以简明扼要的方式全面概述了向…

视频去水印系统源码 支持全平台无水印下载 含完整代码包+搭建教程

分享一个视频去水印系统源码&#xff0c;支持全平台无水印下载&#xff0c;含完整代码包搭建部署教程。 系统架构 视频去水印系统主要由以下几个部分组成&#xff1a; 视频读取&#xff1a;该模块负责读取待处理的视频文件&#xff0c;将其转换为软件可处理的格式。水印检测…

第十六课 虚拟语气

文章目录 前言一、什么是语气二、虚拟语气1、假设的情况与事实相反2、假设的情况与将来的事实相反3、假设的情况与过去的事实相反4、主、从句的动作发生的时间不一致的情况5、虚拟条件状语从句省掉连接词if 的情况6、用介词代替虚拟条件状语从句7、省掉条件状语从句或者主句 三…