OpenCV 4.13.0
开源计算机视觉库 (Open Source Computer Vision)
正在加载...
正在搜索...
未找到匹配项
反向投影

上一篇教程: 直方图比较
下一篇教程: 模板匹配

原作者Ana Huamán
兼容性OpenCV >= 3.0

目标

在本教程中你将学习

  • 什么是反向投影及其用途
  • 如何使用 OpenCV 函数 cv::calcBackProject 计算反向投影
  • 如何使用 OpenCV 函数 cv::mixChannels 混合图像的不同通道

理论

什么是反向投影?

  • 反向投影是一种记录给定图像的像素与直方图模型中的像素分布拟合程度的方法。
  • 简单来说:反向投影是先计算一个特征的直方图模型,然后用这个模型在图像中查找该特征。
  • 应用示例:如果你有一个肤色直方图(例如,一个色调-饱和度直方图),那么你可以用它来在图像中查找肤色区域。

它是如何工作的?

  • 我们将通过皮肤示例来解释。
  • 假设你根据下图得到了一个皮肤直方图(色调-饱和度)。旁边的直方图将是我们的模型直方图(我们知道它代表了肤色的样本)。你应用了某种蒙版来只捕获皮肤区域的直方图:

  • 现在,假设你得到了另一只手图像(测试图像),如下所示:(及其对应的直方图):

  • 我们要做的就是利用我们的模型直方图(我们知道它代表了肤色)来检测测试图像中的肤色区域。步骤如下:
    1. 在测试图像的每个像素(即 \(p(i,j)\))上,收集数据并找到该像素对应的 bin 位置(即 \(( h_{i,j}, s_{i,j} )\))。
    2. 在对应的 bin - \(( h_{i,j}, s_{i,j} )\) - 中查找模型直方图并读取 bin 值。
    3. 将此 bin 值存储在新图像(BackProjection)中。此外,你可能需要先对模型直方图进行归一化,以便测试图像的输出对你来说是可见的。
    4. 应用以上步骤,我们为测试图像获得了以下反向投影图像:
  1. 从统计学角度来看,BackProjection 中存储的值代表了测试图像中的像素属于皮肤区域的概率,基于我们使用的模型直方图。例如,在我们的测试图像中,较亮的区域更有可能是肤色区域(正如它们实际那样),而较暗的区域概率较低(请注意,这些“暗”区域属于受到阴影影响的表面,这会影响检测)。

代码

  • 这个程序做什么?
    • 加载图像
    • 将原始图像转换为 HSV 格式,并仅分离出用于直方图的色调通道(使用 OpenCV 函数 cv::mixChannels)。
    • 允许用户输入用于直方图计算的 bin 数量。
    • 计算直方图(并在 bin 更改时进行更新)以及同一图像的反向投影。
    • 在窗口中显示反向投影和直方图。

说明

  • 读取输入图像

  • 将其转换为 HSV 格式

  • 在本教程中,我们将仅使用色调值来创建一维直方图(如果您想使用更标准的 H-S 直方图,它会产生更好的结果,请参阅上面的链接中的更高级代码)。

  • 如您所见,我们使用函数 cv::mixChannels 来仅获取 HSV 图像的通道 0(色调)。它接收以下参数:
    • &hsv: 源数组,将从中复制通道。
    • 1: 源数组的数量。
    • &hue: 目标数组,将复制通道到其中。
    • 1: 目标数组的数量。
    • ch[] = {0,0}: 指示通道如何复制的索引对数组。在这种情况下,&hsv 的色调 (0) 通道被复制到 &hue 的 0 通道(单通道)。
    • 1: 索引对的数量。
  • 创建一个滑块供用户输入 bin 值。滑块的任何更改都会调用 **Hist_and_Backproj** 回调函数。

  • 显示图像并等待用户退出程序。

  • Hist_and_Backproj 函数:初始化 **cv::calcHist** 所需的参数。 bin 的数量来自滑块。

  • 计算直方图并将其归一化到 \([0,255]\) 范围。

  • 通过调用函数 cv::calcBackProject 获取同一图像的反向投影。

  • 所有参数都已知(与计算直方图时使用的参数相同),只是我们添加了 backproj 矩阵,它将存储源图像(&hue)的反向投影。
  • 显示反向投影。

  • 绘制图像的一维色调直方图。

结果

这是使用示例图像(猜猜是什么?又是一只手)。你可以尝试不同的 bin 值,观察它们如何影响结果: