CUDA库之NPP(二):NPP实现YUV转BGR

博主在CUDA库之NPP:NVIDIA 2D Image and Signal Processing Performance Primitives中已经详细介绍了NPP是啥,以及如何编译NPP。
这里就以 YUV转BGR为例,来完成NPP中的第一个例子(PS:也是博主的第一个Demo)



一、前言

  • 本文中的例子,仅适合于 512 ∗ 512 512*512 512512
    倍数的图像,因为npp处理数据时,有字节对齐
    这个说法,博主计划另写一篇文章 博主在CUDA库之NPP(四):内存开辟和字节对齐中简单探讨了一下字节对齐,本文不再单独研究(PS:补上这里的坑,已时隔一年,是我懒惰了)。
  • 因为只是一个很简单的Demo,所以本文不检测CUDA、NPP函数的返回码
  • 本文利用Opencv读取BGR图像,并转换成YUV的数据格式,然后将数据从主机(Host)拷贝到设备端(Device)
  • 调用nppiYUVToBGR_8u_C3R函数,将内存从设备端拷贝到主机端,再利用Opencv将图像保存出来

二、利用NPP函数,实现YUV转BGR

第一步、利用Opencv读取BGR图像,并转换成YUV数据格式

cv::Mat matBrgImg = cv::imread("./data/Fig0638(a)(lenna_RGB).jpg");
int nWidth = matBrgImg.cols; 
int nHeight = matBrgImg.rows;
int nStep = matBrgImg.step; // 每一行的步长,这里 = nWidth * 3
cv::Mat matYuvImg;
cv::cvtColor(matBrgImg, matYuvImg, CV_BGR2YUV);

左图是原图,右图是YUV上图中,左边是原图,右边是YUV数据
第二步,将YUV数据从 host拷贝到 dev端

Npp8u *pu8YUV_dev = NULL;
cudaMalloc((void **)& pu8YUV_dev, nWidth * nHeight * 3 * sizeof(Npp8u));
cudaMemcpy(pu8YUV_dev, (Npp8u *)matYuvImg.data, nWidth * nHeight * 3 * sizeof(Npp8u), cudaMemcpyHostToDevice);

这里的 Npp8unppdefs.h里,就是一个 unsigned char
关于更多npp中数据类型中的定义可见本文末

第三步、在Device上创建存放BGR数据的内存
这里推荐使用Npp8u * nppiMalloc_8u_C3(int nWidthPixels, int nHeightPixels, int * pStepBytes);
当然 cudamalloc函数也可以在Device上开辟内存空间。
npp这个函数,可以看到一个参数是 pStepBytes, 这个返回每一行占用字节数,由于本文采用的 512 ∗ 512 512*512 512512 的图像,所以这个值返回为 512 ∗ 3 512 * 3 5123

NppStatus nppRet = NPP_NO_ERROR;
NppiSize nppSize{nWidth, nHeight};
int nLineStep_npp = 0;
Npp8u *pu8BGR_dev = nppiMalloc_8u_C3(nWidth, nHeight, &nLineStep_npp);
printf("nLineStep_npp = %d \n", nLineStep_npp); 

第四步、利用npp中nppiYUVToBGR_8u_C3R函数将yuv数据转换成BGR

nppRet = nppiYUVToBGR_8u_C3R(pu8YUV_dev, nStep, pu8BGR_dev, nStep, nppSize);
 printf("nppRet = %d \n", nppRet);

第五步、将BGR数据从dev端拷贝到Host端,并验证结果

unsigned char *pu8Bgr_host = NULL;
pu8Bgr_host = (unsigned char *)malloc(  nWidth * nHeight * 3);
memset(pu8Bgr_host, 0, nWidth * nHeight * 3);
cudaMemcpy(pu8Bgr_host, pu8BGR_dev, nWidth * nHeight * 3, cudaMemcpyDeviceToHost);

cv::Mat newimage(nHeight, nWidth, CV_8UC3);
memcpy(newimage.data, pu8Bgr_host, nWidth * nHeight * 3);

cv::imwrite("./yuv2BGR.jpg",newimage );

最后,别忘记释放内存空间

if (NULL != pu8BGR_dev)
{
    nppiFree(pu8BGR_dev);
    pu8BGR_dev = NULL;
}

if (NULL != pu8YUV_dev)
{
    cudaFree(pu8YUV_dev);
    pu8YUV_dev = NULL;
}

