【发布时间】:2016-08-17 12:04:08
【问题描述】:
在最近的一个项目中,我必须处理图像,但由于这对我来说是新的,所以我有点迷茫。
我需要使用常规扫描设备扫描手部。我可以完成这个,但背景是白色的,我需要它是黑色的。经过几天的研究,找到了改变颜色的方法,我只得到了一张似乎在 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中应用图层组合后的图像结果:
【问题讨论】:
-
我认为白色边框来自于在曲线的阈值处使用突然的方向变化,而不是像我在示例中所做的那样使用圆形弯曲。检查您的框架是否有任何方法可以为亮度创建样条曲线,或者用自己的部分圆或其他东西滚动。
-
如果你还在做这个项目,并且想进一步讨论,你可以在 ImageJ 论坛上发帖:forum.imagej.net。那里有很多图像处理专家,他们可能很感兴趣,可以为您的分析提供建议和努力。
标签: java algorithm image-processing imagej marvin-framework