RenderScript 一个输入和两个输出分配
RenderScript one input- and two output-Allocations
我设法编写了一个内核,将输入位图转换为 Sobel 梯度的 float[](SobelX 和 SobelY 的两个独立内核)。为此,我将输入位图分配为全局变量,然后根据输出分配传递内核并通过 rsGetElementAt 引用输入位图的邻居。因为我实际上想计算幅度 (hypot(Sx,Sy) 和方向 (atan2(Sy,Sx)),所以在一次内核传递中完成所有事情会很好。如果我只需要计算幅度数组,这可以用相同的结构(1 intput Bitmap,1 Output float [])来完成。现在我想知道,是否可以为方向输出添加一个额外的分配(也是一个 float [])。我试过这个使用 rs 函数 rsSetElementAt() 如下:
#pragma version(1)
#pragma rs java_package_name(com.example.xxx)
#pragma rs_fp_relaxed
rs_allocation gIn, direction;
int32_t width;
int32_t height;
// Sobel, Magnitude und Direction
float __attribute__((kernel)) sobel_XY(uint32_t x, uint32_t y) {
float outX=0, outY=0;
if (x>0 && y>0 && x<(width-1) && y<(height-1)){
uchar4 c11=rsGetElementAt_uchar4(gIn, x-1, y-1); uchar4 c12=rsGetElementAt_uchar4(gIn, x-1, y);uchar4 c13=rsGetElementAt_uchar4(gIn, x-1, y+1);
uchar4 c21=rsGetElementAt_uchar4(gIn, x, y-1);uchar4 c23=rsGetElementAt_uchar4(gIn, x, y+1);
uchar4 c31=rsGetElementAt_uchar4(gIn, x+1, y-1);uchar4 c32=rsGetElementAt_uchar4(gIn, x+1, y);uchar4 c33=rsGetElementAt_uchar4(gIn, x+1, y+1);
float4 f11=rsUnpackColor8888(c11);float4 f12=rsUnpackColor8888(c12);float4 f13=rsUnpackColor8888(c13);
float4 f21=rsUnpackColor8888(c21); float4 f23=rsUnpackColor8888(c23);
float4 f31=rsUnpackColor8888(c31);float4 f32=rsUnpackColor8888(c32);float4 f33=rsUnpackColor8888(c33);
outX= f11.r-f31.r + 2*(f12.r-f32.r) + f13.r-f33.r;
outY= f11.r-f13.r + 2*(f21.r-f23.r) + f31.r-f33.r;
float d = atan2(outY, outX);
rsSetElementAt_float(direction, d, x, y);
return hypot(outX, outY);
}
}
和对应的Java代码:
ScriptC_sobel script;
script=new ScriptC_sobel(rs);
script.set_gIn(Allocation.createFromBitmap(rs, bmpGray));
Type.Builder TypeOut = new Type.Builder(rs, Element.F32(rs));
TypeOut.setX(width).setY(height);
Allocation outAllocation = Allocation.createTyped(rs, TypeOut.create());
// the following 3 lines shall reflect the allocation to the Direction output
Type.Builder TypeDir = new Type.Builder(rs, Element.F32(rs));
TypeDir.setX(width).setY(height);
Allocation dirAllocation = Allocation.createTyped(rs, TypeDir.create());
script.forEach_sobel_XY(outAllocation);
outAllocation.copyTo(gm) ;
dirAllocation.copyTo(gd);
不幸的是,这不起作用。我不确定,问题是出在 rs-kernel 的结构逻辑上,还是因为我不能在 Java 代码中使用第二个 Type.Builder 赋值(因为内核已经绑定到幅度输出分配)。非常感谢任何帮助。
PS:我看到在 rs 中第二个 Type.Builder 分配和 "direction" 分配之间没有 link - 但如何实现?
outAllocation
作为参数传递给内核。但是 dirAllocation
的存在和位置也必须传达给 Renderscript 端。在启动脚本之前执行此操作:
script.set_direction(dirAllocation);
我设法编写了一个内核,将输入位图转换为 Sobel 梯度的 float[](SobelX 和 SobelY 的两个独立内核)。为此,我将输入位图分配为全局变量,然后根据输出分配传递内核并通过 rsGetElementAt 引用输入位图的邻居。因为我实际上想计算幅度 (hypot(Sx,Sy) 和方向 (atan2(Sy,Sx)),所以在一次内核传递中完成所有事情会很好。如果我只需要计算幅度数组,这可以用相同的结构(1 intput Bitmap,1 Output float [])来完成。现在我想知道,是否可以为方向输出添加一个额外的分配(也是一个 float [])。我试过这个使用 rs 函数 rsSetElementAt() 如下:
#pragma version(1)
#pragma rs java_package_name(com.example.xxx)
#pragma rs_fp_relaxed
rs_allocation gIn, direction;
int32_t width;
int32_t height;
// Sobel, Magnitude und Direction
float __attribute__((kernel)) sobel_XY(uint32_t x, uint32_t y) {
float outX=0, outY=0;
if (x>0 && y>0 && x<(width-1) && y<(height-1)){
uchar4 c11=rsGetElementAt_uchar4(gIn, x-1, y-1); uchar4 c12=rsGetElementAt_uchar4(gIn, x-1, y);uchar4 c13=rsGetElementAt_uchar4(gIn, x-1, y+1);
uchar4 c21=rsGetElementAt_uchar4(gIn, x, y-1);uchar4 c23=rsGetElementAt_uchar4(gIn, x, y+1);
uchar4 c31=rsGetElementAt_uchar4(gIn, x+1, y-1);uchar4 c32=rsGetElementAt_uchar4(gIn, x+1, y);uchar4 c33=rsGetElementAt_uchar4(gIn, x+1, y+1);
float4 f11=rsUnpackColor8888(c11);float4 f12=rsUnpackColor8888(c12);float4 f13=rsUnpackColor8888(c13);
float4 f21=rsUnpackColor8888(c21); float4 f23=rsUnpackColor8888(c23);
float4 f31=rsUnpackColor8888(c31);float4 f32=rsUnpackColor8888(c32);float4 f33=rsUnpackColor8888(c33);
outX= f11.r-f31.r + 2*(f12.r-f32.r) + f13.r-f33.r;
outY= f11.r-f13.r + 2*(f21.r-f23.r) + f31.r-f33.r;
float d = atan2(outY, outX);
rsSetElementAt_float(direction, d, x, y);
return hypot(outX, outY);
}
}
和对应的Java代码:
ScriptC_sobel script;
script=new ScriptC_sobel(rs);
script.set_gIn(Allocation.createFromBitmap(rs, bmpGray));
Type.Builder TypeOut = new Type.Builder(rs, Element.F32(rs));
TypeOut.setX(width).setY(height);
Allocation outAllocation = Allocation.createTyped(rs, TypeOut.create());
// the following 3 lines shall reflect the allocation to the Direction output
Type.Builder TypeDir = new Type.Builder(rs, Element.F32(rs));
TypeDir.setX(width).setY(height);
Allocation dirAllocation = Allocation.createTyped(rs, TypeDir.create());
script.forEach_sobel_XY(outAllocation);
outAllocation.copyTo(gm) ;
dirAllocation.copyTo(gd);
不幸的是,这不起作用。我不确定,问题是出在 rs-kernel 的结构逻辑上,还是因为我不能在 Java 代码中使用第二个 Type.Builder 赋值(因为内核已经绑定到幅度输出分配)。非常感谢任何帮助。 PS:我看到在 rs 中第二个 Type.Builder 分配和 "direction" 分配之间没有 link - 但如何实现?
outAllocation
作为参数传递给内核。但是 dirAllocation
的存在和位置也必须传达给 Renderscript 端。在启动脚本之前执行此操作:
script.set_direction(dirAllocation);