Библиотека 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}
У меня была такая же проблема, когда я хранил свое ядро как 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};
Фильтр применяет маску, продолжающуюся вверх и влево, в соответствии с математическим соглашением о том, что свертка между двумя функциями меняет направление второй функции.
Маска фильтра коробки простирается вниз и вправо, что, вероятно, более интуитивно понятно.
В любом случае проблема вызвана тем фактом, что входное изображение в измененном коде должно было бы быть выбрано с тем, что фактически было бы ИСТОЧНИКОМ [-4, -4), чтобы вычислить НАЗНАЧЕНИЕ [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
Я думаю, что причина этого заключается в том, что ядро не инициализировано правильно или не используется, поэтому данные с псевдослучайным содержимым используются для ядра.