2015-08-02 2 views
1

У меня нет проблем с применением функции ScriptIntrinsicConvolve3x3 (или 5x5) для распределений входов и выходов, являющихся как U8_4. Но если я хочу применить свертку к фильтру градиента, например Sobel, мне нужен вывод типа float (а не U8_4), потому что мне нужно учитывать также выходные значения NEGATIVE. Этот вопрос был поднят здесь уже 18 месяцев назад, но пока не был дан ответ. Любая помощь высоко ценится.ScriptIntrincisConvolve3x3: Вывод-распределение float4 вместо U8_4?

Android RenderScript copy allocation in rs file

+0

Просто уточнить: вам нужно отдельно сохранить Gx и Gy выход из фильтра Sobel, или вы планируете объединить их для получения величины отрицательного градиента? Если последнее имеет место, вам временно нужны отрицательные значения. Будет намного быстрее иметь собственный скрипт, который вычисляет как свертки Gx, так и Gy за один проход и сохраняет комбинированный результат в U8_4. –

+0

Miloslaw, хороший пункт. Действительно, было бы здорово получить массив амплитуд плюс массив направлений в одном проходе Renderscript. Я не хочу быть жалким, но, к сожалению, после трех недель интенсивного исследования Renderscript я отставку, так как нет документации, и я хочу понять, что я делаю. Кроме того, я даже пытаюсь создать смешную папку .rs с rs. скрипт, который распознается Java как объект Script_C .... Поэтому я стараюсь оптимально использовать Внутренние функции (например, Gauss Blur), и решение этой проблемы Sobel принесет мне необходимую мне скорость. – Settembrini

+0

Это можно сделать, но будет далек от оптимального: вам придется преобразовать данные растрового изображения в float сперва, так как ScriptIntrinsicConvolve3x3 требует ввода и вывода Allocations того же типа. Затем вы получите два прохода ядра и, наконец, преобразование в градиентную величину в Java. Я бы (снова) предложил вам попробовать «Импортировать образец ...» в пустой проект, чтобы вы могли анализировать скрипты сборки и т. Д. И, кстати, как вы установили папку «rs»? Рукой или с помощью папки «Новая папка/Renderscript»? Потому что я только что сделал последний в чистом проекте, и он работал как шарм. –

ответ

2

Ok, ниже у вас есть все важные детали. Он был скопирован из рабочего кода, надеюсь, что я ничего не пропустил. Вычислительная градиентная величина в Java с использованием out и out2 ассигнований остается в качестве упражнения для читателя. ;) Опять же, было бы намного быстрее (и чище) сделать все это в одном проходе Renderscript.

public class MainActivity { 
    private RenderScript mRS; 
    private Allocation mInAllocation; 
    Type.Builder TypeIn; 

    private void createScript(Bitmap mBitmapIn) { 
    mRS = RenderScript.create(this); 

    TypeIn = new Type.Builder(mRS, Element.F32_4(mRS)); 

    mInAllocation = createFromBitmap_F32_4(mRS, mBitmapIn); 

    mScriptConvolve = ScriptIntrinsicConvolve3x3.create(mRS, 
      Element.F32_4(mRS)); 

    } 

    private Allocation createFromBitmap_F32_4(RenderScript rs, Bitmap b) 
    { 
    int w = b.getWidth(); 
    int h = b.getHeight(); 
    int idx = 0; 

    Allocation atn = Allocation.createTyped(mRS, TypeIn.setX(w).setY(h).create()); 
    float []temp = new float[w * h * 4]; 

    for(int y = 0; y < h; y++) 
     for(int x = 0; x < w; x++) 
     { 
      int pix = b.getPixel(x, y); 

      temp[idx++] = 255.f; 
      temp[idx++] = (float)((pix >>> 16) & 0xff); 
      temp[idx++] = (float)((pix >>> 8) & 0xff); 
      temp[idx++] = (float)(pix & 0xff); 
     } 

    atn.copyFrom(temp); 

    return atn; 
    } 

    private void allocationToBitmap(Allocation atn, Bitmap bmp) 
    { 
    int w = bmp.getWidth(); 
    int h = bmp.getHeight(); 
    int idx = 0; 

    float []temp = new float[w * h * 4]; 
    atn.copyTo(temp); 

    for(int y = 0; y < h; y++) 
     for(int x = 0; x < w; x++) 
     { 
      int a = 255; idx++; 
      int r = Math.min(255, Math.max(0, (int)temp[idx++])); 
      int g = Math.min(255, Math.max(0, (int)temp[idx++])); 
      int b = Math.min(255, Math.max(0, (int)temp[idx++])); 

      bmp.setPixel(x, y, (a << 24 | r << 16 | g << 8 | b)); 
     } 
    } 

    private void performFilter(Allocation inAllocation, 
          Bitmap bitmapOut) { 

      Allocation out = Allocation.createTyped(mRS, TypeIn.create()); 
      Allocation out2 = Allocation.createTyped(mRS, TypeIn.create()); 

      // Emboss filter kernel 

      float coefficients[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; 
      float coefficients2[] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; 

      mScriptConvolve.setCoefficients(coefficients); 
      mScriptConvolve.setInput(inAllocation); 
      mScriptConvolve.forEach(out); // Gx 

      mScriptConvolve.setCoefficients(coefficients2); 
      mScriptConvolve.setInput(inAllocation); 
      mScriptConvolve.forEach(out2); // Gy 

      allocationToBitmap(out2, bitmapOut); 
    } 
+0

Я перестроил ваш код, но получаю ошибку времени выполнения при назначении ScriptIntrinsicConvolve3x3.create (rs, Element.F32_4 (rs)); он говорит, что android.support.v8.renderscript.RSIllegalArgumentException: Неподдерживаемый тип элемента. Во всяком случае, я многому научился на этом примере, который на самом деле не чист и не элегантен, как вы сказали выше; и я ясно вижу, что мне нужно реализовать его в Renderscript сам, я постараюсь изо всех сил. Что касается оценки величины, я использую прокси-сервер для гипотезы, который намного быстрее. Спасибо, в любом случае. – Settembrini

+0

private float proxyHypot (float a, float b) { float a1 = (float) Math.abs (a); float b1 = (float) Math.abs (b); if (a1 <= b1) { return 0.426f * a1 + 0.936f * b1; } else { return 0.426f * b1 + 0.936f * a1; } } – Settembrini

+0

Какой телефон/ОС вы используете? –

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