CUDA, АЭС Фильтры

Библиотека CUDA NPP поддерживает фильтрацию изображения с помощью команды nppiFilter_8u_C1R, но продолжает получать ошибки. У меня нет проблем с запуском примера кода boxFilterNPP.

eStatusNPP = nppiFilterBox_8u_C1R(oDeviceSrc.data(), oDeviceSrc.pitch(), 
                                  oDeviceDst.data(), oDeviceDst.pitch(), 
                                  oSizeROI, oMaskSize, oAnchor);

Но если я изменю его на использование nppiFilter_8u_C1R, eStatusNPP вернет ошибку -24 (NPP_TEXTURE_BIND_ERROR). Код ниже - это изменения, которые я сделал в исходном образце boxFilterNPP.

NppiSize oMaskSize = {5,5};
npp::ImageCPU_32s_C1 hostKernel(5,5);

for(int x = 0 ; x < 5; x++){
    for(int y = 0 ; y < 5; y++){
        hostKernel.pixels(x,y)[0].x = 1;
    }
}

npp::ImageNPP_32s_C1 pKernel(hostKernel);

Npp32s nDivisor = 1;

eStatusNPP = nppiFilter_8u_C1R(oDeviceSrc.data(), oDeviceSrc.pitch(), 
                               oDeviceDst.data(), oDeviceDst.pitch(), 
                               oSizeROI, 
                               pKernel.data(),
                               oMaskSize, oAnchor,
                               nDivisor);

Это было опробовано на CUDA 4.2 и 5.0, с тем же результатом.

Код выполняется с ожидаемым результатом, когда oMaskSize = {1,1}

3 ответа

Решение

У меня была такая же проблема, когда я хранил свое ядро ​​как ImageCPU/ImageNPP,

Хорошее решение - хранить ядро ​​как традиционный одномерный массив на устройстве. Я попробовал это, и это дало мне хорошие результаты (и ни один из тех непредсказуемых или мусорных изображений).

Спасибо Фрэнку Джаргсторффу в этом посте Stackru за 1D идею.

NppiSize oMaskSize = {5,5};
Npp32s hostKernel[5*5];

for(int x = 0 ; x < 5; x++){
    for(int y = 0 ; y < 5; y++){
        hostKernel[x*5+y] = 1;
    }
}

Npp32s* pKernel; //just a regular 1D array on the GPU
cudaMalloc((void**)&pKernel, 5 * 5 * sizeof(Npp32s));
cudaMemcpy(pKernel, hostKernel, 5 * 5 * sizeof(Npp32s), cudaMemcpyHostToDevice);

Используя это оригинальное изображение, вот размытый результат, который я получаю из вашего кода с массивом ядра 1D:

Другие параметры, которые я использовал:

Npp32s nDivisor = 25;
NppiPoint oAnchor = {4, 4};

Фильтр применяет маску, продолжающуюся вверх и влево, в соответствии с математическим соглашением о том, что свертка между двумя функциями меняет направление второй функции.

Маска фильтра коробки простирается вниз и вправо, что, вероятно, более интуитивно понятно.

В любом случае проблема вызвана тем фактом, что входное изображение в измененном коде должно было бы быть выбрано с тем, что фактически было бы ИСТОЧНИКОМ [-4, -4) для вычисления DESTINATION[0, 0]. Поскольку доступ к входному изображению осуществляется через сэмплер текстуры, привязка смещения указателя исходного изображения на (-4, -4) вызывает ошибку привязки текстуры, которую вы видите.

Обходной путь: Самый простой обходной путь для этой проблемы должен был бы установить опорную точку в (4, 4), которая эффективно сместила бы маску вниз и вправо. Вам все еще нужно знать, что вы хотите инвертировать веса в массиве ядра (т.е. K[-4, -4] -> K[0, 0], K[0, 0] -> K[-4, -4], так далее.).

Спасибо вам за помощь. Получил ошибку, но я вижу странное поведение. Изображение меняется в зависимости от того, какую программу я запускаю непосредственно перед этим, и изображение не показывает, что я иду вперед.

Пример, который я пытаюсь имитировать, - это nppiFilterBox_8u_C1R с использованием nppiFilter_8u_C1R, где я устанавливаю ядро ​​в единицу, а nDivisor - в сумму ядра.

Этот код все еще является изменением примера кода boxFilterNPP.

NppiSize oMaskSize = {5,5};
npp::ImageCPU_32s_C1 hostKernel(5,5);
for(int x = 0 ; x < 5; x++){
    for(int y = 0 ; y < 5; y++){
        hostKernel.pixels(x,y)[0].x = 1;
    }
}

npp::ImageNPP_32s_C1 pKernel(hostKernel);
Npp32s nDivisor = 25;
NppiPoint oAnchor = {4, 4};
eStatusNPP = nppiFilter_8u_C1R(oDeviceSrc.data(),oDeviceSrc.pitch(), 
                               oDeviceDst.data(), oDeviceDst.pitch(), 
                               oSizeROI, 
                               pKernel.data(),
                               oMaskSize, oAnchor,
                               nDivisor);

Поскольку ядро ​​только единое, необходимость инвертировать веса не должна быть проблемой.

5 различных видов изображений, которые возвращают этот код, показаны ниже. В основном последний возвращается.

http://1ordrup.dk/kasper/image/Lena_boxFilter1.jpg
http://1ordrup.dk/kasper/image/Lena_boxFilter2.jpg
http://1ordrup.dk/kasper/image/Lena_boxFilter3.jpg
http://1ordrup.dk/kasper/image/Lena_boxFilter4.jpg 
http://1ordrup.dk/kasper/image/Lena_boxFilter5.jpg

Я думаю, что причина этого заключается в том, что ядро ​​не инициализировано правильно или не используется, поэтому данные с псевдослучайным содержимым используются для ядра.

Другие вопросы по тегам