简体   繁体   English

如何将 RGB 图像转换为灰度但保留一种颜色? - 爪哇

[英]How can I convert an RGB image to grayscale but keep one color? - Java

I am trying to create an effect similar to Sin City or other movies where they remove all colors except one from an image.我正在尝试创建一种类似于罪恶之城或其他电影的效果,它们会删除图像中除一种之外的所有颜色。

I have an RGB image which I want to convert to grayscale but I want to keep one color.我有一个 RGB 图像,我想将其转换为灰度,但我想保留一种颜色。

This is my picture: Image to edit这是我的照片:要编辑的图片

I want to keep the red color.我想保持红色。 The rest should be grayscale.其余的应该是灰度的。

Here is my code so far:到目前为止,这是我的代码:

package poza;
import java.io.*;

public class poza {

    public static void main(String[] args) {
        
        try {
            FileInputStream fis=new FileInputStream("poza.bmp");
            BufferedInputStream dis=new BufferedInputStream(fis);
            FileOutputStream sif=new FileOutputStream("poza1.bmp");
            BufferedOutputStream bos=new BufferedOutputStream(sif);
            byte[] sti=new byte[54];
            dis.read(sti,0,54);
            bos.write(sti);
            while(dis.available()>0)
            {
                int b,g,r;
                b=dis.read();
                g=dis.read();
                r=dis.read();
                System.out.print(b+" "+g+" "+r+"\n");
                int gri=(int)(0.114*b+0.587*g+0.299*r);
                if(r>=b && r>=g)
                {
                    bos.write(gri);
                    bos.write(gri);
                    bos.write(r);
                }
                else
                {
                    bos.write(b);
                    bos.write(g);
                    bos.write(r);
                    
                }
                
                System.out.print(b+" "+g+" "+r+"\n");

            }
            dis.close();
            bos.close();
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
        
    }

}

You need to note that every color is represented by 3 values or channels, ie red, green and blue.您需要注意,每种颜色都由 3 个值或通道表示,即红色、绿色和蓝色。 If you only keep one of those channels you'll skew the results.如果您只保留这些频道之一,您将歪曲结果。

Instead you need to decide whether a pixel should retain its original color or become grayscale.相反,您需要决定像素应保留其原始颜色还是变为灰度。 So assuming your code already does the conversion to grayscale correctly, it comes down to this:因此,假设您的代码已经正确地转换为灰度,归结为:

if( keepColor ) {
  //I'll keep the order of the components that your example uses, make sure this is correct
  bos.write(b);
  bos.write(g);
  bos.write(r);
} else {
   bos.write(gri); //b
   bos.write(gri); //g
   bos.write(gri); //r
}

So what is left is how keepColor is defined and that depends on your requirements.所以剩下的是如何定义keepColor ,这取决于您的要求。 A simple option might be to pick a color and check if the pixel is within a certain threshold of that color, eg like this:一个简单的选择可能是选择一种颜色并检查像素是否在该颜色的某个阈值内,例如:

/**
  * value - the value to check
  * base - the base value to check against, i.e. the center of the range, expressed in range [0, 255]
  * difference - the allowable difference in percent, expressed in range [0.0, 1.0]
  */ 
boolean withinThreshold(int value, int base, double difference) {
   return value>= base * (1-difference) //check lower bound
     && value <= base * (1+difference); //check upper bound
}  

Then pick a value and a difference, eg like this:然后选择一个值和一个差异,例如:

boolean keepColor = withinThreshold(r, 228, 0.6) //40%-160% of 228 
                  && withinThreshold(g, 95, 0.6) //40%-160% of 95
                  && withinThreshold(b, 78, 0.6); //40%-160% of 78

Of course there are many other possibilities you can play around with, ie different thresholds, different colors, based on brightness (grayscale value in a certain range) etc.当然,您还可以使用许多其他可能性,即基于亮度(特定范围内的灰度值)等不同的阈值、不同的颜色。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM