OpenCV学习 day7 视频分析

第九章

        对输入轴帧实时处理,这可以为动态的机器或者设备提供动力,让设备监视周围的环境,寻找感兴趣的对象,运动,图案,颜色等等。我们只需要确保正确的将每一帧都读取到cv::Mat类实例中,然后作为一个又一个图像传递到这些函数中。本章学习MeanShift算法和CamShift算法来实现实时对象跟踪,并且继续对视频进行运动分析。背景/前景检测是也是本章学习的重点。

9.1 理解直方图

        在灰度图像中,直方图图形就是表示在灰度图像中包含每个可能强度(0-255之间的值)的像素数量。在RGB彩色图像中,直方图可以是三个图,每个图表示包含所有可能的红色、绿色或者蓝色强度的像素数量,注意:像素值不一定表示颜色或强度值。例如在HSV(色调,饱和度,值)颜色空间的颜色图像中,直方图将包含色调、饱和度以及数值数据。

        OpenCV中的直方图使用calcHist函数进行计算,并储存在Mat类中,使用以下参数:

        images\input images:用来计算的图像

        nimagess:第一个参数中的图像数量

        channels:数组,包含用于计算直方图通道的索引号

        mask:用来掩膜图像,以便只输入图像的一部分计算直方图,不需要则传入空Mat类

        hist:是输出直方图,是Mat类,用计算的直方图填满

        dims:直方图的维度 1-32之间取值

        histSize:是包含的直方图每一维大小的数组,或者称为组的大小

        ranges:数组的数组,包含每个通道值的范围

        uniform:布尔标志,标记直方图是否均匀

        accumulate:布尔标志,用于标记计算之前是否应该清除直方图

例子:

int bins = 256;

int channels[] = {0};

int histSize[] = { bins };

float rangeGray[] = {0,255};

const float* ranges[] = { rangeGray };

Mat histogram;

calcHist(&grayImg,

                1,              //number of images

                channels,

                Mat(),        //no masks, an empty Mat

                histogram,

                1,               //dimensionality

                histSize,

                ranges,

                true,           //uniform

                false);         //not accumulate

使用下列代码绘制储存在这个Mat类中的每个值,输出将是柱状图中的直方图可视化:

        将直方图中的每个值绘制为一个矩形,对每个矩形而言,左上角的点用图像的value变量和宽除以组(bin)数(即histSize)来计算。     

double maxVal = 0;

minMaxLoc(histogram,

                    Q_NULLPTR,   //don't need min

                    &maxVal,

                    Q_NULLPTR,   //don't need index min

                    Q_NULLPTR);  //don't need index max

outputImage.creat(640,        //any image width

                                360,      //any image height

                                CV_8UC(3));

outputImage = Scalar::all(128);     //empty grayish image

Point p1(0,0),p2(0,outputImage.rows-1);

for(int i = 0; i < bins; i++){

        float value = histogram.at<float>(1,0);

        value = manVal - value;       //invert

        value = value / maxVal * outputImage.rows; //scale

        p1.y = value;

        p2.x = float( i + 1) * float(outputImage.cols)  //float( bins );

        rectangle(outputImage,

                        p1,

                        p2,

                        Scalar::all(0),

                        CV_FILLED);

        p1.x = p2.x;

}

         如何分割图像得到三个Mat类,每个类代表一个单独的通道:

vector<Mat> planes;

split(inputImage, planes);

9.2 理解反投影图像

         可以使用直方图的反投影对图像进行修改。

//计算反投影

calcBackProject(&image,

                                1,

                                channels,

                                histogram,

                                backprojection,

                                ranges);

 //对直方图结果标准化,否则反投影数值会溢出

normalize(histogram,

                histogram,

                0,

                255,

                NORM_MINMAX);    // 将值控制在0-255

         转换为HSV颜色空间

Mat hsvImg;

cvtColor(inputImage, hsvImg, CV_BGR2HSV);

9.2.1 直方图比较 

         使用calcHist函数计算出的两个直方图,可以通过使用compareHist方法进行相互比较,以找出二者之间的距离或者差异(散度),compareHist接受的参数:

        HISTCMP_CORREL、HISTCMP_CHISQR、HISTCMP_INTERSECT、

        HISTCMP_BHATTACHARYYA、HISTCMP_HELLINGER、HISTCMP_CHISQR_ALT、

        HISTCMP_KLDIV

        下面这个例子是使用现存方法来计算两张图像之间的差异: 

Mat img1 = imread();

Mat img2 = imread();

float range[] = { 0, 255 };

const float* ranges[] = { range };

int bins[] = { 100 };

Mat hist1,hist2;

calcHist(&img1, 1, 0, Mat(), hist1, 1, bins, ranges );

calcHist(&img2, 1, 0, Mat(), hist2, 1, bins, ranges );

qDebug()<<compareHist(hist1, hist2, HISTCMP_CORREL);

qDebug()<<compareHist(hist1, hist2, HISTCMP_CHISQR);

qDebug()<<compareHist(hist1, hist2, HISTCMP_INTERSECT);

qDebug()<<compareHist(hist1, hist2, HISTCMP_BHATTACHARYYA);

qDebug()<<compareHist(hist1, hist2, HISTCMP_HELLINGER);

qDebug()<<compareHist(hist1, hist2, HISTCMP_KLDIV);

9.2.2 直方图均衡化

        图像的直方图可以用来调整图像的亮度和对比度。OpenCV提供了称为equalizeHist的函数,他可以在内部计算一个给定图像的直方图,然后正则化此直方图,并计算直方图的积分(所有bin之和),最后使用更新的直方图作为一个查找表来更新输入图像的像素,从而得到输入图像中的标准化亮度和对比度。

equalizeHist(image, equalizedImg);

9.3 MeanShift算法和CamShift 

        MeanShift有一个非常使用的定义:查找反投影图像上的对象 

        原理就是将一个反投影图像中的白色像素看做二维平面上的散点,MeanShift就是一个迭代方法,用来寻找平面上点分布最密集的地方,用一个小方框不断迭代寻找质量中心,直到需要的移动小于给定的阈值或者达到最大迭代次数。

9.4 背景/前景检测 

        也叫做背景差分,该方法可以用在图像中区域分运动或变化区域,而不是那些或多或少的恒定或静态区域。

        OpenCV中默认安装了BackgroundSubtractorKNNBackgroundSubtractorMOG2两个方法,这些类也来自cv::Algorithm类。

        Ptr<BackgroundSubtractorMOG2> subtractor = createBackgroundSubtractorMOG2();

        注意,背景差分只需要构造BackgroundSubtractorMOG2类和调用apply函数,在使用时再没有其他操作。可以使用默认参数,也可以自行修改:

        history:默认为500,是影响背景差分算法的最后帧数

        varThreshold:默认为16,是算法的方差阈值

        detectShadows:默认情况为ture,可用于忽略或者计算检测到的阴影变化

        切换类很简单,就像下面这样:

Ptr<BackgroundSubtractorKNN> subtractor = createBackgroundSubtractorKNN();

         大部分参数与上文函数相同:

        history:与之前相同 (增加history值,有助于检测更小的运动)

        detectShadows:也与之前相同

        dist2Threshold:默认值为400.0,是像素和样本之间距离平方的阈值

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值