OpenCV 4.11.0
开源计算机视觉库
加载中…
搜索中…
未找到匹配项
反向投影

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

原作者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 值存储在新图像(反向投影)中。此外,您可能需要先对模型直方图进行归一化,以便您可以看到测试图像的输出。
    4. 应用上述步骤,我们得到测试图像的以下反向投影图像。
  1. 从统计学的角度来看,反向投影中存储的值表示基于我们使用的模型直方图测试图像中像素属于皮肤区域的概率。例如,在我们的测试图像中,较亮的区域更有可能是皮肤区域(实际上它们确实如此),而较暗的区域概率较小(请注意,这些“暗”区域属于表面上有一些阴影的区域,这反过来会影响检测)。

代码

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

解释

  • 读取输入图像

  • 将其转换为HSV格式

  • 本教程中,我们将仅使用色相 (Hue) 值来创建一维直方图(如果您想使用更标准的 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 值,并观察它如何影响结果: