【问题标题】:Take monochrome picture (black and white) with Android使用 Android 拍摄单色照片(黑白)
【发布时间】:2012-08-15 22:51:30
【问题描述】:

我想在我的应用程序中拍摄一张真正的黑白照片。我搜索了解决方案(也在这个网站上),但我总是找到将照片放在灰度中的解决方案(例如在this topic 中),但这不是我要找的......

我还找到了一个主题提出这个:

public static Bitmap createContrast(Bitmap src, double value) {
// image size

                int width = src.getWidth();
                int height = src.getHeight();
                // create output bitmap
                Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
                // color information
                int A, R, G, B;
                int pixel;
                // get contrast value
                double contrast = Math.pow((100 + value) / 100, 2);

        // scan through all pixels
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                // get pixel color
                pixel = src.getPixel(x, y);
                A = Color.alpha(pixel);
                // apply filter contrast for every channel R, G, B
                R = Color.red(pixel);
                R = (int) (((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
                if (R < 0) {
                    R = 0;
                } else if (R > 255) {
                    R = 255;
                }

                G = Color.red(pixel);
                G = (int) (((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
                if (G < 0) {
                    G = 0;
                } else if (G > 255) {
                    G = 255;
                }

                B = Color.red(pixel);
                B = (int) (((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
                if (B < 0) {
                    B = 0;
                } else if (B > 255) {
                    B = 255;
                }

                // set new pixel color to output bitmap
                bmOut.setPixel(x, y, Color.argb(A, R, G, B));
            }
        }

        return bmOut;

    }

但是画质太差了……

请问有人有意见吗?

谢谢

【问题讨论】:

  • 嗯..这可能是一个愚蠢的问题,但“真正的黑白”和灰度之间有什么区别?两者都有不同的灰色阴影,但是这些术语有特定的定义吗?顺便说一句,“50 种色调”的笑话被禁止了! :)
  • @Alex - 我也在想同样的事情,偶然发现了这个例子farm3.staticflickr.com/2393/3533241378_04c2b649c2_b.jpg。上图为单色,下图为灰度图。我想这取决于 OP 试图实现的目标 - 从他的应用程序中的手机摄像头捕获真正的单色图像或转换现有图像?我问的唯一原因是因为他已经发布了事后转换它们的示例:-)
  • @shri046 没有一些话,你的例子不是解释。单色是指一种颜色与其他颜色的背景。黑白意味着它在白色背景下是黑色的。我猜您展示的示例只是使用不同的过滤器从彩色转换为黑白。
  • 我认为这可能是合适的:stackoverflow.com/questions/2499545/…
  • @slim 我假设 OP 不想要真正的单色(即仅像素值 0 和 255),这让我感到困惑。我在工作时无法检查大多数链接的图像(被阻止,grr)。顺便说一句,黑白也可能意味着黑色背景上的白色!斑马是黑色带白色条纹还是白色带黑色条纹? :)

标签: java android android-camera photo image


【解决方案1】:

如果您希望图像为 1 位黑/白,您可以使用简单(且速度较慢)的阈值算法

public static Bitmap createBlackAndWhite(Bitmap src) {
    int width = src.getWidth();
    int height = src.getHeight();
    // create output bitmap
    Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
    // color information
    int A, R, G, B;
    int pixel;

    // scan through all pixels
    for (int x = 0; x < width; ++x) {
        for (int y = 0; y < height; ++y) {
            // get pixel color
            pixel = src.getPixel(x, y);
            A = Color.alpha(pixel);
            R = Color.red(pixel);
            G = Color.green(pixel);
            B = Color.blue(pixel);
            int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);

            // use 128 as threshold, above -> white, below -> black
            if (gray > 128) 
                gray = 255;
            else
                gray = 0;
            // set new pixel color to output bitmap
            bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray));
        }
    }
    return bmOut;
}

但取决于看起来不太好,为了获得更好的结果,您需要一种抖动算法,请参阅Algorithm overview - 这是阈值方法。


对于 256 级灰度转换:

根据http://www.mathworks.de/help/toolbox/images/ref/rgb2gray.html,您将每个像素的灰度值计算为gray = 0.2989 * R + 0.5870 * G + 0.1140 * B,这将转换为

public static Bitmap createGrayscale(Bitmap src) {
    int width = src.getWidth();
    int height = src.getHeight();
    // create output bitmap
    Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
    // color information
    int A, R, G, B;
    int pixel;

    // scan through all pixels
    for (int x = 0; x < width; ++x) {
        for (int y = 0; y < height; ++y) {
            // get pixel color
            pixel = src.getPixel(x, y);
            A = Color.alpha(pixel);
            R = Color.red(pixel);
            G = Color.green(pixel);
            B = Color.blue(pixel);
            int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
            // set new pixel color to output bitmap
            bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray));
        }
    }
    return bmOut;
}

但这很慢,因为您必须分别为数百万像素执行此操作。

https://stackoverflow.com/a/9377943/995891 有更好的方法来实现同样的目标。

// code from that answer put into method from above
public static Bitmap createGrayscale(Bitmap src) {
    int width = src.getWidth();
    int height = src.getHeight();
    Bitmap bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bmOut);
    ColorMatrix ma = new ColorMatrix();
    ma.setSaturation(0);
    Paint paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(ma));
    canvas.drawBitmap(src, 0, 0, paint);
    return bmOut;
}

【讨论】:

  • 非常感谢,您的“createBlackAndWhite()”方法正是我想要的。你说的有点慢,但这是真正的黑白。我会尝试优化一下,但效果很好
  • 一个问题:在这段代码“(0.2989 * R + 0.5870 * G + 0.1140 * B)”中,你为什么使用这些值:0.2989、0.5870和0.1140?
  • @Vince 这是将颜色转换为灰度的可能方法之一。人类对颜色亮度的感知不同(例如蓝色比绿色亮得多),因此这试图与人类感知相匹配。查看images here 或阅读stackoverflow.com/questions/687261/…
【解决方案2】:

G = Color.red(像素);

G = 颜色。绿色(像素);

B = Color.red(像素);

B = 颜色。蓝色(像素);

看看这种变化(粗体)是否有帮助。

【讨论】:

    猜你喜欢
    • 2011-03-30
    • 1970-01-01
    • 2015-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多