繁体   English   中英

OpenCL脚本产生意外结果

[英]OpenCL script giving unexpected results

我有这个简单的OpenCL代码块,并且得到了意外的结果。 参数image是一个浮点数数组, value是-255到+255之间的数字。 使用Java我使用JSlider更改value 默认值为0,问题是当我将滑块移动到大于0时图像为黑色,如果将滑块移动到小于0则图像为白色,这是不应该发生的。 应该分别检查每个像素并调整该像素。 似乎不是出于某种原因。

此代码块应更改图像的阈值。 红色,绿色和蓝色大于阈值的任何像素应为白色,否则应为黑色。

kernel void threshold(global float* image, const float value, const int max){
    int index = get_global_id(0);
    if (index >= max){
        return;
    }

    int color = image[index];
    int red = color >> 16 & 0x0FF;
    int green = color >> 8 & 0x0FF;
    int blue = color & 0x0FF;

    if(red > value && green > value && blue > value){
        red = 255;
        green = 255;
        blue = 255;
    }else{
        red = 0;
        green = 0;
        blue = 0;
    }

    int rgba = 255;
    rgba = (rgba << 8) + red;
    rgba = (rgba << 8) + green;
    rgba = (rgba << 8) + blue;

    image[index] = rgba;
}

如果我用以下内容替换中间的if/else语句:

red += value;
if(red > 255){red = 255;}
else if(red < 0){red = 0;}

green += value;
if(green > 255){green = 255;}
else if(green < 0){green = 0;}

blue += value;
if(blue > 255){blue = 255;}
else if(blue < 0){blue = 0;}

获得该操作所需的结果,该结果是调整图像的亮度。

我使用OpenCL错误吗? 据我了解, kernel将一直被调用直到返回成功。 我在Java中使用JOCL来执行此操作,这是我用来调用它的代码:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pocketshop.graphics;

import com.jogamp.common.nio.Buffers;
import com.jogamp.opencl.CLBuffer;
import com.jogamp.opencl.CLCommandQueue;
import com.jogamp.opencl.CLContext;
import com.jogamp.opencl.CLKernel;
import com.jogamp.opencl.CLPlatform;
import com.jogamp.opencl.CLProgram;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.FloatBuffer;
import pocketshop.Canvas;
import pocketshop.dialogs.BrightnessContrastDialog;

/**
 *
 * @author Ryan
 */
public class CL {

    protected static CLBuffer<FloatBuffer> buffer;
    protected static float[] pixels;

    public static CLBuffer<FloatBuffer> getBuffer() {
        return buffer;
    }

    public static float[] getPixels() {
        return pixels;
    }

    public static void start(String script, float val) {

        CLPlatform platform = CLPlatform.getDefault(/*type(CPU)*/);
        CLContext context = CLContext.create(platform.getMaxFlopsDevice());
        try {
            CLProgram program = context.createProgram(getStreamFor("../scripts/" + script + ".cl"));
            program.build(CLProgram.CompilerOptions.FAST_RELAXED_MATH);
            assert program.isExecutable();

            BufferedImage image = Canvas.image;
            assert image.getColorModel().getNumComponents() == 3;

            pixels = image.getRaster().getPixels(0, 0, image.getWidth(), image.getHeight(), (float[]) null);
            FloatBuffer fb = Buffers.newDirectFloatBuffer(pixels);

            // allocate a OpenCL buffer using the direct fb as working copy
            buffer = context.createBuffer(fb, CLBuffer.Mem.READ_WRITE);

            // creade a command queue with benchmarking flag set
            CLCommandQueue queue = context.getDevices()[0].createCommandQueue(CLCommandQueue.Mode.PROFILING_MODE);

            int localWorkSize = queue.getDevice().getMaxWorkGroupSize(); // Local work size dimensions
            int globalWorkSize = roundUp(localWorkSize, fb.capacity());  // rounded up to the nearest multiple of the localWorkSize

            // create kernel and set function parameters
            CLKernel kernel = program.createCLKernel(script.toLowerCase());
            //adjustment(val, queue, kernel, buffer, localWorkSize, globalWorkSize);

            kernel.putArg(buffer).putArg((float) val).putArg(buffer.getNIOSize()).rewind();
            queue.putWriteBuffer(buffer, false);
            queue.put1DRangeKernel(kernel, 0, globalWorkSize, localWorkSize);
            queue.putReadBuffer(buffer, true);

        } catch (IOException e) {
        }
        context.release();
    }

    private static InputStream getStreamFor(String filename) {
        return BrightnessContrastDialog.class.getResourceAsStream(filename);
    }

    private static int roundUp(int groupSize, int globalSize) {
        int r = globalSize % groupSize;
        if (r == 0) {
            return globalSize;
        } else {
            return globalSize + groupSize - r;
        }
    }
}

经过多次试验和错误测试,我发现int color = image[index]; 实际上是红色绿色或蓝色,不是3的整数。

所以,

image[0] = Red;
image[1] = Green;
image[2] = Blue;
image[3] = Red;
image[4] = Green;
image[5] = Blue;

等等

您确定图像是浮点数组吗? 如果是,那么您不应该对其进行整数操作

如果它是每个组件一个字节的rgba,请尝试使用uchar4数据类型,也许更合适,您可以对所有4个组件并行执行向量运算。

也尝试使用opencl的clamp函数来增强范围0..255

暂无
暂无

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

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