if (NULL != pu8Bgr_host)
{
    free(pu8Bgr_host);
    pu8Bgr_host = NULL;
 }

最终,仍然可以得到原图
在这里插入图片描述

三、NPP相关函数定义

1、npp中基础数据类型定义,包括int、float等
具体定义可在 nppdefs.h里查下,以下仅摘录关于数据类型定义的一部分。

/** \defgroup npp_basic_types Basic NPP Data Types
 * @{
 */
typedef unsigned char       Npp8u;     /**<  8-bit unsigned chars */
typedef signed char         Npp8s;     /**<  8-bit signed chars */
typedef unsigned short      Npp16u;    /**<  16-bit unsigned integers */
typedef short               Npp16s;    /**<  16-bit signed integers */
typedef unsigned int        Npp32u;    /**<  32-bit unsigned integers */
typedef int                 Npp32s;    /**<  32-bit signed integers */
typedef unsigned long long  Npp64u;    /**<  64-bit unsigned integers */
typedef long long           Npp64s;    /**<  64-bit signed integers */
typedef float               Npp32f;    /**<  32-bit (IEEE) floating-point numbers */
typedef double              Npp64f;    /**<  64-bit floating-point numbers */

2、npp中返回码的定义,主要用来判断函数是否出错以及出错的原因
当返回码为0时,表示成功运行

