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}

4

Решение

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

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

Благодаря Фрэнк Джаргсторф это сообщение StackOverflow для 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};
2

Другие решения

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

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

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

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

7

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

Пример, который я пытаюсь имитировать, — это 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

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

1