【问题标题】:How can I convert an RGB image to grayscale but keep one color? - Java如何将 RGB 图像转换为灰度但保留一种颜色? - 爪哇
【发布时间】:2021-12-12 14:11:23
【问题描述】:

我正在尝试创建类似于罪恶之城或其他电影的效果,它们会从图像中移除除一种颜色之外的所有颜色。

我有一张 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);
        }
        
    }

}

【问题讨论】:

  • 你能提供一个“一种颜色”的例子吗?假设我想保持“黄色”,这将涉及哪些值?
  • i.stack.imgur.com/YQNq3.png 你的意思是我要保留这张图片的哪个 rgb 代码?
  • stackoverflow.com/questions/69736054/… 我看到了这个链接,这正是我现在想要的,但他正在搜索 matlab 代码,而不是 java 代码。
  • 要将非红色像素变为灰色,您的else 部分需要为 r g 和 b 写入相同的值。
  • 你能给我代码示例吗?

标签: java colors rgb grayscale


【解决方案1】:

您需要注意,每种颜色都由 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

当然,您还可以尝试许多其他可能性,即不同的阈值、不同的颜色、基于亮度(一定范围内的灰度值)等。

【讨论】:

  • 碰巧 OP 的灰度转换不正确,因为他确实进行了线性化并且使用了错误的系数。关于使用阈值或范围,您的观点是正确的,但需要注意的是,这可能不会导致感知上有用的结果,因为色调可能是 OP 试图保留的内容,这需要像 LUV 或 LAB 这样的感知上一致的颜色模型.但是,如果您想要一个狭窄范围内的东西并且色相变化不是问题,那么您的答案是最直接的......
猜你喜欢
  • 2016-04-26
  • 1970-01-01
  • 2013-01-12
  • 2014-10-31
  • 2020-12-09
  • 2017-09-04
  • 1970-01-01
  • 2014-02-26
  • 2014-12-22
相关资源
最近更新 更多