0

(黒)などの数値の RBG コードを持っている場合、-16777216このカラー コードを使用して他の同様の黒の色合いを見つけるにはどうすればよいですか?

白ではないすべてのピクセルをマークして、画像をモノクロに変換しようとしてい-16777216ます。ただし、さまざまな色合いの黒が見つかることがよくありますが、それらは正確に一致しないため失われます。

編集:ちょっと困っています。この色を使用して黒の色合いを見つけようとすると、他のピクセルを白に変換するときにそれらを無視できるようになります。これが私の結果です。

ソース:

ソース

結果:

結果

コード:

package test;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import javax.imageio.ImageIO;

public class Test
{       
    public static void main(String[] args)
    {
        try
        {
            BufferedImage source = ImageIO.read( new URL("http://i.imgur.com/UgdqfUY.png"));
            //-16777216 = black:
            BufferedImage dest = makeMonoChromeFast(source, -16777216);
            File result = new File("D:/result.png");
            ImageIO.write(dest, "png", result);
        }
        catch (Exception e)
        {
            e.printStackTrace();;
        }
    }

    public static BufferedImage makeMonoChromeFast(BufferedImage source, int foreground)
    {        
        int background = -1; //white;

        Color fg = new Color(foreground);

        int color = 0;
        for (int y = 0; y < source.getHeight(); y++)
        {
            for (int x = 0; x < source.getWidth(); x++)
            {
                color = source.getRGB(x, y);
                if ( color == foreground )
                    continue;
                if (! isIncluded(fg, color, 50))
                    source.setRGB(x, y, background);;
            }
        }

        return source;
    }

    public static boolean isIncluded(Color target, int pixelColor, int tolerance)
    {
        Color pixel = new Color(pixelColor);
        int rT = target.getRed();
        int gT = target.getGreen();
        int bT = target.getBlue();
        int rP = pixel.getRed();
        int gP = pixel.getGreen();
        int bP = pixel.getBlue();
        return(
            (rP-tolerance<=rT) && (rT<=rP+tolerance) &&
            (gP-tolerance<=gT) && (gT<=gP+tolerance) &&
            (bP-tolerance<=bT) && (bT<=bP+tolerance) );
    }
}
4

2 に答える 2

3

この「許容差のある色を探す」方法を使用できます。

public static boolean isIncluded(Color target, Color pixel, int tolerance) {
    int rT = target.getRed();
    int gT = target.getGreen();
    int bT = target.getBlue();
    int rP = pixel.getRed();
    int gP = pixel.getGreen();
    int bP = pixel.getBlue();
    return(
        (rP-tolerance<=rT) && (rT<=rP+tolerance) &&
        (gP-tolerance<=gT) && (gT<=gP+tolerance) &&
        (bP-tolerance<=bT) && (bT<=bP+tolerance) );
}

ここではmotorcycle-03.jpg、オートバイ ( motorcycle.jpg) のアウトライン ( ) を取得するために使用されますが、「かすかな灰色のオーバーレイ」は取り除かれます。

オートバイ.jpg

元の画像

オートバイ-03.png

加工画像

ImageOutline.java

このコードには、(実行時に) ある程度の忍耐が必要です。同じことをはるかに高速に実行するコードについては、ギザギザのパスの平滑化を参照してください。

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Area;
import javax.imageio.ImageIO;
import java.io.File;
import java.util.Date;
import javax.swing.*;

/* Motorcycle image courtesy of ShutterStock
http://www.shutterstock.com/pic-13585165/stock-vector-travel-motorcycle-silhouette.html */
class ImageOutline {

