OpenCL 学习step by step (8) 灰度图Histogram计算(2)
现在我们利用上一篇教程的方法,来统计一副RGBA图像中有多少个像素点(该像素点满足R, G, B, A任意分量>=5)。我考虑的方法是建立256 bin的直方图,对于一个像素,求max(R, G,B,A),用该值决定该像素点进入那个bin,这样求出直方图后,width*height - hostBin[0] - hostBin[1] - hostBin[2] - hostBin[3] - hostBin[4],即为我们要的结果。
本教程代码基本上和上一篇教程中代码是一样的,区别主要包括以下两点:
1、我们装入的是RGBA 彩色图。
//装入图像
unsigned char *src_image=0;
gFreeImage img;
if(!img.LoadImage("../lenna.jpg"))
{
printf("can‘t load lenna.jpg\n");
exit(0);
}
src_image = img.getImageData(width,height);
2、在kernel代码中,有点小变化,kernel代码如下:
#define LINEAR_MEM_ACCESS
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#define BIN_SIZE 256
/**
* 计算直方图,bins是256
* data 输入数据
* 一个workgroup内所有thread共享的内存,
* 每个workgroup的直方图
*/
__kernel
void histogram256(__global const uchar4* data,
__local uchar* sharedArray,
__global uint* binResult)
{
size_t localId = get_local_id(0);
size_t globalId = get_global_id(0);
size_t groupId = get_group_id(0);
size_t groupSize = get_local_size(0);
//初始化共享内存
for(int i = 0; i < BIN_SIZE; ++i)
sharedArray[localId * BIN_SIZE + i] = 0;
barrier(CLK_LOCAL_MEM_FENCE);
uchar R, G, B, A, T;
//计算thread直方图
for(int i = 0; i < BIN_SIZE; ++i)
{
#ifdef LINEAR_MEM_ACCESS
R = (uint)data[groupId * groupSize * BIN_SIZE + i * groupSize + localId].x;
G = (uint)data[groupId * groupSize * BIN_SIZE + i * groupSize + localId].y;
B = (uint)data[groupId * groupSize * BIN_SIZE + i * groupSize + localId].z;
A = (uint)data[groupId * groupSize * BIN_SIZE + i * groupSize + localId].w;
uint value = (uint)max(max(R,G),max(B,A));
#else
uint value = data[globalId * BIN_SIZE + i];
#endif // LINEAR_MEM_ACCESS
sharedArray[localId * BIN_SIZE + value]++;
}
barrier(CLK_LOCAL_MEM_FENCE);
//合并workgroup中所有线程的直方图,产生workgroup直方图
for(int i = 0; i < BIN_SIZE / groupSize; ++i)
{
uint binCount = 0;
for(int j = 0; j < groupSize; ++j)
binCount += sharedArray[j * BIN_SIZE + i * groupSize + localId];
binResult[groupId * BIN_SIZE + i * groupSize + localId] = binCount;
}
}
完整的代码请参考:
工程文件gclTutorial8
代码下载: