如何将 RGB 图像转换为灰度图像但保留一种颜色? - Java
How can I convert an RGB image to grayscale but keep one color? - Java
我正在尝试创建一种类似于罪恶之城或其他电影的效果,它们会从图像中删除除一种颜色之外的所有颜色。
我有一张 RGB 图像,我想将其转换为灰度,但我想保留一种颜色。
这是我的照片:
Image to edit
我想保持红色。其余的应该是灰度。
到目前为止,这是我的代码:
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);
}
}
}
您需要注意,每种颜色都由 3 个值或通道表示,即红色、绿色和蓝色。如果您只保留其中一个频道,您会扭曲结果。
相反,您需要决定像素是应保留其原始颜色还是变为灰度。因此,假设您的代码已经正确地转换为灰度,归结为:
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
}
所以剩下的就是如何定义 keepColor
,这取决于您的要求。一个简单的选择可能是选择一种颜色并检查像素是否在该颜色的某个阈值内,例如像这样:
/**
* 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
}
然后选择一个值和一个差值,例如像这样:
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
当然还有很多其他的可能性你可以尝试,比如不同的阈值,不同的颜色,基于亮度(一定范围内的灰度值)等等
我正在尝试创建一种类似于罪恶之城或其他电影的效果,它们会从图像中删除除一种颜色之外的所有颜色。
我有一张 RGB 图像,我想将其转换为灰度,但我想保留一种颜色。
这是我的照片: Image to edit
我想保持红色。其余的应该是灰度。
到目前为止,这是我的代码:
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);
}
}
}
您需要注意,每种颜色都由 3 个值或通道表示,即红色、绿色和蓝色。如果您只保留其中一个频道,您会扭曲结果。
相反,您需要决定像素是应保留其原始颜色还是变为灰度。因此,假设您的代码已经正确地转换为灰度,归结为:
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
}
所以剩下的就是如何定义 keepColor
,这取决于您的要求。一个简单的选择可能是选择一种颜色并检查像素是否在该颜色的某个阈值内,例如像这样:
/**
* 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
}
然后选择一个值和一个差值,例如像这样:
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
当然还有很多其他的可能性你可以尝试,比如不同的阈值,不同的颜色,基于亮度(一定范围内的灰度值)等等