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

时间:2015-08-07 18:24:49

标签: renderscript imagefilter sobel

我想在RenderScript中实现一个Sobel滤镜,uchar4作为输入分配,float []作为输出分配。我不太确定是否可以在RenderScript中使用不同类型的输入和输出分配。我想自己开发解决方案,但是希望得到一些关于最好的Renderscript结构的建议来解决这个问题。我读到的地方,可以使用

float 属性((内核))root(uchar4 * v_in,uint32_t x,uint32_t y){ }

你会推荐这样的方法,还是可以在不使用实际内核的情况下完成,即只是一个函数?提前谢谢。

Sobel(X方向)的我的代码现在看起来如下:

#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代码中的rs_allocation gIn)。但是,我不确定如何从Java端处理这种“双重分配”。此外,Java代码中的outAllocation语句可能不正确。具体而言,我不确定,内核是否会将其作为float []或float [] []返回。

1 个答案:

答案 0 :(得分:1)

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

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

您当然希望使用内核,以便多线程执行可以提高性能。

另外,请查看此example of doing 3x3 convolution in RS

UPDATE:通常,要使用的最佳输入/输出参数取决于您希望此过滤器生成的输出类型 - 它只是幅度吗?然后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);