typedef enum 
{
    /* negative return-codes indicate errors */
    NPP_NOT_SUPPORTED_MODE_ERROR            = -9999,  
    
    NPP_INVALID_HOST_POINTER_ERROR          = -1032,
    NPP_INVALID_DEVICE_POINTER_ERROR        = -1031,
    NPP_LUT_PALETTE_BITSIZE_ERROR           = -1030,
    NPP_ZC_MODE_NOT_SUPPORTED_ERROR         = -1028,      /**<  ZeroCrossing mode not supported  */
    NPP_NOT_SUFFICIENT_COMPUTE_CAPABILITY   = -1027,
    NPP_TEXTURE_BIND_ERROR                  = -1024,
    NPP_WRONG_INTERSECTION_ROI_ERROR        = -1020,
    NPP_HAAR_CLASSIFIER_PIXEL_MATCH_ERROR   = -1006,
    NPP_MEMFREE_ERROR                       = -1005,
    NPP_MEMSET_ERROR                        = -1004,
    NPP_MEMCPY_ERROR                        = -1003,
    NPP_ALIGNMENT_ERROR                     = -1002,
    NPP_CUDA_KERNEL_EXECUTION_ERROR         = -1000,

    NPP_ROUND_MODE_NOT_SUPPORTED_ERROR      = -213,     /**< Unsupported round mode*/
    
    NPP_QUALITY_INDEX_ERROR                 = -210,     /**< Image pixels are constant for quality index */

    NPP_RESIZE_NO_OPERATION_ERROR           = -201,     /**< One of the output image dimensions is less than 1 pixel */

    NPP_OVERFLOW_ERROR                      = -109,     /**< Number overflows the upper or lower limit of the data type */
    NPP_NOT_EVEN_STEP_ERROR                 = -108,     /**< Step value is not pixel multiple */
    NPP_HISTOGRAM_NUMBER_OF_LEVELS_ERROR    = -107,     /**< Number of levels for histogram is less than 2 */
    NPP_LUT_NUMBER_OF_LEVELS_ERROR          = -106,     /**< Number of levels for LUT is less than 2 */

    NPP_CORRUPTED_DATA_ERROR                = -61,      /**< Processed data is corrupted */
    NPP_CHANNEL_ORDER_ERROR                 = -60,      /**< Wrong order of the destination channels */
    NPP_ZERO_MASK_VALUE_ERROR               = -59,      /**< All values of the mask are zero */
    NPP_QUADRANGLE_ERROR                    = -58,      /**< The quadrangle is nonconvex or degenerates into triangle, line or point */
    NPP_RECTANGLE_ERROR                     = -57,      /**< Size of the rectangle region is less than or equal to 1 */
    NPP_COEFFICIENT_ERROR                   = -56,      /**< Unallowable values of the transformation coefficients   */

    NPP_NUMBER_OF_CHANNELS_ERROR            = -53,      /**< Bad or unsupported number of channels */
    NPP_COI_ERROR                           = -52,      /**< Channel of interest is not 1, 2, or 3 */
    NPP_DIVISOR_ERROR                       = -51,      /**< Divisor is equal to zero */

    NPP_CHANNEL_ERROR                       = -47,      /**< Illegal channel index */
    NPP_STRIDE_ERROR                        = -37,      /**< Stride is less than the row length */
    
    NPP_ANCHOR_ERROR                        = -34,      /**< Anchor point is outside mask */
    NPP_MASK_SIZE_ERROR                     = -33,      /**< Lower bound is larger than upper bound */

    NPP_RESIZE_FACTOR_ERROR                 = -23,
    NPP_INTERPOLATION_ERROR                 = -22,
    NPP_MIRROR_FLIP_ERROR                   = -21,
    NPP_MOMENT_00_ZERO_ERROR                = -20,
    NPP_THRESHOLD_NEGATIVE_LEVEL_ERROR      = -19,
    NPP_THRESHOLD_ERROR                     = -18,
    NPP_CONTEXT_MATCH_ERROR                 = -17,
    NPP_FFT_FLAG_ERROR                      = -16,
    NPP_FFT_ORDER_ERROR                     = -15,
    NPP_STEP_ERROR                          = -14,       /**<  Step is less or equal zero */
    NPP_SCALE_RANGE_ERROR                   = -13,
    NPP_DATA_TYPE_ERROR                     = -12,
    NPP_OUT_OFF_RANGE_ERROR                 = -11,
    NPP_DIVIDE_BY_ZERO_ERROR                = -10,
    NPP_MEMORY_ALLOCATION_ERR               = -9,
    NPP_NULL_POINTER_ERROR                  = -8,
    NPP_RANGE_ERROR                         = -7,
    NPP_SIZE_ERROR                          = -6,
    NPP_BAD_ARGUMENT_ERROR                  = -5,
    NPP_NO_MEMORY_ERROR                     = -4,
    NPP_NOT_IMPLEMENTED_ERROR               = -3,
    NPP_ERROR                               = -2,
    NPP_ERROR_RESERVED                      = -1,
    
    /* success */
    NPP_NO_ERROR                            = 0,        /**<  Error free operation */
    NPP_SUCCESS = NPP_NO_ERROR,                         /**<  Successful operation (same as NPP_NO_ERROR) */

    /* positive return-codes indicate warnings */
    NPP_NO_OPERATION_WARNING                = 1,        /**<  Indicates that no operation was performed */
    NPP_DIVIDE_BY_ZERO_WARNING              = 6,        /**<  Divisor is zero however does not terminate the execution */
    NPP_AFFINE_QUAD_INCORRECT_WARNING       = 28,       /**<  Indicates that the quadrangle passed to one of affine warping functions doesn't have necessary properties. First 3 vertices are used, the fourth vertex discarded. */
    NPP_WRONG_INTERSECTION_ROI_WARNING      = 29,       /**<  The given ROI has no interestion with either the source or destination ROI. Thus no operation was performed. */
    NPP_WRONG_INTERSECTION_QUAD_WARNING     = 30,       /**<  The given quadrangle has no intersection with either the source or destination ROI. Thus no operation was performed. */
    NPP_DOUBLE_SIZE_WARNING                 = 35,       /**<  Image size isn't multiple of two. Indicates that in case of 422/411/420 sampling the ROI width/height was modified for proper processing. */
    
    NPP_MISALIGNED_DST_ROI_WARNING          = 10000,    /**<  Speed reduction due to uncoalesced memory accesses warning. */
   
} NppStatus;

3、nppiMalloc_8u_C3创建内存
函数定义如下:

Npp8u  * 
nppiMalloc_8u_C3(int nWidthPixels, int nHeightPixels, int * pStepBytes);
  • 返回一个Npp8u *地址
  • 输入有图像的宽、高
  • int * pStepBytes返回每行占用字节数,由于本文采用的 512 ∗ 512 512*512 512512 的图像,所以这个值返回为 512 ∗ 3 512 * 3 5123

如果输入图像的宽小于512,这个值会补齐为512(这个512可能和显卡设备有关,笔者实验是1080卡)的最小倍数
比如,输入图像的宽为400, pStepBytes = 1536;
比如,输入图像的宽为513, pStepBytes = 2048;
可用如下代码实验

#include "npp.h"
#include "npps_support_functions.h"

int main()
{
    int nWidth = 513;
    int nHeight = 400;
    int nLineStep_npp = 0;
    Npp8u *pu8BGR_dev = nppiMalloc_8u_C3(nWidth, nHeight, &nLineStep_npp);
    printf("nLineStep_npp = %d \n", nLineStep_npp);
    
    printf("hello world \n");
    return 0;
}

