2015-08-09 30 views
0

我設法編寫一個內核,將輸入位圖轉換爲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

回答

1

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

相關問題