RenderScript Sobel 实现,不同的输入和输出类型

RenderScript Sobel lmplementation, different in- and output types

我想在 RenderScript 中实现一个 Sobel 过滤器,其中 uchar4 作为输入分配,float[] 作为输出分配。我不太确定是否可以在 RenderScript 中使用不同类型的输入和输出分配。我想自己开发解决方案,但如果能得到一些关于解决该问题的最佳 Renderscript 结构的建议,我将不胜感激。我在某处读到,可以使用

float attribute((kernel)) root(uchar4 *v_in, uint32_t x, uint32_t y) { }

您会推荐这种方法吗?或者这是否可以在不实际使用内核(即仅使用一个函数)的情况下完成?提前致谢。

我的 Sobel(X 方向)的 rs 代码现在如下所示:

#pragma version(1)
#pragma rs java_package_name(com.example.xxx)
#pragma rs_fp_relaxed

rs_allocation gIn;
int32_t width;
int32_t height;

float __attribute__((kernel)) sobelX(uchar4 *v_in, uint32_t x, uint32_t y)    {
float out=0;

 if (x>0 && y>0 && x<(width-1) && y<(height-1){
uchar4 c11=rsGetElementAt_uchar4(gIn, x-1, y-1);
uchar4 c21=rsGetElementAt_uchar4(gIn, x, y-1);
uchar4 c31=rsGetElementAt_uchar4(gIn, x+1, y-1);
uchar4 c13=rsGetElementAt_uchar4(gIn, x-1, y+1);
uchar4 c23=rsGetElementAt_uchar4(gIn, x, y+1);
uchar4 c33=rsGetElementAt_uchar4(gIn, x+1, y+1);

float4 f11=convert_float4(c11);
float4 f21=convert_float4(c21);
float4 f31=convert_float4(c31);
float4 f13=convert_float4(c13);
float4 f23=convert_float4(c23);
float4 f33=convert_float4(c33);

out= f11.r-f13.r + 2*(f21.r-f23.r) + f31.r-f33.r;
}

return out;
}

我正在努力从 Java 端传递参数:

        float[][] gx = new float[width][height];
        ScriptC_sobel script;
        script=new ScriptC_sobel(rs);

        script.set_width(width) ;
        script.set_height(height) ;
        script.set_gIn(bmpGray);

        Allocation inAllocation = Allocation.createFromBitmap(rs, bmpGray, Allocation.MipmapControl.MIPMAP_NONE,
                Allocation.USAGE_SCRIPT);
        Allocation outAllocation = Allocation.createTyped(rs, float,2) ;

        script.forEach_sobelX(inAllocation, outAllocation);
        outAllocation.copyTo(gx) ;

我知道,为了使用 rsGetElementAt 函数(访问内核中的相邻数据),我还需要将输入分配设置为全局脚本(rs_allocation gIn in rs 代码)。但是,我不确定如何从 Java 端处理此 "double allocation"。 Java 代码中的 outAllocation 语句也可能不正确。具体来说,我不确定内核是否会将其作为 float[] 或 float[][] 返回。

输入和输出可以使用不同的类型。在你的情况下,我实际上建议:

float __attribute__((kernel)) sobel(unchar4 *v_in, uint32_t x, uint32_t y) {}

您当然想使用内核,这样性能可以受益于多线程执行。

另外,看看这个 example of doing 3x3 convolution in RS

更新: 通常,要使用的最佳 in/out 参数取决于您希望此过滤器生成的输出类型 - 仅仅是幅度吗?然后 uint 输出很可能就足够了。

UPDATE2: 如果你打算使用一个变量来传递输入分配,那么你不需要在内核参数中使用它,即:

float __attribute__((kernel)) sobelX(uint32_t x, uint32_t y)

脚本的其余部分看起来没问题(条件中没有缺少括号)。至于 Java 部分,下面我贴一个演示,说明你应该如何准备输出分配和启动脚本。然后将为输出分配中的每个单元格(即每个浮点数)调用内核。

            float[] gx = new float[width * height];
            Type.Builder TypeIn = new Type.Builder(mRS, Element.F32(mRS));
            TypeIn.setX(width).setY(height);

            Allocation outAllocation = Allocation.createTyped(mRS, TypeIn.create());

            mScript.forEach_sobelX(outAllocation);