OpenCL: Blur image with Gaussian filter, 高斯模糊
OpenCL: Blur image with Gaussian filter, Gaussian blur
我计算了 n = 5 的高斯滤波器掩码 nxn。看起来像这样:
int gauss5[] = {
1, 4, 7, 4, 1,
4, 20, 33, 20, 4,
7, 33, 55, 33, 7,
4, 20, 33, 20, 4,
1, 4, 7, 4, 1
};
int gauss5_summ = 331;
在opencl中计算后图像变暗。是什么原因?
size_t global_wblur[2];
size_t local_wblur[2];
global_wblur[0] = h;
global_wblur[1] = w;
local_wblur[0] = local_wblur[1] = 32;
err = clEnqueueNDRangeKernel(queue, cl_img_gaussian_blur, 2, NULL, global_wblur, local_wblur, 0, NULL, NULL);
if (err != CL_SUCCESS) {
fprintf(stderr, "error: clEnqueueNDRangeKernel() blur %d %s\n", err, cl_strerror(err));
exit(EXIT_FAILURE);
}
内核源代码:
__kernel void cl_img_gaussian_blur(__global const uchar *gray, __global uchar *out, __global const uchar *gbox, uint n, uint sum, uint w, uint h)
{
int i, j, offset;
uint x, y, summ;
y = get_global_id(0);
x = get_global_id(1);
offset = n/2;
/* ignore border pixels
*/
if (y - offset < 0 || y + offset > h || x - offset < 0 || x + offset > w) {
out[y*w + x] = gray[y*w + x];
return;
}
summ = 0;
for (j = -offset; j <= offset; j++) {
for (i = -offset; i <= offset; i++) {
summ += gray[(y + j)*w + x + i]*gbox[(j + offset)*n + i + offset];
}
}
out[y*w + x] = summ/sum;
}
模糊图像:
深色(opencl) -- https://github.com/apetrunev/imgalg-opencl/blob/master/dark.png
正常 -- https://github.com/apetrunev/imgalg-opencl/blob/master/test-blur/out.png
你说 gbox 数据初始化如下:
clEnqueueWriteBuffer(queue, gauss_buf, CL_FALSE, 0, 5*5, gauss5, 0, NULL, NULL);
这是错误的,因为您正在复制实际内存量的 1/4。正确的方法是:
clEnqueueWriteBuffer(queue, gauss_buf, CL_FALSE, 0, 5*5*sizeof(cl_int), gauss5, 0, NULL, NULL);
否则,其余为0,导致输出值偏低。
我计算了 n = 5 的高斯滤波器掩码 nxn。看起来像这样:
int gauss5[] = {
1, 4, 7, 4, 1,
4, 20, 33, 20, 4,
7, 33, 55, 33, 7,
4, 20, 33, 20, 4,
1, 4, 7, 4, 1
};
int gauss5_summ = 331;
在opencl中计算后图像变暗。是什么原因?
size_t global_wblur[2];
size_t local_wblur[2];
global_wblur[0] = h;
global_wblur[1] = w;
local_wblur[0] = local_wblur[1] = 32;
err = clEnqueueNDRangeKernel(queue, cl_img_gaussian_blur, 2, NULL, global_wblur, local_wblur, 0, NULL, NULL);
if (err != CL_SUCCESS) {
fprintf(stderr, "error: clEnqueueNDRangeKernel() blur %d %s\n", err, cl_strerror(err));
exit(EXIT_FAILURE);
}
内核源代码:
__kernel void cl_img_gaussian_blur(__global const uchar *gray, __global uchar *out, __global const uchar *gbox, uint n, uint sum, uint w, uint h)
{
int i, j, offset;
uint x, y, summ;
y = get_global_id(0);
x = get_global_id(1);
offset = n/2;
/* ignore border pixels
*/
if (y - offset < 0 || y + offset > h || x - offset < 0 || x + offset > w) {
out[y*w + x] = gray[y*w + x];
return;
}
summ = 0;
for (j = -offset; j <= offset; j++) {
for (i = -offset; i <= offset; i++) {
summ += gray[(y + j)*w + x + i]*gbox[(j + offset)*n + i + offset];
}
}
out[y*w + x] = summ/sum;
}
模糊图像:
深色(opencl) -- https://github.com/apetrunev/imgalg-opencl/blob/master/dark.png
正常 -- https://github.com/apetrunev/imgalg-opencl/blob/master/test-blur/out.png
你说 gbox 数据初始化如下:
clEnqueueWriteBuffer(queue, gauss_buf, CL_FALSE, 0, 5*5, gauss5, 0, NULL, NULL);
这是错误的,因为您正在复制实际内存量的 1/4。正确的方法是:
clEnqueueWriteBuffer(queue, gauss_buf, CL_FALSE, 0, 5*5*sizeof(cl_int), gauss5, 0, NULL, NULL);
否则,其余为0,导致输出值偏低。