当前位置: 首页 > news >正文

CUDA小白 - NPP(3) 图像处理 Color and Sampling Conversion

cuda小白
原始API链接 NPP

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

常见的NppStatus,可以看这里。

如有问题,请指出,谢谢

本节内容主要涉及到使用NPP进行一些图像色域变换等,类似功能的就不细说,仅针对一些常见的。由于Debayer,不同yuv之间的转换(Color Sampling Format Conversion),Gamma校正,Complement Color Key(一直不清楚这个啥)以及Color Processing(调色相关)的接触不对,后面就不介绍了,按需。

Color Model Conversion

当前模块主要涉及到的RGB,BGR,YUV,YUV420,YUV422,NV12,YCbCr,YCbCr422和YCbCr420之间的相互转换,以及批处理(分为同样ROI和不同ROI两个接口)的接口。其他还有一些未接触过的XYZ,LUV,Lab,YCC,CMYK_JPEG,HLS,HSV等与RGB或者BGR之间的转换。
本文就那比较简单的转换,以为RGB和YUV之间的相互转换为例子。

// 此处介绍的RGB和YUV都是三通道的,如果是packed的相互转换,则后缀是C3R,如果都是planar的,则后缀是P3R,反之则是P3C3R或者C3P3R。
// =========== RGB2YUV原理 ===========
// Npp32f nY =  0.299F * R + 0.587F * G + 0.114F * B; 
// Npp32f nU = (0.492F * ((Npp32f)nB - nY)) + 128.0F;
// Npp32f nV = (0.877F * ((Npp32f)nR - nY)) + 128.0F;
// if (nV > 255.0F) 
//     nV = 255.0F; 
NppStatus nppiRGBToYUV_8u_C3R(const Npp8u *pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI);// =========== RGB2YUV原理 ===========
// Npp32f nY = (Npp32f)Y;
// Npp32f nU = (Npp32f)U - 128.0F;
// Npp32f nV = (Npp32f)V - 128.0F;
// Npp32f nR = nY + 1.140F * nV; 
// if (nR < 0.0F)    nR = 0.0F;
// if (nR > 255.0F)  nR = 255.0F;    
// Npp32f nG = nY - 0.394F * nU - 0.581F * nV;
// if (nG < 0.0F)    nG = 0.0F;
// if (nG > 255.0F)  nG = 255.0F;    
// Npp32f nB = nY + 2.032F * nU;
// if (nB < 0.0F)    nB = 0.0F;
// if (nB > 255.0F)  nB = 255.0F;    
NppStatus nppiYUVToRGB_8u_C3R(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");int image_width = image_dog.cols;int image_height = image_dog.rows;int image_size = image_width * image_height * 3;// =============== device memory ===============uint8_t *in_ptr, *yuv, *out_ptr;cudaMalloc((void**)&in_ptr, image_size * sizeof(uint8_t));cudaMalloc((void**)&yuv, image_size * sizeof(uint8_t));cudaMalloc((void**)&out_ptr, image_size * sizeof(uint8_t));cudaMemcpy(in_ptr, image_dog.data, image_size, cudaMemcpyHostToDevice);NppiSize roi1, roi2;roi1.width = image_width;roi1.height = image_height;roi2.width = image_width / 2;roi2.height = image_height / 2;// =============== nppiRGBToYUV_8u_C3R ===============uint8_t *host_yuv = (uint8_t *)malloc(image_size);NppStatus status;status = nppiRGBToYUV_8u_C3R(in_ptr, image_width * 3, yuv, image_width * 3, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiRGBToYUV_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(host_yuv, yuv, image_size, cudaMemcpyDeviceToHost);std::string out_yuv_file = directory + "yuv.bin";FILE *fp = fopen(out_yuv_file.c_str(), "wb");fwrite(host_yuv, image_size, 1, fp);fclose(fp);// =============== nppiYUVToRGB_8u_C3R ===============cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);status = nppiYUVToRGB_8u_C3R(yuv, image_width * 3, out_ptr, image_width * 3, roi2);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiYUVToRGB_8u_C3R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image.data, out_ptr, image_size, cudaMemcpyDeviceToHost);cv::imwrite(directory + "out_rgb.jpg", out_image);// freeCUDA_FREE(in_ptr)CUDA_FREE(yuv)CUDA_FREE(out_ptr)if (host_yuv != nullptr) { free(host_yuv); host_yuv = nullptr; }
}
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

yuv的结果,使用7yuv工具查看
请添加图片描述
使用转换之后的yuv,再转回RGB,在限定ROI之后的结果:
请添加图片描述
注意点:

  1. 可以使用7yuv进行yuv图像的查看,7yuv,下载对应的版本即可,可以体验。
  2. 还有一个接口是基于JPEG的,主要介绍的是JPEG的Color Conversion,由于平时接触较少,这里暂时不介绍了,按需取《JPEG Color Conversion》.

ColorToGray Conversion

当前模块也主要分为三个大方向:RGBToGray,ColorToGray和GradientColorToGray。三个大方向都只选取一个比较常见的进行介绍:

// nGray =  0.299F * R + 0.587F * G + 0.114F * B; 
NppStatus nppiRGBToGray_8u_C3C1R(const Npp8u *pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI);
// nGray =  aCoeffs[0] * R + aCoeffs[1] * G + aCoeffs[2] * B;
NppStatus nppiColorToGray_8u_C3C1R(const Npp8u *pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI,const Npp32f aCoeffs[3]);							 
// NppiNorm { max(inf) / sum(L1) / square root of sum of squares(L2) }
NppStatus nppiGradientColorToGray_8u_C3C1R(const Npp8u *pSrc,int nSrcStep,Npp8u *pDst,int nDstStep,NppiSize oSizeROI,NppiNorm eNorm);
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::cvtColor(image_dog, image_dog, CV_RGB2BGR);int image_width = image_dog.cols;int image_height = image_dog.rows;int image_size = image_width * image_height;// =============== device memory ===============uint8_t *in_ptr;cudaMalloc((void**)&in_ptr, image_size * 3 * sizeof(uint8_t));cudaMemcpy(in_ptr, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);uint8_t *out_ptr1, *out_ptr2, *out_ptr3;cudaMalloc((void**)&out_ptr1, image_size * sizeof(uint8_t));cudaMalloc((void**)&out_ptr2, image_size * sizeof(uint8_t));cudaMalloc((void**)&out_ptr3, image_size * sizeof(uint8_t));NppiSize roi1, roi2;roi1.width = image_width;roi1.height = image_height;roi2.width = image_width / 2;roi2.height = image_height / 2;// =============== nppiRGBToGray_8u_C3C1R ===============cv::Mat out_image_gray = cv::Mat::zeros(image_height, image_width, CV_8UC1);NppStatus status;status = nppiRGBToGray_8u_C3C1R(in_ptr, image_width * 3, out_ptr1, image_width, roi1);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiRGBToGray_8u_C3C1R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image_gray.data, out_ptr1, image_size, cudaMemcpyDeviceToHost);cv::imwrite(directory + "rgb2gray.jpg", out_image_gray);// =============== nppiColorToGray_8u_C3C1R ===============float coeffs[3] = { 0.1f, 0.8f, 0.1f};status = nppiColorToGray_8u_C3C1R(in_ptr, image_width * 3, out_ptr2, image_width, roi1, coeffs);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiColorToGray_8u_C3C1R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image_gray.data, out_ptr2, image_size, cudaMemcpyDeviceToHost);cv::imwrite(directory + "color2rgb.jpg", out_image_gray);// =============== nppiGradientColorToGray_8u_C3C1R_Ctx ===============status = nppiGradientColorToGray_8u_C3C1R(in_ptr, image_width * 3, out_ptr3, image_width, roi1, nppiNormInf);if (status != NPP_SUCCESS) {std::cout << "[GPU] ERROR nppiGradientColorToGray_8u_C3C1R failed, status = " << status << std::endl;return false;}cudaMemcpy(out_image_gray.data, out_ptr3, image_size, cudaMemcpyDeviceToHost);cv::imwrite(directory + "gradient.jpg", out_image_gray);// freeCUDA_FREE(in_ptr)CUDA_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. Color2Gray的接口与RGB2Gray的区别主要在于三个通道是不是比例关系。由于都是灰度图的,ColorGray的变化与直接rgb的转换结果差异性不易从肉眼看出来,但是通过不同的比例组合明显看出图像是有区别的。

