0

我想将 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);
4

1 回答 1

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 倍。所以你需要在主机代码中修复它。

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

于 2020-11-10T04:49:12.913 回答