java - 如何将白色背景更改为黑色

标签 java algorithm image-processing imagej marvin-framework

在最近的项目中,我不得不操纵图像,但是由于这对我来说是新手,所以我有点迷失了。

我需要使用常规扫描设备扫描手。我可以完成它,但是背景是白色的,我需要它是黑色的。经过几天的研究,找到了改变颜色的方法,我只得到了看起来像是剪切并粘贴在ms颜料中的图像。

原始图片:

Raw Scan of the hand

测试:

Raw Scan of the hand

我需要的是这样的:

Target image

我尝试使用Marvin FrameworkImagejCatalano框架。要查看我需要的setps,我使用了gimp,marving编辑器,斐济应用程序(但没有得到我一直在寻找的结果)。
我认为我需要转换为灰度,应用某种阈值,但是在一定范围的颜色中使用Alpha颜色(但是我没有找到方法,仅对二进制图像使用阈值),然后将遮罩应用于最初使用的是阈值灰度图像,但我也不知道如何直接在Java中或使用上面提到的任何框架来做到这一点。
任何帮助,将不胜感激。

更新
根据m69的说法,我尝试播放了发光值,从rgb转换为hsl。我只设置较浅的颜色。

首先尝试使用0.5的光阈值:

First try

第二次尝试使用0.9的光阈值

Second try

float threshold = 0.5f;

for(int y=0; y<imageIn.getHeight(); y++){
    for(int x=0; x<imageIn.getWidth(); x++){

        int r = imageOut.getIntComponent0(x, y);
        int g = imageOut.getIntComponent1(x, y);
        int b = imageOut.getIntComponent2(x, y);
        float[] hsl = HSLColor.fromRGB(r, g, b, null);

        if(hsl[2] >= threshold){
            float t = (hsl[2]-0.5f)*2f; 
            hsl[2] -= t;
            imageOut.setIntColor(x, y, HSLColor.toRGB(hsl));
        }
    }
}

问题在于这种方法会更改所有像素的光线,理想的情况是仅更改对象外部的颜色。我在互联网上寻找想法时,发现了马丁·詹尼克(MartinJaník)的一篇有关骨科解剖学的论文。他提出了下一个算法:
  • 将高斯滤波应用于脚部扫描以获得滤波后的图像
  • 阈值过滤后的图像以获得二进制图像
  • 在形态上关闭二进制图像以获得关闭的二进制图像
  • 对二进制图像应用高斯滤波以获得灰度蒙版
  • 将此遮罩应用于脚部扫描以获取整体脚部图像

  • 有了这个,我可以获得下一个结果:

    Martin Janík algorithm

    这接近于我想要的,因为物体的颜色没有被触摸到。但是,仍然存在一个问题,即对象周围的白色边框。这是因为我使用的是CombineByMask marving插件,它只支持二进制图像(不仅是二进制图像,而且只能掩盖一种颜色)。我认为需要一个新的插件来使用灰度图像蒙版进行组合,当颜色在1-255范围内时,请尝试与图像基础进行组合以获得深色或更浅的颜色(很明显,当颜色为255时,它应该离开只是基本图片的颜色)。

    这是我所说的遮罩灰度图像的示例图像:

    Example image apply a mask using a binary image and a grayscale image

    我认为这是我要走的路。

    更新2

    经过研究,我认为我已经接近想要的结果。我使用的算法是:
  • 应用五个
  • 的对比
  • 转换为灰色图像
  • 应用高斯过滤器
  • 图像阈值
  • 形态学关闭
  • 再次应用高斯滤波器
  • 将此结果图像用作原始
  • 的灰度蒙版

    这是结果图像:

    Result apply a grayscale mask

    这接近我想要的。在六步中,我可以应用两次,三次或更多次高斯滤镜,从而获得更柔和的边框效果,但由于扫描图像的性质,最后总是显示细的白色边框(我认为这是我可以做到的不处理),但我对此结果感到满意。现在,由于我没有找到应用灰度蒙版的Java算法,因此我将代码编写为:
    for(int y=0; y<mask.getHeight(); y++){
            for(int x=0; x<mask.getWidth(); x++){
    
                //ya que está en grayscale, los 3 valores son los mismos
                int r1 = mask.getIntComponent0(x, y);
                int g1 = mask.getIntComponent1(x, y);
                int b1 = mask.getIntComponent2(x, y);
    
                int r2 = image.getIntComponent0(x, y);
                int g2 = image.getIntComponent1(x, y);
                int b2 = image.getIntComponent2(x, y);
    
                //al color de salida, le asignamos la luminicencia de la imagen mascara
                int r = 0, g = 0, b = 0;
                if(r1 > 0 || r2 > 0){
                    r = r1*r2/Math.max(r1, r2);
                }
    
                if(g1 > 0 || g2 > 0){
                    g = g1*g2/Math.max(g1, g2);
                }
    
                if(b1 > 0 || b2 > 0){
                    b = b1*b2/Math.max(b1, b2);
                }
    
                image.setIntColor(x, y, r, g, b);
            }
        }
    

    和工作几乎很好,但有一些我无法解决的小细节。我的想法是像在gimp中那样混合图像,我做了以下工作:在上层设置灰度蒙版,将颜色应用于alpha函数,将白色应用于白色,得到以下结果:

    Gimp mix

    使用我为marving框架编写的算法,我得到下一张图片:

    Using marving

    区别在于,当原始图像上有更多白色时,我的算法不能降低强度颜色,可以比较两个图像看到这种效果。知道如何处理吗?这是在gimp中应用图层组合后的图像结果:

    Layer combination en gimp

    最佳答案

    最好的选择是进入照相馆或GIMP,并使用快速蒙版功能绘画所需的内容,您可以得到非常详细的像素信息,然后退出快速蒙版模式,并确保白色是行进中的蚂蚁的一部分。周围,​​然后从那里删除它,并在背景中填充一层黑色。您可能在边缘上使用了轻微的羽毛以使其自然融合。关于如何执行此操作,有更具体的教程,但这就是我的处理方法。

    关于java - 如何将白色背景更改为黑色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36817851/

    相关文章:

    python - 在Opencv Python中将RGB图像转换为YUV和YCbCr颜色空间图像

    python - OpenCV HOGDescripter Python

    java - 扩展 View 时是否总是需要调用 super ?

    java - 将 HashMap 加载到嵌套配置 bean 会引发 Binding Exception

    java - 将 Editable 作为 EditText.getText() 方法的返回类型的目的是什么?

    algorithm - 将英文名称拆分为名字和姓氏的最佳策略

    algorithm - 合并排序中的递归、快速排序和树的遍历

    python - 导入 cv2 (opencv) 时为 "DLL load failed"

    java - 无法理解带有new运算符的java语句

    java - 编写程序去除给定字符串中的空格