2015-08-09 2 views
0

Мне удалось написать Ядро, которое преобразует бит-бит ввода в поплавок [] градиентов Sobel (два отдельных ядра для SobelX и SobelY). Я сделал это, назначив входной битмап как глобальную переменную, а затем передав ядро ​​на основе выделения Output и ссылаясь на соседей Input-Bitmap через rsGetElementAt. Поскольку я на самом деле хочу вычислить Magnitude (hypot (Sx, Sy) и направление (atan2 (Sy, Sx)), было бы неплохо сделать все это в одном проходе ядра. Если бы мне пришлось вычислять Массив Массив , это можно сделать с той же структурой (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-ядра или это потому, что я не могу использовать второе назначение Type.Builder в Java-коде (потому что ядро ​​уже привязано к выделению по размеру). Любая помощь высоко ценится. PS: Я вижу, что нет никакой связи между вторым назначением Type.Builder и «direction» allocaton в rs - но как это можно достичь?

+0

Почему вы распаковываете и вычисляете на float4? Эти вычисления будут хорошими с int4. Просто перейдите в float4 прямо перед вызовом atan2() и hypot(). –

+0

Определение rsunpackColor8888: «Распакует цвет uchar4 для float 4. Результирующие поплавки будут находиться между 0.0 и 1.0 включительно». Из-за последнего мне нужно было бы сначала умножить на 255, но по какой-то причине он не позволяет преобразовать в int4 или uint4, то есть uint4 f11 = convert_uint4 (255 * rsUnpackColor8888 (c11)); и int4 f11 = convert_int4 (255 * rsUnpackColor8888 (c11)); Создайте справку: ScriptC sym lookup не удалось для 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), но оно падает на моем Galax S5 (Android 5.0). В последнем случае ядро ​​передается, но он сбой при копировании Allocation (в gm и gd). Сообщение об ошибке ist: Fatal signal 7 (SIGBUS), код 2, ошибка addr 0x9e6d4000 in tid 6385. Есть идеи, что может быть проблемой? Интересно, потому что практически те же самые операторы copyTo() работали хорошо, когда вчера я использовал отдельные ядра SobelX/SobelY. – Settembrini

+0

Трудно сказать, не видя больше вашего кода, но для начинающих проверьте, подходят ли массивы gm и gd нужного размера. –

+0

Я приведу код в новый вопрос, так как это может представлять интерес и для других. – Settembrini

Смежные вопросы