使用CUDA并行处理将彩色图像转换为灰度图像

时间:2013-02-05 16:02:00

标签: image-processing cuda parallel-processing gpu

我正在尝试解决我应该将彩色图像更改为灰度图像的问题。为此我使用CUDA并行方法。

我在GPU上调用的kerne代码如下。

__global__
void rgba_to_greyscale(const uchar4* const rgbaImage,
                   unsigned char* const greyImage,
                   int numRows, int numCols)
{
    int absolute_image_position_x = blockIdx.x;  
    int absolute_image_position_y = blockIdx.y;

  if ( absolute_image_position_x >= numCols ||
   absolute_image_position_y >= numRows )
 {
     return;
 }
uchar4 rgba = rgbaImage[absolute_image_position_x + absolute_image_position_y];
float channelSum = .299f * rgba.x + .587f * rgba.y + .114f * rgba.z;
greyImage[absolute_image_position_x + absolute_image_position_y] = channelSum;

}

void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage,
                            uchar4 * const d_rgbaImage,
                            unsigned char* const d_greyImage,
                            size_t numRows,
                            size_t numCols)
{
  //You must fill in the correct sizes for the blockSize and gridSize
  //currently only one block with one thread is being launched
  const dim3 blockSize(numCols/32, numCols/32 , 1);  //TODO
  const dim3 gridSize(numRows/12, numRows/12 , 1);  //TODO
  rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage,
                                             d_greyImage,
                                             numRows,
                                             numCols);

  cudaDeviceSynchronize(); checkCudaErrors(cudaGetLastError());
}

我在第一个像素行中看到一行点。

我得到的错误是

        libdc1394错误:无法初始化libdc1394
        位置51的差异超过5的容差         参考:255
        GPU:0
my input/output images 谁能帮我这个???提前谢谢。

12 个答案:

答案 0 :(得分:5)

现在,因为我发布了这个问题,所以我一直在努力解决这个问题。为了使这个问题正确,我应该做一些改进,现在我意识到我的初步解决方案是错误的。 />要做的更改: -

 1. absolute_position_x =(blockIdx.x * blockDim.x) + threadIdx.x;
 2. absolute_position_y = (blockIdx.y * blockDim.y) + threadIdx.y;

其次,

 1. const dim3 blockSize(24, 24, 1);
 2. const dim3 gridSize((numCols/16), (numRows/16) , 1);

在解决方案中,我们使用的是numCols / 16 * numCols / 16的网格 和24 * 24的块大小

代码以0.040576 ms执行

@datenwolf:谢谢你回答上面的问题!!!

答案 1 :(得分:5)

我最近加入了这个课程并尝试了你的解决方案,但它不起作用,我尝试了自己的。你几乎是对的。正确的解决方案是:

__global__`
void rgba_to_greyscale(const uchar4* const rgbaImage,
               unsigned char* const greyImage,
               int numRows, int numCols)
{`

int pos_x = (blockIdx.x * blockDim.x) + threadIdx.x;
int pos_y = (blockIdx.y * blockDim.y) + threadIdx.y;
if(pos_x >= numCols || pos_y >= numRows)
    return;

uchar4 rgba = rgbaImage[pos_x + pos_y * numCols];
greyImage[pos_x + pos_y * numCols] = (.299f * rgba.x + .587f * rgba.y + .114f * rgba.z); 

}

其余部分与您的代码相同。

答案 2 :(得分:2)

由于您不了解图像尺寸。最好选择二维螺纹块的任何合理尺寸,然后检查两个条件。第一个是内核中的pos_xpos_y索引不超过numRowsnumCols。其次,网格大小应该高于所有块中的线程总数。

const dim3 blockSize(16, 16, 1);
const dim3 gridSize((numCols%16) ? numCols/16+1 : numCols/16,
(numRows%16) ? numRows/16+1 : numRows/16, 1);

答案 3 :(得分:1)

  

libdc1394错误:无法初始化libdc1394

我不认为这是一个CUDA问题。 libdc1394是一个用于访问IEEE1394又名FireWire又名iLink视频设备(DV摄像机,Apple iSight摄像机)的库。该库没有正确初始化,因此您没有获得有用的结果。基本上它是NINO:Nonsens In Nonsens Out。

答案 4 :(得分:1)

绝对x&amp;的计算y图像位置是完美的。 但是当你需要访问彩色图像中的特定像素时,你不应该使用下面的代码吗?

uchar4 rgba = rgbaImage[absolute_image_position_x + (absolute_image_position_y * numCols)];

我这么认为,将它与你编写的代码进行比较,以便在串行代码中执行相同的问题。 请让我知道:))

答案 5 :(得分:1)

您仍然应该遇到运行时问题 - 转换无法提供正确的结果。

