2016-04-26 46 views
1

我試圖將黑白圖像作爲輸出與彩色圖像作爲輸入。我正在使用OpenCV來獲取圖像並寫入輸出,並使用CUDA在內核中將圖像變成黑白。我嘗試了相同的代碼,但沒有OpenCV,它運行良好。但是現在輸出與我真正期望得到的稍有不同。CUDA處理圖像時出錯

我認爲CUDA代碼需要修改才能使用OpenCV。我對它做了一些工作,但沒有找到辦法做到這一點。也許有人可以給我一個建議或修改我的代碼嗎?我真的很困惑這個問題。

__global__ void addMatrix(uchar4 *DataIn, unsigned char *DataOut) 
    { 
     int idx = blockIdx.x * blockDim.x + threadIdx.x; 
     DataOut[idx] = (DataIn[idx].x + DataIn[idx].y + DataIn[idx].z)/3; 
    } 

int main() 
{ 
     cudaDeviceProp deviceProp; 
     cudaGetDeviceProperties(&deviceProp, 0); 

     char* c = ""; 
     printf("Input source of image\n Example of right directory file: E:\henrik-evensen-castle-valley-v03.jpg\n Your turn:\n"); 
     char *tbLEN; 
     tbLEN = new char [1024]; 

     cin.getline(tbLEN,1024); 

     cout<< endl << "Your image: " << tbLEN << endl; 

     //Data for input image 
     IplImage* image; 
     image = cvLoadImage(tbLEN, 1); 
     int height = image->height; 
     int width = image->width; 
     int step = image->widthStep; 
     int SizeIn = (step*height); 
     printf("\nProcessing image\n"); 
     //Data for output image 
     IplImage *image2 = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); 
     int step2 = image2->widthStep; 
     int SizeOut = step2 * height; 

     //GPU 
     uchar4* DatIn = (uchar4*)image->imageData; 
     unsigned char* DatOut = (unsigned char*)image2->imageData; 
     uchar4 *datIndev; 
     unsigned char *datOutdev; 

     printf("Allocating memory on Device\n"); 
     /* Allocate memory on Device */ 
     cudaMalloc(&datIndev, SizeIn * sizeof(unsigned char)); 
     cudaMalloc(&datOutdev, SizeOut * sizeof(unsigned char)); 

     printf("Copy data on Device\n"); 
     /* Copy data on Device */ 
     cudaMemcpy(datIndev, DatIn, SizeIn * sizeof(unsigned char), cudaMemcpyHostToDevice); 
     cudaMemcpy(datOutdev, DatOut, SizeOut * sizeof(unsigned char), cudaMemcpyHostToDevice); 

     int NumThreadsX = deviceProp.maxThreadsPerBlock; 
     int NumBlocksX = (width * height)/NumThreadsX; 

     dim3 blocks(NumBlocksX, 1, 1); 
     dim3 threads(NumThreadsX, 1, 1); 
     addMatrix <<< blocks, threads >>> (datIndev, datOutdev); 


     cudaMemcpy(DatOut, datOutdev, SizeOut * sizeof(unsigned char), cudaMemcpyDeviceToHost); 
     cvNamedWindow("Imagecolor"); 
     cvShowImage("Imagecolor", image); 

     cvNamedWindow("Gray"); 
     cvShowImage("Gray", image2); 
     const char* filename1 = "CcPwSwMW4AELPUc.jpg"; 
     printf("Saving an output image\n"); 
     cvSaveImage(filename1, image2); 
     cudaFree(datOutdev); 
     cudaFree(datIndev); 
     cvWaitKey(0); 
     return 0; 
} 

Input

Output

+2

也許你想驗證圖像的實際步驟,使得每個像素有4個通道。乍一看,我會說圖像是每個像素3個字節,因此uchar4不是適當的類型。 –

+0

我很肯定OpenCV只是放棄了alpha通道,所以你的BGR而不是BGRA數據在源圖像 – talonmies

+1

'cvLoadImage'中,標誌1將是** BGR **,所以你有** 3 **通道.. 。如果你想用alpha,它應該是-1(並且圖像必須有alpha)。另外,我只是想知道爲什麼如果你使用'c'函數opencv – api55

回答

3

這裏有幾個問題:

  1. 你的假設,約四通道數據不正確。您的代碼將從文件中將三通道BGR圖像加載到內存中。因此,您需要將參考文件uchar4更改爲uchar,然後讓每個線程從內核中的源映像加載三個字節。

  2. 您的內核本身包含一個潛在的算術錯誤。三個無符號字符像素值的總和可能會溢出一個無符號字符中間結果併產生不正確的平均值。您應該使用更大的類型進行計算。

總之,你的核心應該是這個樣子:

__global__ void addMatrix(unsigned char *DataIn, unsigned char *DataOut) 
{ 
    int idx = blockIdx.x * blockDim.x + threadIdx.x; 
    int b = DataIn[3*idx]; 
    int g = DataIn[3*idx+1]; 
    int r = DataIn[3*idx+2]; 

    DataOut[idx] = (unsigned char)((b + r + g)/3); 
} 

然後,你可能會發現你的形象看起來是正確的。

+0

非常感謝!我現在看到我做錯了什麼,非常感謝你。 – Generwp