【问题标题】:Image grayscale in OpenCLOpenCL 中的图像灰度
【发布时间】:2020-11-08 20:36:54
【问题描述】:

我想将 RGB 图像转换为灰度图像。

当我复制回内核返回零的数据时我的问题。

OpenCL 代码:

__kernel void grayscale(__global  uchar *  input, __global  uchar *  output)
{
    int gid = get_global_id(0);

    output[gid] =  0.0722 * input[gid][0] + 0.7152 * input[gid][1] + 0.2126 * input[gid][2];
}

主机代码:

void RunKernel(char fileName[], char methodName[], Mat inputImg, Mat outputImg, 
                 char outputLoc[], int mem_size){
/*
 Initialisation of the device and read the kernel source.
*/
    //Creating cl_mem objects for input and output. men_size is the image width*height
        imgInMem = clCreateBuffer(img_context, CL_MEM_READ_ONLY,
                                   mem_size * sizeof(uchar), NULL, &err);
        imgOutMem = clCreateBuffer(img_context, CL_MEM_WRITE_ONLY,
                                   mem_size * sizeof(uchar), NULL, &err);
    //copy the data into cl_mem input
        err = clEnqueueWriteBuffer(img_cmd_queue, imgInMem, CL_TRUE, 0, mem_size *sizeof(uchar),
                                    &inputImg.data, 0, NULL, NULL);

    //Create the program and load the kernel source to it
        img_program = clCreateProgramWithSource(img_context, 1, (const char **) &kernel_src_str,
                                                (const size_t *) &kernel_size, &err);

        err = clBuildProgram(img_program, 1, &dev_id, NULL, NULL, NULL);

        img_kernel = clCreateKernel(img_program, methodName, &err);

    //Setting the kernel args
        err = clSetKernelArg(img_kernel, 0, sizeof(cl_mem), (void *) &imgInMem);
        err = clSetKernelArg(img_kernel, 1, sizeof(cl_mem), (void *) &imgOutMem);

    //define the global size and local size
        size_t global_work_size = mem_size;
        size_t local_work_size = 256;

    //Enqueue a command to execute a kernel on a device ("1" indicates 1-dim work)
        err = clEnqueueNDRangeKernel(img_cmd_queue, img_kernel, 1, NULL, &global_work_size, 
                                      &local_work_size, 0, NULL, NULL);

        err = clFinish(img_cmd_queue);

    //Read back the result from device
        err = clEnqueueReadBuffer(img_cmd_queue, imgOutMem, CL_TRUE, 0, 
                                   mem_size *sizeof(uchar), outputImg.data, 0, NULL, NULL);
/*
   Release the necessary objects.
*/
}

clEnqueueReadBuffer 之后,如果我将值写入控制台,则它全为零。我的 outputImg 在main 中是这样声明的:

Mat outImg(height,width,CV_8UC1,Scalar(0));

并用这个调用方法:

RunKernel("kernels/grayscale.cl","grayscale", inImg, outImg,"resources/grayscale_car_gpu.jpg", MEM_SIZE);

【问题讨论】:

    标签: c++ arrays opencl opencl-c++


    【解决方案1】:

    问题可能是您使用的二维数组语法:

    0.0722 * input[gid][0] + 0.7152 * input[gid][1] + 0.2126 * input[gid][2]
    

    您认为具体访问的是哪些地址?

    相反,假设您尝试以 RGB 形式访问顺序字节(按 BGR 顺序,根据系数值判断),请尝试:

    0.0722 * input[3*gid+0] + 0.7152 * input[3*gid+1] + 0.2126 * input[3*gid+2]
    

    您应该在浮点常量中添加一个“f”(否则它们是双精度数,并非所有设备都支持)。

    您应该将浮点数的舍入添加回 uchar。所以,一起,像这样:

    convert_uchar_sat_rte(0.0722f * input[3*gid+0] + 
                          0.7152f * input[3*gid+1] + 
                          0.2126f * input[3*gid+2])
    

    最后,您为输入和输出图像传递了相同大小的缓冲区,但似乎将输入缓冲区视为 RGB,它比单字节单色大 3 倍。所以你需要在宿主代码中修复它。

    每当您从内核得到不正确的输出时,请简化它以查看它是输入问题、计算问题、输出问题还是主机成本问题。继续缩小范围,直到找到问题为止。

    【讨论】:

      猜你喜欢
      • 2014-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 2014-09-15
      • 1970-01-01
      相关资源
      最近更新 更多