java - Android 上使用 RenderScript 的中值滤波器

标签 java android c99 median renderscript

我正在迈出使用 RenderScript 进行图像处理的第一步。 现在我正在尝试用它为 Android 实现一个中值过滤器。 基本上我尝试用它做的是: 它获取位图格式的图像,为每个像素及其 8 个相邻像素运行 3x3 过滤器(无边缘情况),计算每个颜色 channel 的中值并相应地设置输出像素。

我尝试过它是否可以与像这样的简单反转渲染脚本一起使用:

uchar4 RS_KERNEL invert(uchar4 in, uint32_t x, uint32_t y) {
  uchar4 out = in;
  out.r = 255 - in.r;
  out.g = 255 - in.g;
  out.b = 255 - in.b;
  return out;
}

而且效果很好。 但是当我更改 RenderScript 来计算中位数时,我只得到了黑色图片输出。

这是 RenderScript 代码:

#pragma version(1)
#pragma rs_fp_relaxed
#pragma rs java_package_name(com.google.android.GoogleCamera)

#include "rs_debug.rsh"

rs_allocation input;
uint32_t width;
uint32_t height;

static uchar medi(uchar colors[]) {
    //sorting just to half
    for(int i = 0; i < 5; i++){
        int minIndex = i;
        uchar minValue = colors[i];
        //loop until end
        for(int j = i+1; j < 9; j++){
            if (colors[j] < minValue) {
                minIndex = j;
                minValue = colors[j];
                //swap
                colors[j] = colors[i];
                colors[i] = minValue;
            }
        }
    }
    return colors[4];
}

uchar4 __attribute__((kernel)) median(uchar4 in, uint32_t x, uint32_t y) {
    uchar4 out = in;

    //edge
    if (x == 0 || x == width || y == 0 || y == height)
        return out;

    //all surronding pixels (TopLeft .. BottomRight)
    uchar4 tl = rsGetElementAt_uchar4(input, x-1, y+1);
    uchar4 tm = rsGetElementAt_uchar4(input, x, y+1);
    uchar4 tr = rsGetElementAt_uchar4(input, x+1, y+1);
    uchar4 l = rsGetElementAt_uchar4(input, x-1, y);
    uchar4 r = rsGetElementAt_uchar4(input, x+1, y);
    uchar4 bl = rsGetElementAt_uchar4(input, x-1, y-1);
    uchar4 bm = rsGetElementAt_uchar4(input, x, y-1);
    uchar4 br = rsGetElementAt_uchar4(input, x+1, y-1);

    //array for each color channel
    uchar reds[] = {tl.r, tm.r, tr.r, l.r, r.r, bl.r, bm.r, br.r, in.r};
    uchar greens[] = {tl.g, tm.g, tr.g, l.g, r.g, bl.g, bm.g, br.g, in.g};
    uchar blues[] = {tl.b, tm.b, tr.b, l.b, r.b, bl.b, bm.b, br.b, in.b};
    uchar alphas[] = {tl.a, tm.a, tr.a, l.a, r.a, bl.a, bm.a, br.a, in.a};

    //get median values
    out.r = medi(reds);
    out.g = medi(greens);
    out.b = medi(blues);
    out.a = medi(alphas);

    return out;
}

以防万一调用java部分:

private static Runnable runMedian(final Bitmap original, final File file) {
        return new Runnable() {
            @Override
            public void run() {
                //Create new bitmap
                Bitmap bitmap = original.copy(original.getConfig(), true);

                //Create renderscript
                RenderScript rs = RenderScript.create(CameraActivity.staticContext);

                //Create allocation from Bitmap
                Allocation allocationA = Allocation.createFromBitmap(rs, bitmap);

                //Create allocation with same type
                Allocation allocationB = Allocation.createTyped(rs, allocationA.getType());

                //Create script from rs file
                ScriptC_median medianScript = new ScriptC_median(rs);

                medianScript.set_input(allocationA);
                medianScript.set_width(original.getWidth());
                medianScript.set_height(original.getWidth());
                medianScript.forEach_median(allocationA, allocationB);

                //Copy script result into bitmap
                allocationB.copyTo(bitmap);

                //Destroy everything to free memory
                allocationA.destroy();
                allocationB.destroy();
                medianScript.destroy();
                rs.destroy();

                //write resulting bitmap to file
                writeFile(file, bitmap, "median");
            }
        };
    }

希望懂一点的人可以帮助我。 最美好的祝愿

最佳答案

您可能需要修改对边缘的处理:索引 x 从 0 到宽度-1,因此边缘位于宽度-1(和高度-1)。

在java部分,medianScript.set_height(original.getWidth());可能应该读取original.getHeight()除非宽度和高度相同。

关于java - Android 上使用 RenderScript 的中值滤波器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59977108/

相关文章:

Python 中的 Java setRequestHeader

java - 如何使用 Weblogic 访问文件?

android - 如何动态地将字符串消息添加到 Android 屏幕

c - 哪些 C99 功能被认为是有害的或不受支持的

c - 错误 : unknown conversion type character 'l' in format - scanning long long

c99 - 将 Google V8 嵌入 ANSI C 应用程序 - 从哪里开始?

java - 如何在创建索引请求中创建索引类型和id?

java - 主线程中的异常。空指针异常

java - getText 与 onTextChanged charSequence

android - 重新创建 map 后如何删除标记?