RenderScript一个输入和两个输出分配
我设法编写一个内核,将输入位图转换为Sobel渐变(两个独立的SobelX和SobelY内核)的float []。我通过将输入位图分配为全局变量,然后根据输出分配传递内核并通过rsGetElementAt引用输入位图的邻居来完成此操作。因为我实际上想要计算Magnitude(hypot(Sx,Sy))和Direction(atan2(Sy,Sx)),所以在一次Kernel-pass中完成整个事情会很好,如果我只需要计算Magnitude Array ,这可以用相同的结构完成(1 intput Bitmap,1 Output float [])。现在我想知道是否可以为方向输出添加一个额外的分配(也是一个float [])。我试过了用RS-功能rsSetElementAt()如下:RenderScript一个输入和两个输出分配
#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内核的结构逻辑还是因为我不能在Java代码中使用第二个Type.Builder赋值(因为内核已经绑定到Magnitude Output-allocation)。任何帮助,高度赞赏。 PS:我发现第二个Type.Builder赋值和rs中的“方向”分配之间没有联系 - 但这怎么能实现呢?
outAllocation
作为参数传递给内核。但dirAllocation
的存在和位置也必须传达给Renderscript方面。刚开始的脚本之前:
script.set_direction(dirAllocation);
奇怪的是,这个内核适用于我的旧版Galaxy Tab2(Android 4.2),但它在我的Galaxs S5(Android 5.0)上崩溃。在后一种情况下,内核被传递,但在复制Allocation(gm和gd)时崩溃。错误信息是:tatal 6385中的致命信号7(SIGBUS),代码2,故障地址0x9e6d4000。任何想法可能是什么问题?我想知道,因为当我昨天使用单独的SobelX/SobelY内核时,几乎相同的copyTo()语句运行良好。 – Settembrini
很难说没有看到更多的代码,但对于初学者来说,检查gm和gd数组的大小是否合适。 –
我会将代码带入一个新的问题,因为这可能会引起其他人的兴趣。 – Settembrini
你为什么在float4上解包和计算?这些计算在int4中可以正常使用。在调用atan2()和hypot()之前转换为float4。 –
rsunpackColor8888的定义是:“将uchar4颜色解包为float4,生成的浮点数将在0.0和1.0之间(含)。”由于后者,我需要先乘以255,但由于某些原因,它不允许转换为int4或uint4,即 uint4 f11 = convert_uint4(255 * rsUnpackColor8888(c11));和 int4 f11 = convert_int4(255 * rsUnpackColor8888(c11)); 都会产生一个错误:ScriptC sym查找失败convert_float – Settembrini
对不起,从uchar4到uint4的转换工作,但错误与(f11.r-f13.r + ...)转换为float(其中f11 ,f13是uint4的)。 – Settembrini