ScriptIntrincisConvolve3x3:输出分配float4而不是U8_4?

时间:2015-08-02 11:12:01

标签: android convolution renderscript

对于输入和输出分配同时应用ScriptIntrinsicConvolve3x3(或5x5)函数同样是U8_4也没有问题。但是如果我想将卷积应用于像Sobel这样的梯度滤波器,我需要一个float类型的输出(不是U8_4),因为我还需要考虑NEGATIVE输出值。这个问题在18个月前提出,但尚未得到答复。任何帮助都非常感谢。

Android RenderScript copy allocation in rs file

1 个答案:

答案 0 :(得分:2)

好的,下面你有所有重要的部分。它是从一个正常工作的代码中复制而来的,希望我没有错过任何东西。使用outout2分配在Java中计算梯度幅度是留给读者的练习。 ;)同样,在一个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);
  }