zoukankan      html  css  js  c++  java
  • 萌新的opencv入门2--meanshift物体追踪

    1 Meanshift原理

      meanshift算法,其本质还是一种梯度下降法求最值方法。我认为可以这样表述,我们在取一个点(比如区域的某个角)作为区域的代表,将区域与目标相似程度数值化(或者机器学习中,将此点一定大小范围内匹配点的数目),作为这点的值,这样在图像上就可以形成坐标的xy的标量场,这样再利用梯度沿着相似程度上升的方向移动,这大概是就是算法原理。

      在目标追踪中描述这个算法,我在代码实现中选择的是HSV空间中的H分量直方图分布作为目标的的特征,将追踪到的区域的直方图与目标直方图进行比较,数值化两个直方图的相似程度。然后在追踪区域的附近区域计算相似程度,一旦发现邻域中某区域(A)的相似程度有提升,就将追踪区域更新为A,并在A邻域重复上述操作。直到追踪区域与目标的相似程度达到局部最大值停止迭代。

    2 出现的问题

      1 容易陷入局部最优值。

      梯度下降法的通病,表现为追踪到颜色相近的物体。

      想到的解决方法:设置相似度的阈值,假如某邻域低于某个阈值将从此邻域跳出。(未在代码中体现)

      2 梯度下降收敛速度过慢。

      假如在区域邻域计算相似度的过程花费时间,物体移动速度又较快,很容易就会失去对物体的跟随。

      想到的优化:考虑到物体移动应该不是无规律的,那么梯度上升的方向一定程度上代表了物体的移动方向,物体保留原来速度的可能性比较大,那么在新区域也优先计算上一区域相似度上升方向的的相似度,这样一定程度上加快了收敛速率。

    3 实现代码。

      

    // meanshifttet.cpp: 定义控制台应用程序的入口点。
    
    #include "stdafx.h"
    #include<opencv2/opencv.hpp>
    #include<math.h>
    using namespace cv;
    using namespace std;
    Point origin;
    Rect selection;
    Point track[36];
    Mat frame, trackobject, trackhsv;
    int flag = 0;
    MatND dstlist;
    static void onMouse(int event, int x, int y, int, void*)//鼠标事件,框选要追踪的物体,并计算目标物体HSV空间中H的直方图
    {
        switch (event)
        {
        case EVENT_LBUTTONDOWN:
            origin = Point(x, y);
            selection = Rect(x, y, 0, 0);
            break;
        case EVENT_LBUTTONUP:
            selection.x = MIN(x, origin.x);
            selection.y = MIN(y, origin.y);
            selection.width = std::abs(x - origin.x);
            selection.height = std::abs(y - origin.y);
            trackobject = frame(selection).clone();
            cvtColor(trackobject, trackhsv, CV_RGB2HSV);
            int  hsvnum = 30;
            float hrange[] = { 0,179 };
            const float *range[] = { hrange };
            int channels = 0;
            int size = 256; //?
            calcHist(&trackhsv, 1, &channels, Mat(), dstlist, 1, &size, range);
            flag = 1;
            break;
        }
    }
    int drawrect(Mat &img, Rect t) { //追踪框
        rectangle(img, t.tl(), t.br(), Scalar(0));
        return 1;
    }
    double calcmp(Rect a) { //计算与目标直方图的距离
        Mat select = frame(a);
        Mat newtrack = select.clone();
        Mat newtrackhsv;
        MatND newlist;
        cvtColor(newtrack, newtrackhsv, CV_RGB2HSV);
        int  hsvnum = 30;
        float hrange[] = { 0,179 };
        const float *range[] = { hrange };
        int channels = 0;
        int size = 256; 
        calcHist(&newtrackhsv, 1, &channels, Mat(), newlist, 1, &size, range);
        return compareHist(dstlist, newlist, CV_COMP_CORREL);
    }
    
    int main()
    {
        Rect newtrack;
        VideoCapture cap;
        namedWindow("meanshift", CV_WINDOW_NORMAL);
        cap.open(0);
        double step = 20; //追踪的步长,假如运动速度较快,就设置的大一点
        for (int i = 0; i < 4; i++) { //邻域方向,为计算速率的提升,仅仅选取了上下左右四个方向
            track[i].x = cos(i*1.0 / 2 * 3 .14 )*step;
            track[i].y = sin(i*1.0 / 2 * 3.14)*step;
        }
        if (!cap.isOpened())
        {
            cout << "摄像头未能正常开启
    ";
            return -1;
        }
        while (1) {
            cap >> frame;
            cvSetMouseCallback("meanshift", onMouse);
            drawrect(frame, selection);
            imshow("meanshift", frame);
    
            if (flag == 1) {
                double last = calcmp(selection);
                for (int i = 0; i < 4; i++) {
                    if ((selection.x + track[i].x) > 0&&(selection.y + track[i].y)>0&& (selection.br().y + track[i].y)<479&& (selection.br().x + track[i].x)<639) { //防止追踪框越界
                        newtrack = selection + track[i];
                    }
                    while (last < calcmp(newtrack)) {
                        if ((selection.x + track[i].x) > 0 && (selection.y + track[i].y)>0 && (selection.br().y + track[i].y)<479 && (selection.br().x + track[i].x)<639) {//防止追踪框越界
                            selection = selection + track[i]; //优先计算原梯度上升方向。
                        }
                        break;
                    }
    
                }
            }
            waitKey(30);
        }
    
        return 0;
    }
  • 相关阅读:
    高级数据类型--字典(dict)
    一些JS常用的方法
    怎样提高WebService的性能
    Microsoft Enterprise Library 5.0 系列(三)
    Microsoft Enterprise Library 5.0 系列(四)
    Expression Blend学习二UI布局
    Expression Blend学习四控件
    Expression Blend学习5控件
    Expression Blend学习动画基础
    WPF三维图形
  • 原文地址:https://www.cnblogs.com/zsl96/p/8626942.html
Copyright © 2011-2022 走看看