使用直方图确定有色物体的存在?
我正在尝试确定图片的一部分是否包含红白条纹对象(liftramp)。如果它存在,它看起来像这样:,如果不是这样的话:
I'm trying to determine if portion of the picture contains red-white striped object (liftramp). If it is present, it looks like this: , and when not like this:
天真的方法是提取直方图,并计算是否有更多的红色像素而不是蓝色/绿色像素:
The naive approach was to extract histogram, and count if there is more red pixels than blue/green ones:
use Image::Magick;
my $image = Image::Magick->new;
my $rv = $image->Read($picture);
#$rv = $image->Crop(geometry=>'26x100+484+40');
my @hist_data = $image->Histogram;
my @hist_entries;
# Histogram returns data as a single list, but the list is actually groups of 5 elements. Turn it into a list of useful hashes.
while (@hist_data) {
my ($r, $g, $b, $a, $count) = splice @hist_data, 0, 5;
push @hist_entries, { r => $r, g => $g, b => $b, alpha => $a, count => $count };
}
my $total=0;
foreach my $v (@hist_entries) {
if ($$v{r}>($$v{g}+$$v{b})) { $total +=$$v{count}; }
}
然后比较 $ total> 10
(任意阈值)。虽然这对于相对阳光灿烂的日子似乎很有效(给出 50-180 存在与 0-2 不存在),重云和黄昏使得检测总是说liftramp不存在。
and then comparing if $total > 10
(arbitrary threshold). While that seems to work nice for relatively sunny day (giving 50-180 for presence vs 0-2 for not present), heavy clouds and dusk make the detection always say the liftramp is not present.
我想必须有更聪明的方法来检测是否存在红白对象。所以问题是如何更可靠地进行检测?
I guess there must be smarter way to detect if red-white object is present. So the question is how to do that detection more reliably?
请注意,灰色/绿色背景可能随着季节变化而变得更加灰褐色或类似。我也不能指望像素精度,因为它可能会移动一点(或者我只裁剪3-4像素,看看它们是否是红色) - 但它应该适合它裁剪的盒子。
Note that grayish/green background might change with seasons to more of gray-brown or something. I also cannot count on pixel precision as it might move a little (or I'd just crop a 3-4 pixels and look if they are red) - but it should mostly fit it he cropped box.
另一种对光照更不敏感的方法是在转换为HSV色彩空间后寻找红色色调。但由于红色与黑色/灰色/白色具有相同的0色调,我会反转图像,使红色变为青色。因此,在反转并转换为HSV后对色调通道进行直方图,并在180度附近的青色色调或其等效的50%灰度或0到255范围内的128处查找值。在imagemagick中,您将执行
Another way to do it that would be more insensitive to lighting would be to look for red hues after converting to HSV colorspace. But since red has the same 0 hue as black/gray/white, I would invert the image so that red becomes cyan. So histogram the hue channel after inverting and converting to HSV and look for values at cyan hue near 180 degrees or its equivalent of 50% gray or 128 in the range of 0 to 255. In imagemagick, you would do
convert XqG0F.png -negate -colorspace HSV -channel red -separate +channel -define histogram:unique-colors=false histogram:without_hist.png
convert x5hWF.png -negate -colorspace HSV -channel red -separate +channel -define histogram:unique-colors=false histogram:with_hist.png
所以你可以在第二张图片中看到(对于红色条),有一个实质性的中间附近的宽峰,即50%(水平),但在该区域的第一张图像中没有。
So you can see in the second image (for the red bar), there is a substantial broad peak near mid-way i.e., 50% (horizontally), but none in the first image in that region.