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);
我想在 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);