一个内核中的两个float []输出传递(Sobel - >幅度和方向)

时间:2015-08-09 20:44:28

标签: allocation renderscript

我编写了以下rs代码,以便计算与sobel梯度相同的内核中的大小和方向。

#pragma version(1)
#pragma rs java_package_name(com.example.xxx)
#pragma rs_fp_relaxed

rs_allocation bmpAllocIn, direction;
int32_t width;
int32_t height;

// Sobel, Magnitude und Direction
float __attribute__((kernel)) sobel_XY(uint32_t x, uint32_t y) {
float sobX=0, sobY=0, magn=0;

// leave a border of 1 pixel
if (x>0 && y>0 && x<(width-1) && y<(height-1)){
    uchar4 c11=rsGetElementAt_uchar4(bmpAllocIn, x-1, y-1); uchar4   c12=rsGetElementAt_uchar4(bmpAllocIn, x-1, y);uchar4 c13=rsGetElementAt_uchar4(bmpAllocIn, x-1, y+1);
    uchar4 c21=rsGetElementAt_uchar4(bmpAllocIn, x, y-1);uchar4 c23=rsGetElementAt_uchar4(bmpAllocIn, x, y+1);
    uchar4 c31=rsGetElementAt_uchar4(bmpAllocIn, x+1, y-1);uchar4 c32=rsGetElementAt_uchar4(bmpAllocIn, x+1, y);uchar4 c33=rsGetElementAt_uchar4(bmpAllocIn, x+1, y+1);

    sobX= (float) c11.r-c31.r + 2*(c12.r-c32.r) + c13.r-c33.r;
    sobY= (float) c11.r-c13.r + 2*(c21.r-c23.r) + c31.r-c33.r;

    float d = atan2(sobY, sobX);
    rsSetElementAt_float(direction, d, x, y);
    magn= hypot(sobX, sobY);
}
else{
    magn=0;
    rsSetElementAt_float(direction, 0, x, y);
}
 return magn;
}

Java部分:

float[] gm = new float[width*height]; // gradient magnitude
float[] gd = new float[width*height]; // gradient direction
        ScriptC_sobel script;
        script=new ScriptC_sobel(rs);
        script.set_bmpAllocIn(Allocation.createFromBitmap(rs, bmpGray));

        // dirAllocation: reference to the global variable "direction" in rs script. This
        // dirAllocation is actually the second output of the kernel. It will be "filled" by
        // the rsSetElementAt_float() method that include a reference to the current
        // element (x,y) during the passage of the kernel.
        Type.Builder TypeDir = new Type.Builder(rs, Element.F32(rs));
        TypeDir.setX(width).setY(height);
        Allocation dirAllocation = Allocation.createTyped(rs, TypeDir.create());
        script.set_direction(dirAllocation);

        // outAllocation: the kernel will slide along this global float Variable, which is
        // "formally" the output (in principle the roles of the outAllocation (magnitude) and the
        // second global variable direction (dirAllocation)could have been switched, the kernel
        // just needs at least one in- or out-Allocation to "slide" along.)
        Type.Builder TypeOut = new Type.Builder(rs, Element.F32(rs));
        TypeOut.setX(width).setY(height);
        Allocation outAllocation = Allocation.createTyped(rs, TypeOut.create());
        script.forEach_sobel_XY(outAllocation); //start kernel

        // here comes the problem
        outAllocation.copyTo(gm) ;
        dirAllocation.copyTo(gd);

简而言之:此代码适用于我较旧的Galaxy Tab2(API17),但它会与我的Galaxy S5(API 21)一起造成崩溃(致命信号7(SIGBUS),代码2,故障地址0x9e6d4000)。奇怪的是,当我使用一个更简单的内核,它只是以相同的方式计算SobelX或SobelY渐变(除了第二次分配,这里是方向),它也适用于S5。因此,问题不能是一些兼容性问题。另外,正如我所说的,内核本身没有问题(我可以记录Magnitude和direction值),但它与上面的.copyTo语句相悖。正如您所看到的,gm和gd浮点具有与内核使用的所有其他分配相同的维度(宽度*高度)。知道问题可能是什么吗?或者是否有一种替代的,更强大的方式来完成整个故事?

0 个答案:

没有答案