简体   繁体   English

在OpenCL中读取像素RGB值时出现问题

[英]Issue with reading pixel RGB values in OpenCL

I need to read pixels from two parts (with same width and height) of image ( eg squares ([0,0], [300, 300]) and ([400,0], [700,300])) and make difference for each pixel. 我需要从图像的两个部分(具有相同的宽度和高度)(例如,正方形([0,0],[300、300])和([400,0],[700,300]))中读取像素,并对每个像素。

This is C (pseudo)code : 这是C(伪)代码

/**
 * @param img Input image
 * @param pos Integer position of top left corner of the second square (in this case 400)
 */
double getSum(Image& img, int pos)
{
    const int width_of_cut = 300;
    int right_bottom = pos + width;

    Rgb first, second;
    double ret_val = 0.0;

    for(int i=0; i < width_of_cut; i++)
    {
        for(int j=0; j < width_of_cut; j++)
        {
            first  = img.getPixel( i, j );
            second = img.getPixel( i + pos, j );

            ret_val += ( first.R - second.R ) +
                       ( first.G - second.G ) +
                       ( first.B - second.B );
        }
    }

    return ret_val;
}

But my kernel (with same arguments and the __global float* output is set to 0.0 in host code) is giving me completely different values: 但是我的内核 (具有相同的参数,并且在主机代码中将__global float* output设置为0.0)为我提供了完全不同的值:

__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE |
                               CLK_ADDRESS_CLAMP_TO_EDGE |
                               CLK_FILTER_NEAREST;



__kernel void getSum( __read_only image2d_t input,
                        const int x_coord,
                      __global float* output )
{
    int width  = get_image_width( input );
    int height = get_image_height( input );

    int2 pixelcoord = (int2) (get_global_id(0), get_global_id(1)); // image coordinates

    const int width_of_cut = 300; 

    const int right_bottom = x_coord + width_of_cut;

    int a,b;
    a = (int)(pixelcoord.x + x_coord);
    b = pixelcoord.y; 

    if( a < right_bottom && b < width_of_cut )
    {
        float4 first = read_imagef(input, sampler, pixelcoord);
        float4 second = read_imagef(input, sampler, (int2)(a,b));

        output[get_global_id(0)] += ((first.x - second.x) +
                                    (first.y - second.y) +
                                    (first.z - second.z));
    }

}

I am new to OpenCL and I have no idea what am I doing wrong. 我是OpenCL的新手,我不知道自己在做什么错。

Update (1d image): 更新(一维图片):

I changed the kernel code. 我更改了内核代码。 Now I'm reading an 1d image in one loop, but I'm still not getting the correct values. 现在,我正在一个循环中读取一维图像,但是仍然没有获得正确的值。 I'm not sure that I know, how to read pixels from 1d image correctly. 我不确定我是否知道如何正确地从1d图像读取像素。

__kernel void getSum( __read_only image1d_t input,
                        const int x_coord,
                      __global float* output,
                        const int img_width )
{

    const int width_of_cut = 300; 

    int i = (int)(get_global_id(0));

    for(int j=0; j < width_of_cut; j++)
    {
        int f = ( img_width*i + j );
        int s = f + x_coord;

        float4 first = read_imagef( input, sampler, f ); //pixel from 1st sq.
        float4 second = read_imagef( input, sampler, s ); //pixel from 2nd sq.

        output[get_global_id(0)] += ((first.x - second.x) +
                                     (first.y - second.y) +
                                     (first.z - second.z));
    }    
}

Race condition. 比赛条件。

All vertical work items are accessing the same output memory ( output[get_global_id(0)] += ) and not atomically. 所有垂直工作项都访问同一输出内存( output[get_global_id(0)] += ),而不是原子访问。 Therefore the result are likely incorrect (eg, two threads read the same value, add something to it, and write it back. Only one wins). 因此,结果可能不正确(例如,两个线程读取相同的值,向其中添加内容,然后将其写回。只有一个获胜)。

If your device supports it, you could make this an atomic operation, but it would be slow. 如果您的设备支持它,则可以使它成为原子操作,但这会很慢。 You'd be better off running a 1D kernel that has a loop accumulating these vertically (so, the j loop from your C example). 您最好运行一维内核,该内核具有一个垂直累积这些循环的循环(因此,来自C示例的j循环)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM