在最近的一个项目中,我必须处理图像,但由于这对我来说是新的,所以我有点迷路了。
我需要使用常规扫描设备扫描手部。我可以完成这个,但背景是白色的,我需要它是黑色的。经过几天的研究,找到了改变颜色的方法,我只得到了一张似乎在 ms paint 中剪切和粘贴的图像。
原图:
测试:
我需要的是这样的:
我尝试使用Marvin Framework、Imagej、Catalano框架。要查看我需要的 setps,我使用 gimp、marving 编辑器、斐济应用程序(但没有得到我想要的结果)。
我想我需要的是转换为灰度,应用某种阈值,但在一定的颜色范围内使用 alpha 颜色(但我没有找到方法,只有二进制图像的阈值),然后将蒙版应用到原始使用阈值灰度图像,但我不知道如何直接在 Java 中执行此操作,或者使用我上面提到的任何框架。
任何帮助,将不胜感激。
更新 根据 m69 所说,我尝试使用发光值,从 rgb 转换为 hsl。我只设置了较浅的颜色。
首先尝试使用 0.5 的光阈值:
第二次尝试使用 0.9 的光阈值
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));
}
}
}
问题是这种方法会改变所有像素的光线,理想的情况是只改变物体外部的颜色。我在互联网上寻找一个想法,我找到了 Martin Janík 的一篇关于骨科分析的论文。他提出了下一个算法:
- 对足部扫描应用高斯滤波以获得滤波图像
- 对滤波后的图像进行阈值化以获得二值图像
- 形态上关闭二值图像以获得闭合二值图像
- 对二值图像应用高斯滤波以获得灰度掩码
- 将此蒙版应用于足部扫描以获得整体足部图像
有了这个我可以得到下一个结果:
这接近我想要的,因为对象中的颜色没有被触及。但是对象周围的白色边框仍然存在问题。这是因为我正在使用 combineByMask marving 插件,它只支持二进制图像(不仅是二进制图像,而且只能屏蔽一种颜色)。我认为需要一个新插件来使用灰度图像蒙版进行组合,当颜色在 1-255 范围内时,尝试与图像基础组合以获得更暗或更亮的颜色(当颜色为 255 时,它应该离开只是基本图像的颜色)。
这是我所说的屏蔽灰度图像的示例图像:
我想这就是我要走的路。
更新 2
在做了一些研究之后,我想我已经接近我想要的结果了。我使用的算法是:
- 应用五个对比度
- 转换为灰度图像
- 应用高斯滤波器
- 阈值图像
- 形态关闭
- 再次应用高斯滤波器
- 将此结果图像用作原始图像的灰度蒙版
这是结果图像:
这接近我想要的。在第六步中,我可以应用两次、三次或更多次高斯滤镜,给出更柔和的边框效果,但由于扫描图像的性质,最后总是显示一个细的白色边框(我认为这是我可以做到的)不处理)但我对这个结果很满意。现在,由于我没有找到应用灰度蒙版的 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 函数,给出以下结果:
使用我为 marving 框架编写的算法,我得到下一张图像:
不同的是,我的算法不能在原始图像上有更多的白色时降低强度颜色,你可以看到比较两个图像的效果。知道如何处理吗?这是在 gimp 中应用图层组合后的图像结果: