无法理解NPP nppiFilterMedian参数ROI,掩码,偏移量等

问题描述

2020/08/30编辑

我在NVIDIA论坛上https://forums.developer.nvidia.com/t/nppifiltermedian-memory-out-of-bounds-with-y-axis-mask/149420

对我的问题进行了更全面的演示。

原始问题

我很难确定nppiFilterMedian函数系列的适当参数-特别是nppiFilterMedian_32f_C1R。我使用了推力和NPP的混合物。

我的最初目标是将MATLAB代码转录为C ++。这是一个使用“ movmedian”在水平和垂直方向上应用中值滤波器(一维滤波器大小)的基本MATLAB示例:

>> input = [(-10.0:-7);(-6:-3)]

input =

   -10    -9    -8    -7
    -6    -5    -4    -3

>> output = movmedian(input,3,1)

output =

    -8    -7    -6    -5
    -8    -7    -6    -5

>> output = movmedian(input,2)

output =

   -9.5000   -9.0000   -8.0000   -7.5000
   -5.5000   -5.0000   -4.0000   -3.5000

在那之后,我花了一些时间尝试使其通过Thrust和NPP与CUDA一起使用:

#include <thrust/device_vector.h>
#include <thrust/host_vector.h>

#include "npp.h"
#include "nppi.h"
#include "filter.h"

int main(int argc,char **argv) {
    int width = 2;
    int height = 4;

    int nstep = width*sizeof(Npp32f);

    int filter_len = 3;

    thrust::device_vector<float> input(width*height,0.0F);
    thrust::device_vector<float> output(width*height,0.0F);

    NppiSize roi = NppiSize{width,height};

    NppiSize mask_horizontal = NppiSize{1,filter_len};
    NppiPoint anchor_horizontal = NppiPoint{0,1}; // start in center of filter

    NppiSize mask_vertical = NppiSize{filter_len,1};
    NppiPoint anchor_vertical = NppiPoint{1,0}; // start in center of filter

    Npp8u* buffer_horizontal;
    Npp32u buffer_size_horizontal;

    Npp8u* buffer_vertical;
    Npp32u buffer_size_vertical;

    NppStatus npp_status = nppiFilterMedianGetBufferSize_32f_C1R(
        roi,mask_horizontal,&buffer_size_horizontal);
    if (npp_status != NPP_NO_ERROR) {
        std::cerr << "NPP error " << npp_status << std::endl;
        std::exit(1);
    }

    cudaError cuda_status
        = cudaMalloc(( void** )&buffer_horizontal,buffer_size_horizontal);
    if (cuda_status != cudaSuccess) {
        std::cerr << cudaGetErrorString(cuda_status);
        std::exit(1);
    }

    float start = -10.0f;
    for (std::size_t i = 0; i < width; ++i) {
        for (std::size_t j = 0; j < height; ++j) {
            input[i*height + j] = start;
            start += 1.0F;
        }
    }

    std::cout << "input" << std::endl;
    for (int i = 0; i < width; ++i) {
        std::cout << "row " << i << std::endl;
        for (std::size_t j = 0; j < height; ++j) {
            std::cout << input[i*height + j] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;

    // apply horizontal 1D median filter
    nppiFilterMedian_32f_C1R(thrust::raw_pointer_cast(input.data()),nstep,thrust::raw_pointer_cast(output.data()),roi,anchor_horizontal,buffer_horizontal);

    std::cout << "output horizontal" << std::endl;
    for (int i = 0; i < width; ++i) {
        std::cout << "row " << i << std::endl;
        for (std::size_t j = 0; j < height; ++j) {
            std::cout << output[i*height + j] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;

    // apply vertical 1D median filter
    nppiFilterMedian_32f_C1R(thrust::raw_pointer_cast(input.data()),mask_vertical,anchor_vertical,buffer_vertical);

    std::cout << "output vertical" << std::endl;
    for (int i = 0; i < width; ++i) {
        std::cout << "row " << i << std::endl;
        for (std::size_t j = 0; j < height; ++j) {
            std::cout << output[i*height + j] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;

    cudaFree(buffer_horizontal);
    cudaFree(buffer_vertical);
}

打印的输出如下:

input
row 0
-10 -9 -8 -7
row 1
-6 -5 -4 -3


output horizontal
row 0
-8 -7 -8 -7
row 1
-6 -5 -4 -3


output vertical
row 0
-9 -9 -8 -7
row 1
-6 -5 -4 -3

垂直看起来可能是正确的(浮点精度较低-也许是GPGPU吗?),但水平不是。

通常,我对ROI,锚点,步距的概念非常困惑,尤其是ROI src指针偏移量:https://docs.nvidia.com/cuda/npp/nppi_conventions_lb.html#roi_specification

我不确定我是否应该从偏移量1开始,然后将roi减小1(以确保滤镜的左侧不小于0或大于width-1)。

任何帮助将不胜感激。

FWIW,我能够使用一个更简单的中值滤波器库mf2d-它不能提供与MATLAB完全相同的输出,但是总体来说,它在整体算法中似乎可以正常工作。

在简单的库中,参数少得多(没有roi,mask,anchor等)。我的函数调用很简单:

// apply 1D median filter in horizontal direction
median_filter_2d<float>(height,width,filter_len,input.data(),output.data());

// apply 1D median filter in vertical direction
median_filter_2d<float>(height,output.data());

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...