【计算机视觉】借助图像直方图来检测特定物(MeanShift、CamShift算法)

直方图引入

直方图是一个简单的表,它给出了一幅图像或一组图像中拥有给定数值的像素数量。因此,灰度图像的直方图有256个条目(或称为容器)。0号容器给出值为0的像素数目,1号容器给出值为1的像素个数,以此类推。

直方图反投影

直方图是图像内容的一个重要特性。如果一幅图像的区域中显示的是一种独特的纹理或是一个独特的物体,那么这个区域的直方图可以看做一个概率函数,它给出的是某个像素属于该纹理或物体的概率。这使得我们可以借助图像的直方图来检测特定的内容。

反投影直方图的方法是一种把目标概率分布映射到观测图像的简单方法。其作用是,替换一个输入图像中每一个像素值,使其变成感兴趣区域(ROI)的直方图中对应的概率值

其在opencv2的C++ API为:

cv::calcBackProject(&image,
    1,                //一幅图像
    channels,        //通道数量
    histogram,        //进行反投影的直方图
    result,            //生成的反投影图像
    ranges,            //每个维度的值域
    255.0              //缩放因子
    );

HSV颜色空间

HSV(Hue,Saturation,Value)是根据颜色的直观特性(色调H,饱和度S,亮度V)创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。

色调H

用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;

饱和度S

取值范围为0.0~1.0,值越大,颜色越饱和。

亮度V

取值范围为0.0(黑色)~1.0(白色)。

HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。

HSV颜色空间

hue表示颜色的相位角,取值范围是0---360;S表示颜色的饱和度;S为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率,通俗点讲,S表示的是某种颜色的“纯度”, S取值越大,表示色彩越纯,取值越小,表示色彩越灰。V表示色彩的明亮程度,范围从0到1。V等于0表示圆锥的底部定点,也就是黑色,V等于1表示圆锥的顶面,当V=1并且S=0时表示纯白色。

HSV圆锥

应用示例:建立颜色概率模型

由于我们要进行的是通过一种算法来实现检测特定物体(尤其是人脸)的功能,所以通过这个示例的引入,来为后面介绍Mean Shift算法打下基础。

因为肤色在颜色空间的分析相当集中,但会受到光照和人种的影响。为了减少肤色收光照强度的影响,通常将颜色空间从RBG转换到亮度和色度分离的某个颜色空间,如HSV颜色空间,然后放弃亮度分量。

采集肤色样本,吧肤色样本中的每个像素从RGB空间转换到HSV空间,统计其H分量的直方图,并对该直方图进行归一化处理,就可以得到肤色在H空间的概率分布,该概率分布就是所需的跟踪模式。

具体步骤如下:

1、将观测图像中每个像素从RGB空间映射到HSV空间,按公式计算H分量大小建立起统计直方图

2、根据直方图进行反向投影运算,即,将观测图像中的每个像素值,用其H分量在已建立的统计直方图中对应的值代替

3、所得到输出图像就是观测图像的颜色概率分布图像

现在,用程序演示直方图反投影算法中使用颜色信息。

class ContentFinder
{
private:
    float hranges[2];
    const float* ranges[3];
    int channels[3];
    float threshold;
    cv::MatND histogram;

public:
    ContentFinder():threshold(-1.0f){
        ranges[0] = hranges;//所有通道的值相同
        ranges[1] = hranges;
        ranges[2] = hranges;
    }

    //设置直方图的阈值[0,1]
    void setThreshold(float t)
    {
        threshold = t;
    }

    //获取阈值
    float getThreshold()
    {
        return threshold;
    }

    //设置参考直方图
    void setHistogram(const cv::MatND& h)
    {
        histogram = h;
        cv::normalize(histogram,histogram,1.0);//输入直方图必须是归一化后的
    }

    cv::Mat find(const cv::Mat& image,
                float minValue,float maxValue,
                int* channels,int dim);

};

