Java OpenCL中的灰度图像
我想将RGB图像转换为灰度图像 我的问题是,图像是缩放的,但分辨率保持不变。 这里有一个例子: OpenCL代码似乎是正确的:Java OpenCL中的灰度图像,java,bytearray,opencl,bufferedimage,jocl,Java,Bytearray,Opencl,Bufferedimage,Jocl,我想将RGB图像转换为灰度图像 我的问题是,图像是缩放的,但分辨率保持不变。 这里有一个例子: OpenCL代码似乎是正确的: const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST; __kernel void grayscale
const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE |
CLK_ADDRESS_CLAMP_TO_EDGE |
CLK_FILTER_NEAREST;
__kernel void grayscale(__read_only image2d_t src,
__write_only image2d_t dst)
{
int x = get_global_id(0);
int y = get_global_id(1);
uint4 color;
color = read_imageui(src, sampler, (int2)(x, y));
uint gray = (color.x + color.y + color.z) / 3;
write_imageui(dst, (int2)(x,y), (uint4)(gray, gray, gray, 0));
}
因此,我似乎在对象大小或BuffereImage本身上犯了一个错误
注意:cl类仅用于获取cl COmmandqueue/device/的实例
cl_program prog;
cl_kernel kernel;
String kernelSrc = null;
int[] err = new int[1];
BufferedImage grayimg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
// --------------------
// Get the Sourcecodes
try {
kernelSrc = CLFileLoader.GetSource(KERNEL_GRAYSCALE_PATH);
}
catch(IOException exc) {
System.err.println("Error while loading Kernelfile: " + exc);
}
prog = clCreateProgramWithSource(cl.getContext(), 1, new String[] {kernelSrc}, null, err);
clBuildProgram(prog, 0, null, null, null, err);
kernel = clCreateKernel(prog, "grayscale", err);
if(err[0] != CL_SUCCESS) {
System.err.println("Couldnt create Graykernel");
System.exit(1);
}
byte dataBuffer[] = ((DataBufferByte)img.getRaster().getDataBuffer()).getData();
cl_image_format imageFormat = new cl_image_format();
imageFormat.image_channel_data_type = CL_UNSIGNED_INT8;
imageFormat.image_channel_order = CL_RGBA;
cl_image_format formats[] = new cl_image_format[1];
formats[0] = imageFormat;
cl_mem input = clCreateImage2D(cl.getContext(), CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, formats, img.getWidth(),
img.getHeight(), 0, Pointer.to(dataBuffer), err);
cl_mem output = clCreateImage2D(cl.getContext(), CL_MEM_WRITE_ONLY, formats, img.getWidth(),
img.getHeight(), 0, null, err);
if(err[0] != CL_SUCCESS) {
System.err.println("Couldnt create objects");
System.exit(1);
}
// Set Args
clSetKernelArg(kernel, 0, Sizeof.cl_mem, Pointer.to(input));
clSetKernelArg(kernel, 1, Sizeof.cl_mem, Pointer.to(output));
// Transfer Image to the OpenCL-Device
if(clEnqueueWriteImage(cl.getCommandQueue(), input, CL_TRUE,
new long[] {0,0,0}, new long [] {img.getWidth(), img.getHeight(), 1},
img.getWidth(), 0, Pointer.to(dataBuffer), 0, null, null) != CL_SUCCESS) {
System.err.println("Cant write Image");
System.exit(1);
}
long workSize[] = new long[] {img.getWidth(), img.getHeight()};
long workSizelocal[] = new long[] {2,2};
if(clEnqueueNDRangeKernel(cl.getCommandQueue(), kernel, 2, null,
workSize, workSizelocal, 0, null, null) != CL_SUCCESS) {
System.err.println("Cant apply Blackwhite-kernel");
System.exit(1);
}
byte grayimg_byte[] = ((DataBufferByte)grayimg.getRaster().getDataBuffer()).getData();
if(clEnqueueReadImage(cl.getCommandQueue(), output, CL_TRUE, new long[] {0,0,0},
new long[] {img.getWidth(), img.getHeight(), 1}, img.getWidth(), 0, Pointer.to(grayimg_byte), 0, null, null) != CL_SUCCESS) {
System.err.println("Cant read values from Blackwhite-kernel");
System.exit(1);
}
clReleaseMemObject(input);
clReleaseMemObject(output);
return grayimg;
致以最诚挚的问候我一点也不知道OpenCL,但您是否可以在这里只写一个灰度值而不是三个
write_imageui(dst, (int2)(x,y), (uint4)(gray, gray, gray, 0));
我想把它去掉,格雷,格雷。我认为这是因为您使用CL_UNSIGNED_INT8作为类型,但您正在编写一个无符号32位int
顺便说一句,还有其他从RGB计算灰度值的方法,请参阅,如果使用,您可能会得到比仅平均R+G+B更好的结果
Gray = 0.21 R + 0.72 G + 0.07 B
write_imageui函数需要一个int4作为3。参数Thx关于亮度方法的信息。CL_UNSIGNED_INT8表示每个通道8位。我认为函数调用是可以的,当复制发生时,问题可能在OpenCL之外。RGB是原始颜色空间吗?如果原件是YCbCr e。GJPEG图像,比工作已经完成-只要拉原始Y平面。我想你是复制一个其他格式的图像UINT32,这就是为什么你只有1/4时,处理它。它不会崩溃,因为您给出了指向OpenCLAPI的指针,并且只占用了必要的部分。您可以发布结果的图像吗?你说它被放大了?我在上面贴了两张图片的链接。加载的映像为3字节\u BGR