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中的“方向”分配之间没有联系 - 但这怎么能实现呢?

+0

你为什么在float4上解包和计算?这些计算在int4中可以正常使用。在调用atan2()和hypot()之前转换为float4。 –

+0

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

+0

对不起,从uchar4到uint4的转换工作,但错误与(f11.r-f13.r + ...)转换为float(其中f11 ,f13是uint4的)。 – Settembrini

outAllocation作为参数传递给内核。但dirAllocation的存在和位置也必须传达给Renderscript方面。刚开始的脚本之前:

script.set_direction(dirAllocation); 

此外,了解memory allocation in Renderscript

+0

奇怪的是,这个内核适用于我的旧版Galaxy Tab2(Android 4.2),但它在我的Galaxs S5(Android 5.0)上崩溃。在后一种情况下,内核被传递,但在复制Allocation(gm和gd)时崩溃。错误信息是:tatal 6385中的致命信号7(SIGBUS),代码2,故障地址0x9e6d4000。任何想法可能是什么问题?我想知道,因为当我昨天使用单独的SobelX/SobelY内核时,几乎相同的copyTo()语句运行良好。 – Settembrini

+0

很难说没有看到更多的代码,但对于初学者来说,检查gm和gd数组的大小是否合适。 –

+0

我会将代码带入一个新的问题,因为这可能会引起其他人的兴趣。 – Settembrini