ScriptIntrincisConvolve3x3: Распределение выходных данных float4 вместо U8_4?

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

Распределение копий Android RenderScript в файле rs

1 ответ

Решение

Хорошо, ниже у вас есть все важные части. Это было скопировано из рабочего кода, надеюсь, я ничего не пропустил. Вычисление величины градиента в 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);
  }
Другие вопросы по тегам