cv::Mat ContentFinder::find(const cv::Mat& image,
                            float minValue,float maxValue,
                            int* channels,int dim)
{
    cv::Mat result;
    hranges[0] = minValue;
    hranges[1] = maxValue;

    for(int i=0;i<dim;i++)
    {
        this->channels[i] = channels[i];
    }
    cv::calcBackProject(&image,1,    //输入图片
                        channels,    //所有通道列表
                        histogram,    //直方图
                        result,        //反投影的结果
                        ranges,        //值域
                        255.0        //缩放因子
                        );
    //进行阈值化以得到二值图像
    if(threshold > 0.0)
        cv::threshold(result,result,255*threshold,255,cv::THRESH_BINARY);
    return result;
}

均值漂移(Mean Shift)算法

假设我们现在知道物体的近似位置,概率映射可用于找到的对象的确切位置。最有可能的位置是在已知窗口区域中得到最大概率的位置。因此,如果我们从最初的位置开始,并且迭代移动,边可以找到精确的位置。这便是均值漂移算法所要完成的任务。

原理

均值漂移算法以迭代的方式锁定概率函数的局部最大值。它主要是寻找预定义窗口中数据点的重心点,或者说加权平均值。该算法将窗口中心移动到数据点的重心处,并重复这个过程直到窗口重心收敛到一个稳定点。

从数学角度上说,Mean Shift算法利用概率密度的梯度爬升来寻找局部最优。当输入一个图像的范围,然后根据反向投影图和输入的方框进行Mean Shift迭代,它是向重心移动,即向反向投影图中概率大的地方移动,所以始终会移动到目标上,Mean Shift算法是一个变步长的梯度上升算法

现考虑一个点集(这可以是经过直方图反投影的像素点的分布),现有一个小窗口,需要将其移至像素点最密集的区域。如下图所示:

meanshift_basics

最初的窗口表示为C1这个大的蓝色圆圈,其原始中心为"C1_o"。随着这个中心点向局部密度较大的区域移动,得到了"C1_r"的中心点。随着这个过程的迭代,最终会得到一个最大像素点分布的区域,即C2,该区域包含了最多数量的点。

总结下来,Mean Shift的基本思路是,从每个像素开始,首先估计有相似颜色的邻近像素点的密度(局部密度)的梯度,而后利用迭代算法求出局部密度的峰值(即重心点),把能够聚类到同一个峰值点的所有像素点划分成一个区域。

基本流程

(1)选择跟踪窗口的大小和初始位置。在Mean Shift跟踪算法中,核窗宽(即核函数的定义域的大小,就是搜索窗口的大小)的大小起着非常重要的作用。因为它不但决定了参与Mean Shift迭代的样本数量,而且也反映了跟踪窗口的大小。通常,核窗宽由初始跟踪窗口的尺寸决定,而且在整个跟踪过程中不再发生变化。

meanshift_step1

(2)计算跟踪窗口内的质心(或重心)。在离散二维(2D)概率分布图像中,计算某窗口的质心同物理上计算某物体的质心一样,即利用窗口的零阶矩M00和(x,y)的一阶矩(M10,M01)之间的关系,计算得到窗口的质心。

公式

meanshift_step2

(3)调整跟踪窗口的中心到质心;

(4)重复第二步和第三步,直到跟踪窗口中心和质心“会聚”,即每次窗口移动的距离小于一定的阈值。

meanshift_step3

一般一个图像就是个矩阵,像素点均匀的分布在图像上,就没有点的稠密性。所以怎样来定义点的概率密度,这才是最关键的。而我们可以根据像素点的颜色相近来定义为概率密度高。

其作为人脸跟踪的应用由下图演示:

meanshift_face

优点

Mean Shift作为一种高效的模式匹配算法,由于不需要进行全局搜索,而且搜索精度高,已经广泛地应用在各种模式识别、实时可视跟踪等领域。

不足