相关文章:

CUDA小白 - NPP(3) 图像处理 Color and Sampling Conversion

cuda小白 原始API链接 NPP GPU架构近些年也有不少的变化&#xff0c;具体的可以参考别的博主的介绍&#xff0c;都比较详细。还有一些cuda中的专有名词的含义&#xff0c;可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus&#xf…...

Android硬件通信之 串口通信

一&#xff0c;串口介绍 1.1 串口简介 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方式的扩展接口&#xff1b; 串行接口&#xff08;SerialInterface&#xff09;是指数据一位一位地顺序…...

高防服务器面对DDOS攻击的威胁有何必要性

高防服务器面对DDOS攻击的威胁有何必要性&#xff1f;分布式拒绝服务&#xff08;DDoS&#xff09;攻击是一种常见而危险的网络攻击形式&#xff0c;它可以使目标网络服务器过载&#xff0c;导致服务不可用。本文将深入探讨DDoS攻击的威胁&#xff0c;以及高防服务器在抵御这种…...

VBA中如何将if写到一行

在VBA中&#xff0c;可以使用以下两种方式来编写一行if语句&#xff1a; 使用三元运算符&#xff1a; Dim result As String result "Yes" If True Else "No"在这个例子中&#xff0c;如果条件为真&#xff0c;则result变量的值为"Yes"&#…...

性能测试,python 内存分析工具 -memray

Memray是一个由彭博社开发的、开源内存剖析器&#xff1b;开源一个多月&#xff0c;已经收获了超8.4k的star&#xff0c;是名副其实的明星项目。今天我们就给大家来推荐这款python内存分析神器。 Memray可以跟踪python代码、本机扩展模块和python解释器本身中内存分配&#xf…...

Jmeter(二十八):beanshell的使用

Beanshell 是一种轻量级的 Java 脚本,纯 Java 编写的,能够动态的执行标准 java 语法及一些扩展脚本语法,类似于 javaScript,在工作中可能用的多的就是: Beanshell 取样器:跟Http取样器并列Beanshell前置处理器:一般放在Http请求下,在请求前处理一些数据Beanshell后置处…...

数学建模:层次分析法

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 层次分析法 步骤描述 将问题条理化&#xff0c;层次化&#xff0c;构建出一个有层次的结构模型。层次分为三类&#xff1a;目标层&#xff0c;准则&#xff08;指标&#xff09;层&#xff0c;方案层。比…...

POI-TL制作word

本文相当于笔记&#xff0c;主要根据官方文档Poi-tl Documentation和poi-tl的使用&#xff08;最全详解&#xff09;_JavaSupeMan的博客-CSDN博客文章进行学习&#xff08;上班够用&#xff09; Data AllArgsConstructor NoArgsConstructor ToString EqualsAndHashCode public …...

大数据Flink(七十一):SQL的时间属性

文章目录 SQL的时间属性 一、Flink三种时间属性简介...

51单片机项目(7)——基于51单片机的温湿度测量仿真

本次做的设计&#xff0c;是利用DHT11传感器&#xff0c;测量环境的温度以及湿度&#xff0c;同时具备温度报警的功能&#xff1a;利用两个按键&#xff0c;设置温度阈值的加和减&#xff0c;当所测温度大于温度阈值的时候&#xff0c;蜂鸣器就会响起&#xff0c;进行报警提示。…...

按钮控件之1---QPushButton 标准按钮/普通按钮控件