    public static Area getOutline(BufferedImage image, Color color, boolean include, int tolerance) {
        Area area = new Area();
        for (int x=0; x<image.getWidth(); x++) {
            for (int y=0; y<image.getHeight(); y++) {
                Color pixel = new Color(image.getRGB(x,y));
                if (include) {
                    if (isIncluded(color, pixel, tolerance)) {
                        Rectangle r = new Rectangle(x,y,1,1);
                        area.add(new Area(r));
                    }
                } else {
                    if (!isIncluded(color, pixel, tolerance)) {
                        Rectangle r = new Rectangle(x,y,1,1);
                        area.add(new Area(r));
                    }
                }
            }
        }
        return area;
    }

    public static boolean isIncluded(Color target, Color pixel, int tolerance) {
        int rT = target.getRed();
        int gT = target.getGreen();
        int bT = target.getBlue();
        int rP = pixel.getRed();
        int gP = pixel.getGreen();
        int bP = pixel.getBlue();
        return(
            (rP-tolerance<=rT) && (rT<=rP+tolerance) &&
            (gP-tolerance<=gT) && (gT<=gP+tolerance) &&
            (bP-tolerance<=bT) && (bT<=bP+tolerance) );
    }

    public static BufferedImage drawOutline(int w, int h, Area area) {
        final BufferedImage result = new BufferedImage(
            w,
            h,
            BufferedImage.TYPE_INT_RGB);
        Graphics2D g = result.createGraphics();

        g.setColor(Color.white);
        g.fillRect(0,0,w,h);

        g.setClip(area);
        g.setColor(Color.red);
        g.fillRect(0,0,w,h);

        g.setClip(null);
        g.setStroke(new BasicStroke(1));
        g.setColor(Color.blue);
        g.draw(area);

        return result;
    }

    public static BufferedImage createAndWrite(
        BufferedImage image,
        Color color,
        boolean include,
        int tolerance,
        String name)
        throws Exception {
        int w = image.getWidth();
        int h = image.getHeight();

        System.out.println("Get Area: " + new Date() + " - " + name);
        Area area = getOutline(image, color, include, tolerance);
        System.out.println("Got Area: " + new Date() + " - " + name);

        final BufferedImage result = drawOutline(w,h,area);
        displayAndWriteImage(result, name);

        return result;
    }

    public static void displayAndWriteImage(BufferedImage image, String fileName) throws Exception {
        ImageIO.write(image, "png", new File(fileName));
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(image)));
    }

    public static void main(String[] args) throws Exception {
        final BufferedImage outline = ImageIO.read(new File("motorcycle.jpg"));
        BufferedImage crop = outline.getSubimage(17,35,420,270);
        displayAndWriteImage(crop, "motorcycle-01.png");

        BufferedImage crude = createAndWrite(crop, Color.white, false, 60, "motorcycle-02.png");

        BufferedImage combo = createAndWrite(crude, Color.red, true, 0, "motorcycle-03.png");
    }
}

質問に見られるコードで、150 の許容範囲で、これがわかります。

ここに画像の説明を入力

于 2013-09-22T08:52:58.920 に答える
2

一般的には、ウィキペディアのこのページで説明されている sRGB からグレースケールへの変換式を使用し、特定の「グレー」値を黒と白の境界として選択する方法だと思います。(選択はあなた次第です...)

しかし、グレー スケール ポイントを表す RGB 値が既にあるとします。これらの値はすべて、赤、緑、青の値が等しいことがわかります。その場合は、RGB の色成分の 1 つを選択し、選択した「灰色」の同じ色値と比較するだけです。

黒、グレー、白の複数の色合いを区別する必要がある場合は、複数の境界「色」を選択します。


編集:ちょっと困っています。この色を使用して黒の色合いを見つけようとすると、他のピクセルを白に変換するときにそれらを無視できるようになります。これが私の結果です。

そこに表示されているのは、アンチエイリアシングの効果です。実際、画像には「純粋な」黒はほとんどありません。人間の目には黒く見えるものの多くは、実際には暗いか、それほど暗い灰色ではありません。境界の色 (つまり、「黒」と「黒ではない」の境界) をより灰色にする必要があります。

于 2013-09-22T10:09:55.373 に答える