在数码照片中,如何检测山脉是否被云遮住了?
问题
我有一组日本一座山的数码照片。然而,这座山经常被云或雾遮蔽。
我可以使用哪些技术来检测图像中的山是否可见?我目前正在使用 Perl 和 Imager 模块,但对替代方案持开放态度。
所有图像都是从完全相同的位置拍摄的 - 这些是一些样本。
示例图片 http://www.freeimagehosting.net/uploads/7304a6e191.jpg
我的简单解决方案
我首先采集了山锥的几个水平像素样本,并将亮度值与天空中的其他样本进行比较。这对于区分好图像 1 和坏图像 2 很有效。
然而,在秋天下雪了,山变得比天空更亮,就像图 3 一样,我的简单亮度测试开始失败。
图 4 是边缘情况的示例。我认为这是一张好照片,因为一些山峰清晰可见。
更新1
感谢您的建议 - 我很高兴你们都大大高估了我的能力。
根据答案,我开始尝试 ImageMagick 边缘检测 变换,它给出我有一个更简单的图像来分析。
convert sample.jpg -edge 1 edge.jpg
边缘检测样本 http://www.freeimagehosting.net/uploads/caa9018d84.jpg
I假设我应该使用某种遮罩来去除树木和大部分云。
获得蒙版图像后,比较与“好”图像相似度的最佳方法是什么?我想“compare”命令适合这项工作吗?如何从中获得数字“相似度”值?
更新2
我想我可能会通过卷积得到一些成果。
我通过对良好图像执行边缘检测来制作“内核”图像(下图顶部)。然后我把山的轮廓周围的所有“噪音”都涂黑,然后将其裁剪掉。
然后我使用了以下代码:
use Image::Magick;
# Edge detect the test image
my $test_image = Image::Magick->new;
$test_image->Read($ARGV[0]);
$test_image->Quantize(colorspace=>'gray');
$test_image->Edge(radius => 1);
# Load the kernel
my $kernel_image = Image::Magick->new;
$kernel_image->Read('kernel-crop.jpg');
# Convolve and show the result
$kernel_image->Convolve(coefficients => [$test_image->GetPixels()]);
$kernel_image->Display();
我对各种示例图像运行了此代码,得到的结果如下(每个示例下方显示了卷积图像):
(抱歉 - 与上次不同的示例图像!)
替代文本 http://www.freeimagehosting.net/uploads/f9a5a34980.jpg
现在我我试图量化图像的“粗糙”程度。我尝试获取图像平均亮度:
$kernel_image->Scale('1x1');
die $kernel_image->GetPixel(x=>1,y=>1)[0];
但这给出了没有给出有意义的值(0.0165、0.0175 和 0.0174)。还有更好的办法吗?
The problem
I have a collection of digital photos of a mountain in Japan. However the mountain is often obscured by clouds or fog.
What techniques can I use to detect that the mountain is visible in the image? I am currently using Perl with the Imager module, but open to alternatives.
All the images are taken from the exact same position - these are some samples.
Sample Images http://www.freeimagehosting.net/uploads/7304a6e191.jpg
My naïve solution
I started by taking several horizontal pixel samples of the mountain cone and comparing the brightness values to other samples from the sky. This worked well for differentiating good image 1 and bad image 2.
However in the autumn it snowed and the mountain became brighter than the sky, like image 3, and my simple brightness test started to fail.
Image 4 is an example of an edge case. I would classify this as a good image since some of the mountain is clearly visible.
UPDATE 1
Thank you for the suggestions - I am happy you all vastly over-estimated my competence.
Based on the answers, I have started trying the ImageMagick edge-detect transform, which gives me a much simpler image to analyze.
convert sample.jpg -edge 1 edge.jpg
Edge detected samples http://www.freeimagehosting.net/uploads/caa9018d84.jpg
I assume I should use some kind of masking to get rid of the trees and most of the clouds.
Once I have the masked image, what is the best way to compare the similarity to a 'good' image? I guess the "compare" command suited for this job? How do I get a numeric 'similarity' value from this?
UPDATE 2
I think I may be getting somewhere with convolve.
I made my 'kernel' image (top of the image below) by performing edge detect on a good image. I then blacked out all the 'noise' around the outline of the mountain and then cropped it.
I then used the following code:
use Image::Magick;
# Edge detect the test image
my $test_image = Image::Magick->new;
$test_image->Read($ARGV[0]);
$test_image->Quantize(colorspace=>'gray');
$test_image->Edge(radius => 1);
# Load the kernel
my $kernel_image = Image::Magick->new;
$kernel_image->Read('kernel-crop.jpg');
# Convolve and show the result
$kernel_image->Convolve(coefficients => [$test_image->GetPixels()]);
$kernel_image->Display();
I ran this for various sample images, and I got results as below (the convolved image is shown below each sample):
(Sorry - different sample images from last time!)
alt text http://www.freeimagehosting.net/uploads/f9a5a34980.jpg
Now I am trying to quantify how 'ridgy' an image is. I tried taking the image average brightness:
$kernel_image->Scale('1x1');
die $kernel_image->GetPixel(x=>1,y=>1)[0];
But this gives does not give meaningful values (0.0165, 0.0175 and 0.0174). Any better ways?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
答案取决于问题的具体程度。如果是同一 POV 中的同一座山,则针对已知的良好图像运行边缘检测,并将其用作与语料库中边缘检测到的图像进行卷积的基线。如果您只对山的边缘感兴趣,请手动从基线中删除其他要素。
The answer depends on how specific the problem is. If it's the same mountain from the same POV, run and edge detection against a known good image, and use it as a baseline for convolving against edge-detected images from the corpus. If it's only the edge of the mountain that you're interested in, manually remove other features from the baseline.
我认为你的工作水平太低了。快速通过边缘检测过滤器将图像集非常明显地划分为 (1, 3) 和 (2, 4)。特别是如果这些图像来自固定的相机视点,则在算法上找到与(1)中的原型形状的匹配将相对容易。即使您的情况(4)也可以为您提供一个部分匹配的域,您可以启发式地确定那里是否有足够的山可供考虑。
I think you are working on too low a level. A quick pass through an edge detection filter partitioned the image set very distinctly into (1, 3) and (2, 4). Especially if these images come from a fixed camera viewpoint, finding a match against the prototypical shape in (1) would be relatively easy algorithmically. Even your case of (4) could give you a domain of partial matching which you could heuristically determine if there was enough mountain there to consider.
基于您已有的内容,提出一些具体建议:
A few specific recommendations, building upon what you've got already:
Convolve
function from PerlMagick (you seem already comfortable with Perl and ImageMagick) to convolve the kernel with a few images. On the resulting image you should see a sharp spike corresponding to the "correct" position of the kernel (coinciding with the mountain in the image).