Cuda nppiFilter中断输出图像

Cuda nppiFilter中断输出图像,cuda,nvidia,npp,Cuda,Nvidia,Npp,我使用NPP编写了一个BoxFilter示例,但输出图像看起来已损坏。这是我的代码: #include <stdio.h> #include <string.h> #include <ImagesCPU.h> #include <ImagesNPP.h> #include <Exceptions.h> #include <npp.h> #include "utils.h" void boxfilter1_transf

我使用NPP编写了一个BoxFilter示例,但输出图像看起来已损坏。这是我的代码:

#include <stdio.h>
#include <string.h>

#include <ImagesCPU.h>
#include <ImagesNPP.h>
#include <Exceptions.h>

#include <npp.h>
#include "utils.h"


void boxfilter1_transform( Npp8u *data, int width, int height ){
    size_t size = width * height * 4;

    // declare a host image object for an 8-bit RGBA image
    npp::ImageCPU_8u_C4 oHostSrc(width, height);

    Npp8u *nDstData = oHostSrc.data();
    memcpy(nDstData, data, size * sizeof(Npp8u));

    // declare a device image and copy construct from the host image,
    // i.e. upload host to device
    npp::ImageNPP_8u_C4 oDeviceSrc(oHostSrc);

    // create struct with box-filter mask size
    NppiSize oMaskSize = {3, 3};

    // Allocate memory for pKernel
    Npp32s hostKernel[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
    Npp32s *pKernel;

    checkCudaErrors( cudaMalloc((void**)&pKernel, oMaskSize.width * oMaskSize.height * sizeof(Npp32s)) );
    checkCudaErrors( cudaMemcpy(pKernel, hostKernel, oMaskSize.width * oMaskSize.height * sizeof(Npp32s),
                                cudaMemcpyHostToDevice) );

    Npp32s nDivisor = 9;

    // create struct with ROI size given the current mask
    NppiSize oSizeROI = {oDeviceSrc.width() - oMaskSize.width + 1, oDeviceSrc.height() - oMaskSize.height + 1};
    // allocate device image of appropriatedly reduced size
    npp::ImageNPP_8u_C4 oDeviceDst(oSizeROI.width, oSizeROI.height);
    // set anchor point inside the mask
    NppiPoint oAnchor = {2, 2};

    // run box filter
    NppStatus eStatusNPP;
    eStatusNPP = nppiFilter_8u_C4R(oDeviceSrc.data(), oDeviceSrc.pitch(),
                                   oDeviceDst.data(), oDeviceDst.pitch(),
                                   oSizeROI, pKernel, oMaskSize, oAnchor, nDivisor);
    //printf("NppiFilter error status %d\n", eStatusNPP);
    NPP_DEBUG_ASSERT(NPP_NO_ERROR == eStatusNPP);

    // declare a host image for the result
    npp::ImageCPU_8u_C4 oHostDst(oDeviceDst.size());
    // and copy the device result data into it
    oDeviceDst.copyTo(oHostDst.data(), oHostDst.pitch());
    memcpy(data, oHostDst.data(), size * sizeof(Npp8u));

    return;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括“utils.h”
void-boxfilter1_变换(Npp8u*数据,整数宽度,整数高度){
尺寸=宽度*高度*4;
//为8位RGBA图像声明主机图像对象
npp::ImageCPU_8u_C4 oHostSrc(宽度、高度);
Npp8u*nDstData=oHostSrc.data();
memcpy(nDstData,data,size*sizeof(Npp8u));
//声明设备映像并从主机映像复制构造,
//即,将主机上载到设备
npp::图像npp_8u_C4 oDeviceSrc(oHostSrc);
//使用框过滤器掩码大小创建结构
NppiSize-oMaskSize={3,3};
//为pKernel分配内存
Npp32s主机内核[9]={1,1,1,1,1,1,1,1};
Npp32s*pKernel;
检查CUDAERRORS(cudaMalloc((void**)和pKernel,oMaskSize.width*oMaskSize.height*sizeof(Npp32s));
检查CUDAERRORS(cudaMemcpy(pKernel,hostKernel,oMaskSize.width*oMaskSize.height*sizeof(Npp32s),
cudamemcpyhostodevice);
Npp32s=9;
//使用给定当前掩码的ROI大小创建结构
NppiSize-oSizeROI={oDeviceSrc.width()-oMaskSize.width+1,oDeviceSrc.height()-oMaskSize.height+1};
//分配适当缩小大小的设备映像
npp::图像npp_8u_C4 oDeviceDst(oSizeROI.宽度,oSizeROI.高度);
//在遮罩内设置定位点
NppiPoint-oAnchor={2,2};
//运行箱过滤器
NppStatus eStatusNPP;
eStatusNPP=nppiFilter_8u_C4R(oDeviceSrc.data(),oDeviceSrc.pitch(),
oDeviceDst.data(),oDeviceDst.pitch(),
oSizeROI、pKernel、oMaskSize、oAnchor、nDivisor);
//printf(“NppiFilter错误状态%d\n”,eStatusNPP);
核电站调试断言(核电站无错误==eStatusNPP);
//为结果声明主机映像
npp::ImageCPU_8u_C4 oHostDst(oDeviceDst.size());
//并将设备结果数据复制到其中
oDeviceDst.copyTo(oHostDst.data(),oHostDst.pitch());
memcpy(data,oHostDst.data(),size*sizeof(Npp8u));
返回;
}
大部分代码是从示例boxFilterNPP.cpp复制的。以及输出图像:


为什么会这样?

您有跨步问题。更改此行:

npp::ImageCPU_8u_C4 oHostDst(oDeviceDst.size());
为此:

npp::ImageCPU_8u_C4 oHostDst(oDeviceSrc.size());
发生了什么事

假设您的输入图像是600x450

  • oHostSrc
    为600 x 450,螺距为600x4=2400
  • data
    oHostSrc
    memcpy
    是正常的,因为它们具有相同的宽度和间距
  • oDeviceSrc
    oHostSrcc
    (600x450)获取大小
  • oDeviceDst
    略小于
    oDeviceSrc
    ,因为它只拾取ROI的大小,所以类似于596x446
  • 您的代码正在创建与oDeviceDst大小相同的
    oHostDst
    ,因此大约为596x446
  • .copyTo
    操作将oDeviceDst(倾斜)596x446图像复制到(未倾斜)
    oHostDst
    ,也就是596x446
  • 最后一个
    memcpy
    会破坏图像,因为它正在将596x446
    oHostDst
    图像复制到600x450
    数据区域
解决方案是在600x450处创建
oHostDst
,并让
.copyTo
操作处理行大小和间距的差异


原始代码没有此问题,因为该代码中没有未粘贴的副本(例如,未使用原始
memcpy
)。只要在每个复制步骤中明确地处理源和目标的间距和宽度,创建最终图像是600x450还是596x446并不重要。但是最后的
memcpy
操作没有显式地处理间距和宽度,而是隐式地假设源和目标大小相同,而事实并非如此。

您有跨步问题。更改此行:

npp::ImageCPU_8u_C4 oHostDst(oDeviceDst.size());
为此:

npp::ImageCPU_8u_C4 oHostDst(oDeviceSrc.size());
发生了什么事

假设您的输入图像是600x450

  • oHostSrc
    为600 x 450,螺距为600x4=2400
  • data
    oHostSrc
    memcpy
    是正常的,因为它们具有相同的宽度和间距
  • oDeviceSrc
    oHostSrcc
    (600x450)获取大小
  • oDeviceDst
    略小于
    oDeviceSrc
    ,因为它只拾取ROI的大小,所以类似于596x446
  • 您的代码正在创建与oDeviceDst大小相同的
    oHostDst
    ,因此大约为596x446
  • .copyTo
    操作将oDeviceDst(倾斜)596x446图像复制到(未倾斜)
    oHostDst
    ,也就是596x446
  • 最后一个
    memcpy
    会破坏图像,因为它正在将596x446
    oHostDst
    图像复制到600x450
    数据区域
解决方案是在600x450处创建
oHostDst
,并让
.copyTo
操作处理行大小和间距的差异


原始代码没有此问题,因为该代码中没有未粘贴的副本(例如,未使用原始
memcpy
)。只要在每个复制步骤中明确地处理源和目标的间距和宽度,创建最终图像是600x450还是596x446并不重要。但是您最后的
memcpy
操作没有显式地处理间距和宽度,而是隐式地假定源和目标大小相同,而事实并非如此。

感谢您的帮助!问题解决了!在我更改了行(如您的回答中所示)之后,输出图像变得与原始图像一样。然后我改变了:
npp::ImageCPU_8u_C4 oHostDst(oDeviceSrc.size())至:
npp::图像CPU_8u_C4 oHostDst(宽度,h