java 将图像转换为黑白(不是灰度)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17482149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 02:07:54  来源:igfitidea点击:

Converting an image to black and white ( not gray scal)

javaimage-processing

提问by Bilbo Baggins

hello I am converting an image from color to pure black and white the result is a dark image. I am not getting the reason. Following is my code its been inspired by other codes on SO. Any guidance would be helpfull.

你好,我正在将图像从彩色转换为纯黑色和白色,结果是一个黑色的图像。我不明白原因。以下是我的代码,其灵感来自 SO 上的其他代码。任何指导都会有所帮助。

BufferedImage coloredImage = ImageIO.read(new File("/home/discusit/ninja.png"));
BufferedImage blackNWhite = new BufferedImage(coloredImage.getWidth(),coloredImage.getHeight(),BufferedImage.TYPE_BYTE_BINARY);
Graphics2D graphics = blackNWhite.createGraphics();
graphics.drawImage(blackNWhite, 0, 0, null);

I am not getting what I am doing wrong. Any more ideas using any other open source library would be fine.

我没有明白我做错了什么。使用任何其他开源库的更多想法都可以。

WORKING :::::

在职的 :::::

BufferedImage coloredImage = ImageIO.read(new File("/home/abc/ninja.png"));
BufferedImage blackNWhite = new BufferedImage(coloredImage.getWidth(),coloredImage.getHeight(),BufferedImage.TYPE_BYTE_BINARY);
Graphics2D graphics = blackNWhite.createGraphics();
graphics.drawImage(coloredImage, 0, 0, null);

ImageIO.write(blackNWhite, "png", new File("/home/abc/newBlackNWhite.png"));

回答by Mathias

If you want control over the so-called thresholding process, here a ready-to-use snippet. Start with 128 as a threshold, then you get what the other methods do.

如果你想控制所谓的阈值过程,这里有一个现成的片段。以 128 作为阈值开始,然后你就会明白其他方法的作用。

/**
 * Converts an image to a binary one based on given threshold
 * @param image the image to convert. Remains untouched.
 * @param threshold the threshold in [0,255]
 * @return a new BufferedImage instance of TYPE_BYTE_GRAY with only 0'S and 255's
 */
public static BufferedImage thresholdImage(BufferedImage image, int threshold) {
    BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
    result.getGraphics().drawImage(image, 0, 0, null);
    WritableRaster raster = result.getRaster();
    int[] pixels = new int[image.getWidth()];
    for (int y = 0; y < image.getHeight(); y++) {
        raster.getPixels(0, y, image.getWidth(), 1, pixels);
        for (int i = 0; i < pixels.length; i++) {
            if (pixels[i] < threshold) pixels[i] = 0;
            else pixels[i] = 255;
        }
        raster.setPixels(0, y, image.getWidth(), 1, pixels);
    }
    return result;
}

回答by user2357112 supports Monica

You don't actually convert the colored image to black and white; you're creating a new, blank image the same size as the old one. You need to actually do something to process the old image.

您实际上并未将彩色图像转换为黑白图像;您正在创建一个与旧图像大小相同的新空白图像。您实际上需要做一些事情来处理旧图像。

回答by William Morrison

To actually convert the image to black and white, you could iterate over each pixel and average the colors at that location. For example

要将图像实际转换为黑白,您可以迭代每个像素并平均该位置的颜色。例如

for(int x=0;x<width;x++){
    for(int y=0;y<height;y++){
        Color color = getPixelAt(x,y);
        int newColor = (color.getRed()+color.getGreen()+color.getBlue())/3;
        Color newPixelColor = new Color(newColor,newColor,newColor);
        //set new pixel
    }
}

There are more accurate ways to convert color to black and white though. Our eyes actually perceive more green than red, and more red than blue. Because of this, a more true conversion would weight each of the color componets appropriately to produce a better perceived average.

不过,有更准确的方法可以将颜色转换为黑白。我们的眼睛实际上感知到的绿色多于红色,红色多于蓝色。正因为如此,更真实的转换会适当地加权每个颜色成分,以产生更好的感知平均值。

Weighting I've used that produces good results is as follows:

我使用的产生良好结果的加权如下:

int newColor = (int)(color.getGreen()*.7+color.getRed()*.2+color.getBlue()*.1);

Edit:

编辑:

If by black and white you mean an image with only black pixels and white pixels, you could do this by assigning all pixels with an average less than a threshold value to black, and all pixels with an average greater to white. Like so:

如果黑色和白色是指只有黑色像素和白色像素的图像,您可以通过将平均值小于阈值的所有像素分配给黑色,并将平均值大于阈值的所有像素分配给白色来实现。像这样:

