nppiFilter中断输出图像



我用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 %dn", 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;
}

大部分代码是从示例boxFilterNPP.cpp中复制的。输出图像:http://img153.imageshack.us/img153/7716/o8z.png

为什么会这样?

您有一个跨越式的问题。更改此行:

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

对此:

npp::ImageCPU_8u_C4 oHostDst(oDeviceSrc.size());

发生了什么?

假设您的输入图像为600x450。

  • oHostSrc为600 x 450,间距为600x4=2400
  • 从CCD_ 3到CCD_ 4的CCD_
  • oDeviceSrcoHostSrcc拾取尺寸(600x450)
  • oDeviceDstoDeviceSrc稍小,因为它只拾取ROI的大小,所以它有点像596x446
  • 您的代码正在创建与oDeviceDst大小相同的oHostDst,因此大约为596x446
  • .copyTo操作将oDeviceDst(倾斜)596x446映像复制到(未倾斜)oHostDst,也就是596x446
  • 最终的memcpy会破坏图像,因为它正在将596x446个oHostDst图像复制到600x450个data区域

解决方案是以600x450创建oHostDst,并让.copyTo操作处理线条大小和间距的差异。

原始代码没有这个问题,因为该代码中的任何位置都没有未缝合的副本(例如,没有使用原始memcpy)。只要在每个复制步骤都明确处理源和目标的间距和宽度,那么将最终图像创建为600x450还是596x446都无关紧要。但您的最后一个memcpy操作并没有显式地处理间距和宽度,而是隐式地假设源和目的地大小相同,但事实并非如此。

最新更新