C# 的计算机视觉应用 - 第二部分
应用计算机视觉 - 矩。
引言
如果你学过高中物理,你就会知道一些关于“矩”的东西。从物理学,它进入了概率论,由于计算机视觉利用概率论,因此在计算机视觉中使用矩是很自然的。所以,继第一部分之后,我将讨论图像矩以及如何使用它们。由于本系列文章的主题是应用,我将始终强调理论与实践相结合。那么,让我们开始吧!
图像矩
图像矩可以简单地描述为图像像素强度(pixel intensity)的某种函数。像素强度不过是像素的颜色值。矩是根据它们的幂来描述的,就像数学中的“幂”。所以,我们有零阶矩、一阶矩、二阶矩等。以下是计算矩的公式
请注意,从基本代数可知,任何数的 0 次幂都是 1,这就是为什么上面的一些项消失了。此外,零阶矩也称为图像的面积。所以,基本上,我们需要像素强度或值以及 x 和 y 坐标来计算矩。使用矩,我们可以找到图像的质心或重心。还可以通过使用矩找到其他一些东西。
直方图反投影
直方图反投影是一种用于创建目标概率图像(反投影图像)的技术。例如,假设我们创建一个图像中目标的直方图。如果我们对该直方图进行反投影到图像上,它将创建一个图像,显示像素属于目标的概率。
让我们深入研究一下——一旦我们有了目标直方图 histT
,我们就创建要在其上反投影目标直方图的图像 histImage
的直方图。然后,对于图像中的每个像素值,我们从图像直方图获得存储桶索引 idx
。我们将反投影图像中像素的值设置为目标直方图在该存储桶索引处的值与图像直方图在该存储桶索引处的值之比,即 histT[idx] / histImage/[idx]
,如下所示。
Bitmap bpImage = new Bitmap(bmp.Width, bmp.Height, bmp.PixelFormat);
Histogram frameHistogram = Create1DHistogram(bmp, sourceHistogram.BinCount1,
sourceHistogram.BinCount2, sourceHistogram.BinCount3);
:
:
for (int y = 0; y < size.Y; y++)
{
pPixel = fastBitmap[0, y];
pPixelBP = fastBitmapBP[0, y];
for (int x = 0; x < size.X; x++)
{
//get the bin index for the current pixel colour
idx = GetSingleBinIndex(sourceHistogram.BinCount1,
sourceHistogram.BinCount2, sourceHistogram.BinCount3, pPixel);
//find the value for backprojection image and set
if (frameHistogram.Data[idx] > 0) //avoid divide by zero error
val = (byte)(255 * (int)(sourceHistogram.Data[idx] /
frameHistogram.Data[idx]));
else
val = 0;
pPixelBP->red = val;
pPixelBP->green = val;
pPixelBP->blue = val;
//increment the pointer
pPixel++;
pPixelBP++;
}
}
在上面的代码中,我们创建了一个空白的反投影图像,为当前帧创建了直方图,并遍历了帧像素。对于每个像素,我们找到存储桶索引,并使用此存储桶索引,我们获取目标直方图和帧直方图的值。我们找到这些值的比率并进行缩放,使比率值范围从 0 到 255。这个值最终用于设置反投影图像中的像素值。所以,这是反投影图像的一个例子
在上图中,我用鼠标选择了目标。它显示为红色矩形(暂时忽略黄色矩形)。然后,所选目标的直方图被反投影(右图)到同一图像帧上。我们可以看到,如果目标和帧在某个像素索引对应的存储桶值相同,则反投影图像中的结果像素值将为 255。因此,像素值越亮,其属于目标的概率越高。在反投影图像中(暂时忽略红色和蓝色线条),我们可以清楚地看到目标以及一些噪声,即一条垂直线和左上角的一些区域。
讨论直方图反投影的原因是
- 这是一项有用的技术,可以纳入你的工具箱
- 你可以找到更多关于目标的信息,例如方向,并且
- 我将使用反投影实现一个简单的对象跟踪器。
使用反投影图像和矩,我们可以找到目标的方向,以及概率分布的长度和宽度。以下是使用公式
角度是对象绕主轴 l(上面的红线)的方向,而 w 是短轴(上面的蓝线)。
质心跟踪器
现在,是时候做一些更令人兴奋的事情了——让我们跟踪图像序列中的一个对象。我们将如何做到这一点?让我们做以下工作
- 选择图像中的对象,并创建目标窗口内区域的直方图。
- 使用反投影分割对象。但是,不是将它投影到整个帧上,而是将其投影到搜索区域(黄色框)上,以减少跟踪器失败的风险。
- 找到这个对象的质心。
- 获取下一帧,并使用直方图反投影分割搜索窗口下的区域。
- 找到质心,并将目标窗口和搜索窗口居中于质心。
- 重复 4 直到图像序列结束。
我们应该认识到,在原始对象周围使用搜索窗口非常重要。它将分割范围限制在较小的区域内。这意味着由于背景中存在颜色相似的对象而导致跟踪器丢失的概率降低。此外,有限的区域增加了处理速度,使跟踪器非常快。
使用代码 - 矩 & 质心
步骤 1:选择一个直方图大小 - 默认是 4x4x4。
步骤 2:从列表中选择一个图像,然后单击“选择”按钮。
步骤 3:使用鼠标在图像中选择一个区域 - 右键单击鼠标并拖动。这将创建所选区域的直方图,将其反投影到整个图像上,计算矩,并标记所选区域的质心。
使用代码 - 质心跟踪
步骤 1:选择一个直方图大小 - 默认是 4x4x4
步骤 2:单击“加载序列”按钮以查看第一张图像的直方图。
步骤 3:使用鼠标在图像中选择一个区域 - 右键单击鼠标并拖动。这将仅反投影到搜索区域,计算矩并标记所选区域的质心。目标直方图以红色显示,在跟踪过程中不会改变。
步骤 4:单击“跟踪”按钮以观看跟踪效果。候选直方图以蓝色显示,在跟踪过程中会发生变化,因为它是在跟踪器“认为”是目标区域的直方图。
您可以将自己的序列(命名为 0 到 N)的位图拖放到序列文件夹中,并在其上试用跟踪器。
在本篇文章中,我们学习了图像矩,然后运用我们的创造力将所学的矩知识应用于创建一个简单的对象跟踪器。显然,这是一个简单的跟踪器,但在特定情况下可能非常有效。但在现实世界中,我们并不总是有机会拥有理想的条件。我们无法控制将部署跟踪器的环境。场景中会有多个对象在做不同的事情,颜色也不同等等。所以,我们需要一个更鲁棒的对象跟踪器。这将是我下一篇文章的主题,届时我将讨论一个非常流行的跟踪算法,称为……“Meanshift 算法”——敬请期待。
致谢
对于使用的任何第三方代码或材料,请参阅第一部分的“兴趣点”。
历史
- 版本 1.0。