static final int BLACK = 0;
static final int WHITE = 255;
int threshold = 127;
if(newColor < threshold)
    newColor = BLACK;
else
    newColor = WHITE;

回答by Teodor

View a model

查看模型

import java.awt.*;
import java.awt.image.BufferedImage;

public class ImageTool {
    public static void toBlackAndWhite(BufferedImage img) {
        toBlackAndWhite(img, 50);
    }
    public static void toBlackAndWhite(BufferedImage img, int precision) {
        int w = img.getWidth();
        int h = img.getHeight();

        precision = (0 <= precision && precision <= 100) ? precision : 50;

        int limit = 255 * precision / 100;

        for(int i = 0, j; i < w; ++i) {
            for(j = 0; j < h; ++j) {
                Color color = new Color(img.getRGB(i, j));
                if(limit <= color.getRed() || limit <= color.getGreen() || limit <= color.getBlue()) {
                    img.setRGB(i, j, Color.WHITE.getRGB());
                } else {
                    img.setRGB(i, j, Color.BLACK.getRGB());
                }
            }
        }
    }
}

Try with main code

尝试使用主代码

for(Integer i : new Integer[] {0, 30, 70, 100}) {
    BufferedImage img = ImageIO.read(new File("in.png"));
    ImageTool.toBlackAndWhite(img, i);
    ImageIO.write(img, "png", new File("out_" + i + ".png"));
}

and you will see the result.

你会看到结果。

回答by Gabriel Ambrósio Archanjo

There are many approaches to represent images using just black and white pixels and for different kind of applications such as compression, impression, arts and analysis.

有许多方法可以仅使用黑白像素来表示图像,并且可以用于不同类型的应用程序,例如压缩、印象、艺术和分析。

The example below uses Marvin Frameworkand shows three different ways to represent images in black and white. In the case of halftone technique, an illusion of shades of gray is created, but if zoom in you'll see just white and black pixels.

下面的示例使用Marvin 框架并展示了三种不同的方式来表示黑白图像。在半色调技术的情况下,会产生灰色阴影的错觉,但如果放大,您只会看到白色和黑色像素。

input:

输入:

enter image description here

在此处输入图片说明

thresholding:

阈值:

enter image description here

在此处输入图片说明

halftone:

半色调:

enter image description here

在此处输入图片说明

halftone zoom:

半色调缩放:

enter image description here

在此处输入图片说明

circles:

界:

enter image description here

在此处输入图片说明

import static marvin.MarvinPluginCollection.*;

public class BlackAndWhiteExamples {

    public BlackAndWhiteExamples(){
        MarvinImage original = MarvinImageIO.loadImage("./res/lena3.jpg");
        MarvinImage output = original.clone();
        thresholding(original, output, 190);
        // 1. Thresholding
        MarvinImageIO.saveImage(output, "./res/lena3_thresholding.png");
        halftoneErrorDiffusion(original, output);
        // 2. Halftoning
        MarvinImageIO.saveImage(output, "./res/lena3_error_diffusion.png");
        // 3. Circles
        halftoneCircles(original, output, 15, 0, 0);
        MarvinImageIO.saveImage(output, "./res/lena3_circles.png");
    }

    public static void main(String[] args) {    new BlackAndWhiteExamples();    }
}

回答by Diego Catalano

You can use Catalano Framework, contains several filters for image processing, you can convert to black and white using threshold filter. See below:

您可以使用 Catalano Framework,它包含多个用于图像处理的过滤器,您可以使用阈值过滤器将其转换为黑白。见下文:

http://code.google.com/p/catalano-framework/

http://code.google.com/p/catalano-framework/

FastBitmap fb = new FastBitmap(bufferedImage);

Grayscale g = new Grayscale();
g.applyInPlace(fb);

Threshold t = new Threshold(150);
t.applyInPlace(fb);

//Show the results
JOptionPane.showMessageDialog(null, fb.toIcon());

//or if u prefer retrieve the bufferedImage you need to do
bufferedImage = fb.toBufferedImage();

回答by johnchen902

I think it's just a typo:

我认为这只是一个错字:

graphics.drawImage(blackNWhite, 0, 0, null);

Replace blackNWhitewith the image you want to process with

替换blackNWhite为您要处理的图像

graphics.drawImage(coloredImage, 0, 0, null);

And now blackNWhitecontains the black-and-white version of coloredImage. Maybe you will want another assignment:

现在blackNWhite包含黑白版本的coloredImage. 也许你会想要另一个任务:

coloredImage = blackNWhite;