1、父类QAbstractButton 2、QPushButton按钮&#xff0c;是Qt常用的控件之一&#xff0c;提供普通的按钮功能。 通过信号槽机制接收触发信号并执行对应动作。3、创建QPushButton 它有三个构造函数&#xff1a; // 空对象 QPushButton(QWidget *parent nullptr); // 指定QPus…...

Ae 效果:CC Light Rays

生成/CC Light Rays Generate/CC Light Rays CC Light Rays&#xff08;CC 光线&#xff09;可以创建从光源发出并能穿过图层内容的光线效果。常用于制作光线透过门窗或云层的场景&#xff0c;或者用于创建神奇或梦幻的氛围感。 本效果会被限制在源图层的大小范围之内。 ◆ ◆…...

MPI之通信模式(标准,缓存,同步,就绪)

MPI缓冲区 由MPI自行维护的一块内存区域&#xff0c;也可由用户(MPI_Bsend)自行维护&#xff1b;发送方 维护一块发送缓冲区&#xff1b; 接收方 维护一块接收缓冲区。 数据收发过程&#xff1a; 当发送端将数据拷贝到自身的数据缓冲区后(注意这里是拷贝&#xff0c;即数据到…...

面试官:说一下 MyBatis 的一级缓存和二级缓存 ?

目录 1. MyBatis 的缓存机制 2. 为什么不默认开启 MyBatis 的二级缓存 3. MyBatis 如何开启二级缓存 4. MyBatis 有哪些缓存清除策略 1. MyBatis 的缓存机制 MyBayis 中包含两级缓存&#xff1a;一级缓存和二级缓存 1. 一级缓存是 SqlSession 级别的&#xff0c;是 MyBati…...

Ajax与jQuery

目录 Ajax是一种异步无刷新的技术 Ajax的优点&#xff1a; 可以无需刷新页面与服务器端进行通信允许根据用户事件来更新部分页面内容 Ajax的缺点&#xff1a; 没有浏览历史&#xff0c;不能回退存在跨域问题&#xff08;同源&#xff09;SEO&#xff08;搜索引擎优化&#x…...

色温曲线坐标轴的选取:G/R、G/B还是R/G、B/G ?

海思色温曲线坐标 Mstar色温曲线坐标 高通色温曲线坐标 联咏色温曲线坐标 查看各家白平衡调试界面&#xff0c;比如海思、Mstart、高通等调试资料&#xff0c;白平衡模块都是以R/G B/G作为坐标系的两个坐标轴&#xff0c;也有方案是以G/R G/B作为坐标系的两个坐标轴。 以G/R G…...

maven部署

一、下载Maven 地址&#xff1a;Maven – Download Apache Maven 二、解压缩&#xff0c;设置环境变量 tar -xvf apache-maven-3.8.8-bin.tar.gz export MAVEN_HOME/opt/apache-maven-3.8.8 export PATH$MAVEN_HOME/bin:$PATH echo $MAVEN_HOME echo $PATH mvn -v...

docker进阶作业

一、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 安装Docker&#xff1a;确保已在CentOS 7.5上安装了Docker。 拉取MySQL 5.6镜像&#xff1a;使用以下命令从Docker Hub上拉取MySQL 5.6镜像。 docker pull mysql:5.6 运行MySQL容器&#xff1a;使用以下命令…...

HTML+JavaScript+CSS DIY 分隔条splitter

一、需求分析 现在电脑的屏幕越来越大&#xff0c;为了利用好宽屏&#xff0c;我们在设计系统UI时喜欢在左侧放个菜单或选项面板&#xff0c;在右边显示与菜单或选项对应的内容&#xff0c;两者之间用分隔条splitter来间隔&#xff0c;并可以通过拖动分隔条splitter来动态调研…...

Oracle-day5:新增、复制建表、表结构、表数据、删除

目录 一、insert新增数据 二、复制建表 三、表结构修改 四、查看表结构、表数据处理 五、修改表数据 六、删除语句 八、练习题 一、insert新增数据 /* ---------- 一、DML 数据操作语言-------- -- 1、增加数据 insert 语法&#xff1a;insert into 表名 (列1,列2,…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...