4、NppStatus nppiYUVToBGR_8u_C3R(const Npp8u * pSrc, int nSrcStep, Npp8u * pDst, int nDstStep, NppiSize oSizeROI);函数将YUV转换成BGR

  • *pSrc 源数据地址
  • *nSrcStep 源数据的Step,即每行占用字节数
  • *pDst 目的数据
  • *nDstStep 目的数据的Step.
  • oSizeROI 感兴趣区域
  • return 错误码
  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: NPP是Net Primary Productivity的缩写,指的是植物净初级生产力。在python中,可以使用一些常用的和算法来计算NPP。 首先,我们需要获取植物的生物量和光合有效辐射(PAR)数据。可以使用遥感或实地采集的方法获取这些数据。 接下来,我们可以使用以下公式计算NPPNPP = GPP - R 其中,GPP代表植物总初级生产力,R代表植物的呼吸损失。 对于GPP的计算,可以使用光合作用模型,例如Farquhar模型。该模型将光合速率与环境因子(如CO2浓度、温度、光照强度)和植物特性相关联。可以通过获取环境因子数据和植物特性参数,计算得到GPP。 对于R的计算,可以使用常见的呼吸模型,例如Lloyd-Taylor模型。该模型将植物呼吸速率与温度相关联。可以通过获取温度数据,计算得到R。 最后,将计算得到的GPP和R代入NPP的公式中,即可得到NPP的值。 通过使用python中的科学计算(如numpy和pandas)和相关模型,我们可以实现NPP的计算。需要注意的是,为了得到准确的结果,数据的质量和准确性非常重要,在计算中要谨慎处理异常值和数据缺失的情况。 ### 回答2: Python实现NPP(Nonparametric Power Calculations)计算是通过使用相应的统计和函数来计算。NPP用于估计实验的样本大小或功效,而无需做出对总体分布形状或参数假设。下面是一个简单的Python代码示例: ```python import numpy as np from statsmodels.stats.power import tt_ind_solve_power def calculate_npp(effect_size, alpha, power): # 设置输入参数 nobs1 = None # 第一组样本大小(未知) ratio = 1.0 # 第二组样本相对于第一组的样本比例 nobs2 = ratio * nobs1 # 第二组样本大小(根据比例计算) # 使用tt_ind_solve_power函数计算样本大小 nobs1 = tt_ind_solve_power(effect_size=effect_size, alpha=alpha, power=power, nobs1=nobs1, ratio=ratio) # 打印结果 print("第一组样本大小:", nobs1) print("第二组样本大小:", nobs2) # 调用函数进行计算 calculate_npp(effect_size=0.5, alpha=0.05, power=0.8) ``` 上述代码中,我们使用了numpy和statsmodels中的tt_ind_solve_power函数来进行NPP计算。在函数中,我们需要提供效应大小(effect_size)、显著性水平(alpha)和功效(power)等参数。函数会自动计算并打印出第一组和第二组样本的大小。 ### 回答3: Python实现NPP(Net Primary Productivity,净初级生产力)计算可以通过以下步骤完成: 1. 首先,需要准备NPP计算所需的数据。这些数据通常包括植被指数(Vegetation Index)、环境温度、降水量等。可以使用现有的气象站数据或遥感数据来获取这些数据。 2. 根据所选的NPP计算公式,编写Python函数来计算NPPNPP的计算公式通常包括植被指数、环境温度和降水量等因素,具体公式可以根据研究领域和需求选择。 3. 在Python中,可以使用NumPy(Numerical Python)来进行数据处理和计算。可以使用NumPy中的数组对数据进行处理,例如计算平均值、最大值等。 4. 在编写NPP计算函数时,可以使用条件语句和循环语句来处理不同情况下的数据,例如根据植被指数和环境温度的不同范围选择不同的计算公式。 5. 将计算得到的NPP结果保存到文件中,以便后续分析和使用。可以使用Python中的文件操作函数将结果写入到CSV或其他格式的文件中。 6. 最后,为了验证和评估NPP计算的准确性,可以使用已有的NPP数据进行对比。通过比对计算结果和已有数据之间的差异,可以评估计算结果的可靠性,并进行必要的调整和改进。 总之,通过准备数据、编写计算函数、使用NumPy进行数据处理、保存结果和验证计算准确性等步骤,可以实现Python对NPP的计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值