缺乏必要的模型更新方法;整个跟踪过程中跟踪窗口的大小保持不变,当目标存在尺度变化的时候会导致尺度定位不准确。

连续自适应的Meanshift(CamShift)算法

Bradski根据Mean Shift算法的不足,提出了Camshift算法。CamShift算法,即Continuously Adaptive Mean-Shift算法,基本思想就是对视频图像的多帧进行MeanShift运算,将上一帧结果作为下一帧的初始值,迭代下去。

该算法采用不变矩对目标的尺寸进行估算,实现了连续自适应地调整跟踪窗口的大小和位置,并将其应用在对连续彩色图像序列中的运动目标的快速跟踪。

简单点说,Mean Shift是针对单张图片寻找最优迭代结果,而Camshift则是针对视频序列来处理,并对该序列中的每一帧图片都调用Mean Shift来寻找最优迭代结果。正是由于Camshift针对一个视频序列进行处理,从而保证其可以不断调整窗口的大小,如此一来,当目标的大小发生变化的时候,该算法就可以自适应地调整目标区域继续跟踪。

原理

Camshift算法首先根据跟踪目标颜色概率模型,将视频图像转化为概率分布图像(PDI),并初始化一个矩形搜索窗口,对每一帧PDI图像利用Mean Shift算法搜索目标匹配的最优区域,并根据搜索区域的不变矩估算跟踪目标的中心和大小,保存和输出当前帧搜索结果,并且用当前帧搜索结果作为下一帧图像初始化搜索窗口。如此循环,即可实现对目标的连续跟踪。Camshift算法是一种动态变化的非参数密度函数梯度估计方法

具体步骤

(1)创建指定窗口的颜色概率分布图,初始化一个搜索窗口W,其大小为S

camshift_1

由上图左图的直方图可以知道,选定区域最常见的色度范围。假设新的视频帧到来时,每个像素点的色度值被检测,通过直方图给出该像素点的概率值。

(2)利用Mean Shift算法使搜索窗口“收敛";在2D概率分布图像中,计算搜索窗口的质心;调整搜索窗口的中心到计算的质心位置。重复该过程,直到“收敛”(即中心的位移小于给定的阈值)

(3)重新设置搜索窗口的大小S并计算跟踪目标的输出参数,并用新的窗口大小初始化下一帧Mean Shift的搜索窗口

camshift_2

上图表示通过Camshift算法跟踪人脸时计算一个视频帧图像中可能存在人脸的图像。黑色像素概率值最低,白色像素概率值最高,灰色像素介于二者之间。

(4)跳转到第二步进行下一帧的循环

下面是Camshift算法的人脸跟踪演示:

camshift_face

参考资料

OpenCV 3.0.0-dev documentation

OpenCV 2 计算机视觉编程手册,科学出版社

基于OpenCV的人脸跟踪识别系统研究,雷静,西安电子科技大学,硕士学位论文,2010

Meanshift,聚类算法

时间: 2024-10-11 18:03:00

【计算机视觉】借助图像直方图来检测特定物(MeanShift、CamShift算法)的相关文章

opencv2对读书笔记——反投影直方图以检测待定的图像内容

一些小概念 1.直方图是图像内容的一个重要特性. 2.如果一幅图像的区域中显示的是一种独特的纹理或是一个独特的物体,那么这个区域的直方图可以看作是一个概率函数,它给出的是某个像素属于该纹理或物体的概率. 3.反投影直方图的作用是在于替换一个输入图像中每一个像素值,使其变成归一化直方图中对应的概率值. 这是一个什么样的过程 名字听起来感觉很高端,其实这个一个很简单的过程. 1.首先我们截取一个区域,作为目标区域. 2.然后将目标区域取直方图,并将其直方图归一化,并得到这个区域的概率. 3.利用ca

matlab工具箱之人眼检测+meanshift跟踪算法--人眼跟踪

