最後更新 CUDA NPP中值濾波:解決。 WDDM超時也是一個問題。找到了解決方案:WDDM timeout fix。謝謝羅伯特。16個圖像
更新:感謝羅伯特指出,過濾器的中心不是0,0。不幸的是,如果過濾器增加了,那麼您發佈的代碼將會打破我的說法,比如17x17。這可能是由於您沒有考慮圖像「側面」的邊界。在任何情況下,這裏是最當前的代碼,但作爲前仍表現出同樣的問題...
//npp
#include "npp.h"
#include "nppi.h"
#include "device_launch_parameters.h"
#include <iostream>
int main() {
//Image size.
int imageWidth = 6592;
int imageHeight = 4400;
//Misc.
int bytesPerPixel = 2;
int totalPixels = imageWidth*imageHeight;
int filterSize = 17;
int halfFilter = filterSize/2;
cudaError success2;
NppStatus success1;
//Mask & Origin for CUDA.
NppiSize cudaMask;
cudaMask.height = filterSize;
cudaMask.width = filterSize;
NppiPoint cudaAnchor;
cudaAnchor.x = halfFilter;
cudaAnchor.y = halfFilter;
//ROI for CUDA.
int left = halfFilter;
int right = (imageWidth-1) - halfFilter;
int top = halfFilter;
int bot = (imageHeight-1) - halfFilter;
NppiSize cudaROI;
cudaROI.height = bot - top;
cudaROI.width = right - left;
//Step size.
int step = imageWidth * bytesPerPixel;
//Create a new "image".
unsigned short* image = new unsigned short[totalPixels];
for(int i=0; i<imageWidth; i++)
for(int j=0; j<imageHeight; j++)
image[j*imageWidth+i] = 10;
//Allocate mem on device.
Npp16u *dSrc, *dDst;
Npp8u *dBuf;
Npp32u bufferSize;
//This call always returns a bufferSize==0. That doesn't seem right...
success1 = nppiFilterMedianGetBufferSize_16u_C1R(cudaROI, cudaMask, &bufferSize);
std::cout << "get bufferSize returned: " << (int)success1 << std::endl;
std::cout << bufferSize << std::endl;
success2 = cudaMalloc((void**)&dBuf, bufferSize);
std::cout << "cudaMalloc 1 returned: " << (int)success2 << std::endl;
success2 = cudaMalloc((void**)&dSrc, totalPixels*sizeof(Npp16u));
std::cout << "cudaMalloc 2 returned: " << (int)success2 << std::endl;
success2 = cudaMalloc((void**)&dDst, totalPixels*sizeof(Npp16u));
std::cout << "cudaMalloc 3 returned: " << (int)success2 << std::endl;
//Copy host image to device.
success2 = cudaMemcpy(dSrc, image, totalPixels*sizeof(Npp16u), cudaMemcpyHostToDevice);
std::cout << "cudaMemcpy 1 returned: " << (int)success2 << std::endl;
//Copy source to destination.
success1 = nppiCopy_16u_C1R(dSrc, step, dDst, step, cudaROI);
std::cout << "npp Copy 1 returned: " << (int)success1 << std::endl;
//Filter.
Npp32u offset = top*step + left*bytesPerPixel;
success1 = nppiFilterMedian_16u_C1R( dSrc + offset,
step,
dDst + offset,
step,
cudaROI, cudaMask, cudaAnchor, dBuf);
std::cout << "npp Filter returned: " << (int)success1 << std::endl;
//Copy resultant back to host.
success2 = cudaMemcpy(image, dDst, totalPixels*sizeof(Npp16u), cudaMemcpyDeviceToHost);
std::cout << "cudaMemcpy 2 returned: " << (int)success2 << std::endl;
//Clean.
success2 = cudaFree(dDst);
success2 = cudaFree(dBuf);
success2 = cudaFree(dSrc);
delete image;
system("pause");
return 0;
}
我試圖計算的29mp圖像的中值濾波。過濾器大小爲13x13。圖像的寬度和高度如下所示。 對於一個未知的原因,下面的代碼將崩潰,我問,如果有人知道這是爲什麼?
奇怪的事情我已經注意到:與nppiFilterMedian_16u_C1R發生
錯誤()。該函數本身返回一個沒有錯誤的情況,但是下面的cudaMemcpy()會做。沒有過濾器,cudaMemcpy()工作得很好。
此外,爲獲得16位過濾器的緩衝區大小總是返回0大小我測試過8位和32位,它會返回非零值...
我認爲這是可能是NPPI庫中的一個錯誤(?)。 這似乎是大小依賴(如果你使用降低圖像的寬度/高度將功能就好了13×13濾波器尺寸)。但是,我的過濾器尺寸需要增加到31x31。
其他重要信息: 的Windows應用程序64,CUDA 7.5運行時,NPP版本7.5。 GPU設備是Quadro k2200(4GB全球內存)。
請張貼代碼,實際上編譯 –
中值濾波器是不確定的(非法)當面罩外定義的輸入圖像區域。當你設置你的代碼時,這是圖像邊界區域的情況。在[等效英特爾IPP文檔】(http://hpc.ipp.ac.cn/wp-content/uploads/2015/12/documentation_2016/en/ipp/common/ipp_manual/GUID-5D2F9418-E4F6-4F6C-B0F7 -B438CF28EA63.htm)你會注意到它需要減少輸出尺寸,即:「爲了確保在圖像邊界的像素處理有效的操作,應用程序應該正確定義額外的邊界像素」你違反了這個規則 –
羅伯特,我發佈了編譯的代碼。我仍在研究你提到的關於邊界像素的內容。現在,我只是試圖降低投資回報率,以便不需要邊框複製/複製。 –