行:

  1. uchar4 rgba = rgbaImage [absolute_image_position_x + absolute_image_position_y];
  2. greyImage [absolute_image_position_x + absolute_image_position_y] = channelSum;
  3. 应更改为:

    1. uchar4 rgba = rgbaImage [absolute_image_position_x + absolute_image_position_y * numCols];
    2. greyImage [absolute_image_position_x + absolute_image_position_y * numCols] = channelSum;

答案 6 :(得分:1)

__global__
void rgba_to_greyscale(const uchar4* const rgbaImage,
                       unsigned char* const greyImage,
                       int numRows, int numCols)
{
    int rgba_x = blockIdx.x * blockDim.x + threadIdx.x;
    int rgba_y = blockIdx.y * blockDim.y + threadIdx.y;
    int pixel_pos = rgba_x+rgba_y*numCols;

    uchar4 rgba = rgbaImage[pixel_pos];
    unsigned char gray = (unsigned char)(0.299f * rgba.x + 0.587f * rgba.y + 0.114f * rgba.z);
    greyImage[pixel_pos] = gray;
}

void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage, uchar4 * const d_rgbaImage,
                            unsigned char* const d_greyImage, size_t numRows, size_t numCols)
{
    //You must fill in the correct sizes for the blockSize and gridSize
    //currently only one block with one thread is being launched
    const dim3 blockSize(24, 24, 1);  //TODO
    const dim3 gridSize( numCols/24+1, numRows/24+1, 1);  //TODO
    rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage, numRows, numCols);

    cudaDeviceSynchronize(); checkCudaErrors(cudaGetLastError());
}

答案 7 :(得分:1)

在这种情况下,libdc1394错误与firewire等无关 - 它是udacity用于比较程序创建的图像与参考图像的库。而且说的是,你的图像和参考图像之间的差异已超过特定阈值,即该位置即。像素。

答案 8 :(得分:0)

您正在运行以下数量的块和网格:

  const dim3 blockSize(numCols/32, numCols/32 , 1);  //TODO
  const dim3 gridSize(numRows/12, numRows/12 , 1);  //TODO

但你没有在你的内核代码中使用任何线程!

 int absolute_image_position_x = blockIdx.x;  
 int absolute_image_position_y = blockIdx.y;

这样想,图像的宽度可以划分为列的absolute_image_position_x部分,图像的高度可以划分为行的absolute_image_position_y部分。现在,它创建的每个横截面的框都需要根据greyImage平行地更改/重绘所有像素。足够的作品扰乱:)

答案 9 :(得分:0)

能够处理非标准输入尺寸图像的相同代码

int idx=blockDim.x*blockIdx.x+threadIdx.x;
int idy=blockDim.y*blockIdx.y+threadIdx.y;

uchar4 rgbcell=rgbaImage[idx*numCols+idy];

   greyImage[idx*numCols+idy]=0.299*rgbcell.x+0.587*rgbcell.y+0.114*rgbcell.z;


  }

  void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage, uchar4 * const d_rgbaImage,
                        unsigned char* const d_greyImage, size_t numRows, size_t numCols)
 {
 //You must fill in the correct sizes for the blockSize and gridSize
 //currently only one block with one thread is being launched

int totalpixels=numRows*numCols;
int factors[]={2,4,8,16,24,32};
vector<int> numbers(factors,factors+sizeof(factors)/sizeof(int));
int factor=1;

   while(!numbers.empty())
  {
 if(totalpixels%numbers.back()==0)
 {
     factor=numbers.back();
     break;
 }
   else
   {
  numbers.pop_back();
   }
 }



 const dim3 blockSize(factor, factor, 1);  //TODO
 const dim3 gridSize(numRows/factor+1, numCols/factor+1,1);  //TODO
 rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage,    numRows, numCols);

答案 10 :(得分:0)

1- int y = (blockIdx.y * blockDim.y) + threadIdx.y;

2- const dim3 blockSize(32, 32, 1);

以网格和块大小

1- const dim3 gridSize((numCols/32+1), (numRows/32+1) , 1);

2- Id Name Marks 1 A 34 2 b 35

代码以0.036992 ms执行。

答案 11 :(得分:0)

const dim3 blockSize(16, 16, 1);  //TODO
const dim3 gridSize( (numRows+15)/16, (numCols+15)/16, 1);  //TODO

int x = blockIdx.x * blockDim.x + threadIdx.x;  
int y = blockIdx.y * blockDim.y + threadIdx.y;

uchar4 rgba = rgbaImage[y*numRows + x];
float channelSum = .299f * rgba.x + .587f * rgba.y + .114f * rgba.z;
greyImage[y*numRows + x] = channelSum;