Viola-Jones 人眼检测算法+meanshift跟踪算法 这次的代码是对视频中的人眼部分进行检测加跟踪,检测用的是matlab自带的人眼检测工具箱 下面是matlab官网介绍这个算法的一些东西: http://cn.mathworks.com/help/vision/examples/face-detection-and-tracking-using-camshift.html?searchHighlight=Viola-Jones http://cn.mathworks.com/hel

paper 27 :图像/视觉显著性检测技术发展情况梳理(Saliency Detection、Visual Attention)

1. 早期C. Koch与S. Ullman的研究工作. 他们提出了非常有影响力的生物启发模型. C. Koch and S. Ullman . Shifts in selective visual attention: Towards the underlying neural circuitry. Human Neurobiology, 4(4):219-227, 1985. C. Koch and T. Poggio. Predicting the Visual World: Silenc

OpenCV成长之路:图像直方图的应用

2014-04-11 13:57:03 标签:opencv 图像 直方图 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://ronny.blog.51cto.com/8801997/1394118 正如第4篇文章所说的图像直方图在特征提取方面有着很重要的作用,本文将举两个实际工程中非常实用的例子来说明图像直方图的应用. 一.直方图的反向映射. 我们以人脸检测举例,在人脸检测中,我们第一步往往需要先提取图像中皮肤区域来缩小人脸的检

OpenCV入门教程之五 图像直方图的应用

正如第4篇文章所说的图像直方图在特征提取方面有着很重要的作用,本文将举两个实际工程中非常实用的例子来说明图像直方图的应用. 一.直方图的反向映射 我们以人脸检测举例,在人脸检测中,我们第一步往往需要先提取图像中皮肤区域来缩小人脸的检测范围,这一般获得皮肤的颜色范围还需要定义阈值并不断的调整,实际中参数太多而不容易控制. 这里我们就可以考虑用直方图的反射映射. 1,收集人脸皮肤样本. 2,拼合样本并计算其颜色直方图. 3,将得到的样本颜色直方图反射映射到待检测的图片中,然后进行阈值化即可. 这里为

图像局部特征点检测算法综述与应用举例

研究图像特征检测已经有一段时间了,图像特征检测的方法很多,又加上各种算法的变形,所以难以在短时间内全面的了解,只是对主流的特征检测算法的原理进行了学习.总体来说,图像特征可以包括颜色特征.纹理特等.形状特征以及局部特征点等.其中局部特点具有很好的稳定性,不容易受外界环境的干扰,本篇文章也是对这方面知识的一个总结. 本篇文章现在(2015/1/30)只是以初稿的形式,列出了主体的框架,后面还有许多地方需要增加与修改,例如2013年新出现的基于非线性尺度空间的KAZE特征提取方法以及它的改进AKAT

opencv图像直方图均衡化及其原理

直方图均衡化是什么有什么用 先说什么是直方图均衡化,通俗的说,以灰度图为例,原图的某一个像素为x,经过某个函数变为y.形成新的图.新的图的灰度值的分布是均匀的,这个过程就叫直方图均衡化. 图像直方图均衡化作用:用来增强对比度. 这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候.通过这种方法,亮度可以更好地在直方图上分布.这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能. 这种方法对于背景和前景都太亮或者太

图像肤色初步检测实现

肤色检测输出结果中有许多瑕疵,待于进一步处理(如:滤波操作.....).在此贴出几种图像肤色检测相关代码,供大家参考. 第一种:RGB color space // skin region location using rgb limitation void ImageSkin::ImageSkinRGB(IplImage* rgb,IplImage* _dst) { assert(rgb->nChannels==3&& _dst->nChannels==3); static

图像直方图均衡化增强opencv与C语言版

本文实现彩色图像的全局直方图均衡.分别对R/G/B三通道均衡,读写图片采用OpenCV.代码如下: #include <opencv2/opencv.hpp> //#include <cv.h> //#include <cxcore.h> //#include <highgui.h> #include <time.h> #include <stdio.h> #include <math.h> #include "