OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
反向投影

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

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

目标

在本教程中,您将学习

理论

什么是反向投影?

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

它是如何工作的?

  • 我们以皮肤为例进行解释。
  • 假设你已经根据下图获取了一个肤色直方图(色相-饱和度)。旁边的直方图将作为我们的模型直方图(我们知道它代表肤色的一个样本)。你应用了蒙版来只捕获皮肤区域的直方图:

  • 现在,让我们想象你得到另一张手部图像(测试图像),如下图所示:(及其相应的直方图):

  • 我们要做的是使用我们的模型直方图(我们知道它代表肤色)来检测测试图像中的皮肤区域。以下是步骤:
    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格式

  • 对于本教程,我们将仅使用色相值来构建我们的一维直方图(如果你想使用更标准的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)的反向投影。
  • 显示backproj

  • 绘制图像的一维色相直方图

结果

以下是使用示例图像(你猜怎么着?另一只手)的输出。你可以调整bin值,你会观察到它如何影响结果: