同一窗口下基于KCF 目标跟踪和基于模板匹配的目标跟踪效果比较

2 篇文章 0 订阅
1 篇文章 0 订阅

参考图像跟踪(四)KCF算法
我们知道KCF 是一个效率和速度都比较好的一种跟踪算法。而模板匹配的目标跟踪是比较笨的一种方式,因此有必要放在一起比比看。代码已经在下面!
大家可以自己去比较!
当然基本条件是要有特殊库,要基于opencv 3.0以上的配置!
实现用鼠标选取一个跟踪区域,然后就有不同颜色的框来指示跟踪效果了。
总得来说,KCF 效果好些,特别是当跟踪目标跑到录像机外面去的时候,也有作用。

// ConsoleApplication1.cpp : Defines the entry point for the console application.
//


#include "stdafx.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <math.h>

#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
//#include "kcftracker.hpp"
#include <opencv2/tracking.hpp>
using namespace std;
using namespace cv;
cv::Mat org, dst, img, tmp;
float xMin = 0.0;
float yMin = 0.0;
float width = 0.0;
float height = 0.0;
bool CHOSE = false;
bool STATE_1 = false;
bool STATE_2 = false;
bool STATE_3 = false;
bool isKCF = false;
void templatematchtracking(Mat frame, Mat &templ, Rect2d &rect);
void on_mouse(int event, int x, int y, int flags, void *ustc)//event
{
    static Point pre_pt(-1, -1);
    static Point cur_pt(-1, -1);
    char temp[16];
    if (event == CV_EVENT_LBUTTONDOWN)
    {
        // 使用四个顶点计算出目标框
        org.copyTo(img);
        sprintf_s(temp, "(%d,%d)", x, y);
        pre_pt = Point(x, y);
        xMin = x;
        yMin = y;
        putText(img, temp, pre_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);
        circle(img, pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);
        imshow("img", img);
    }
    else if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))
    {
        img.copyTo(tmp);
        sprintf_s(temp, "(%d,%d)", x, y);
        cur_pt = Point(x, y);
        putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));
        imshow("img", tmp);
        STATE_2 = true;
    }
    else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))
    {
        img.copyTo(tmp);
        sprintf_s(temp, "(%d,%d)", x, y);
        cur_pt = Point(x, y);
        putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));
        rectangle(tmp, pre_pt, cur_pt, Scalar(0, 255, 0, 0), 5, 8, 0);
        imshow("img", tmp);
    }
    else if (event == CV_EVENT_LBUTTONUP)//
    {
        org.copyTo(img);
        sprintf_s(temp, "(%d,%d)", x, y);
        cur_pt = Point(x, y);
        putText(img, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));
        circle(img, pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);
        rectangle(img, pre_pt, cur_pt, Scalar(0, 255, 0, 0), 1, 8, 0);//
        imshow("img", img);
        img.copyTo(tmp);
        //
        width = abs(pre_pt.x - cur_pt.x);
        height = abs(pre_pt.y - cur_pt.y);
        if (width == 0 || height == 0)
        {
            printf("width == 0 || height == 0");
            return;
        }
        CHOSE = true;
        Rect2d rect = Rect2d(min(cur_pt.x, pre_pt.x), min(cur_pt.y, pre_pt.y), width, height);
        rect &= Rect2d(0, 0, org.cols, org.rows);
        dst = org(rect);
        // namedWindow("dst");
        // imshow("dst",dst);
        // waitKey(0);
        STATE_3 = STATE_1 = STATE_2 = false;
    }
}
#define HEIGHT   0.97
#define THETA  60
#define FOCUS   1100
#define PI  3.141592653
void adjustPosition(float  x, float  y, float &actual_x, float &actual_y) {
    float move_pixel_x = x - (xMin + width / 2);
    float move_pixel_y = y - (yMin + height / 2);
    float S = HEIGHT / cos(THETA*PI / 180);
    float DX = (S*move_pixel_x) / FOCUS;
    float DY = (S*move_pixel_y) / FOCUS;
    actual_x = DX;
    actual_y = DY / cos(THETA*PI / 180);
}
int main()
{
    // save_dir的路径,用于读取图像
    string save_dir = "d:\1.jpg";
    VideoCapture cap(0);
    if (!cap.isOpened())
    {
        return -1;
    }
    // 当前帧
    Mat frame;
    Mat last_gray;
    Mat first;
    Mat cur_gray;
    bool HOG = true;// 是否使用hog特征
    bool FIXEDWINDOW = false;// 是否使用修正窗口
    bool MULTISCALE = true;// 是否使用多尺度
    bool SILENT = false;// 是否不做显示
    bool LAB = false;// 是否使用LAB颜色
    float sum_error_ncc = 0.0;
    int err_num = 0;
    float mean_error_ncc = 0.0;
    bool LOST = false;
    // 创建KCF跟踪器
    // KCFTracker tracker(HOG, FIXEDWINDOW, MULTISCALE, LAB);
    // KCFTracker tracker_redetect(HOG, FIXEDWINDOW, MULTISCALE, LAB);
    // create the tracker
    Ptr<Tracker> tracker = Tracker::create("KCF");


    Rect2d templRect,kcfRect;// 跟踪结果目标框
    Mat templmat;
    bool stop = false;
    bool FIRST = true;
    int nFramesNochose = 0;
    int nFrames = 0;// 帧号计数
    while (!stop)
    {
        cap >> frame;//获取图像
        org = frame;//?
        org.copyTo(img);
        org.copyTo(tmp);
        if (!CHOSE) {
            namedWindow("img");
            imshow("img", frame);
            setMouseCallback("img", on_mouse, 0);
        }
        if (CHOSE && FIRST)
        {
            templRect.x = xMin;
            templRect.y = yMin;
            templRect.width = width;
            templRect.height = height;
            templRect &= Rect2d(0, 0, org.cols, org.rows);
            kcfRect = templRect;
            printf("Initial  Box : %f, %f, %f, %f\n", xMin, yMin, width, height);
            // 使用第一帧和目标框来初始化跟踪器
            tracker->init(frame, kcfRect);
            cvtColor(frame, last_gray, CV_RGB2GRAY);
            rectangle(frame, kcfRect, Scalar(0, 255, 255), 5, 8);
            templmat = last_gray(templRect);
            FIRST = false;
        }
        else if (CHOSE && !FIRST)
        {
            //double start = clock();
            cvtColor(frame, last_gray, CV_RGB2GRAY);
            //if (isKCF)
            {
                // 更新当前帧的结果
                tracker->update(frame, kcfRect);
            }
            //else
            {
                templatematchtracking(frame, templmat, templRect);
            }
            sum_error_ncc += mean_error_ncc;
            err_num++;
            //double finish = clock();
            //////////////////////////////////////////////////////////////////
            //printf("TIME : %f ms!\n", (finish - start) * 1000 / CLOCKS_PER_SEC);
            Scalar color1,color;
            if (mean_error_ncc < 0.1)
            {
                color = Scalar(0, 255, 0, 0);
                color1 = Scalar(255, 0, 0,0);
            }
            else
            {
                color = Scalar(0, 0, 255, 0);
                color1 = Scalar(0, 255, 125, 0);
            }
            rectangle(frame, templRect, color, 3, 8);
            rectangle(frame, kcfRect, color1, 2, 8);
            float actual_x = 0.0;
            float actual_y = 0.0;
            char buff[50] = { '\0' };
            adjustPosition((templRect.x + templRect.width / 2), (templRect.y + templRect.height / 2), actual_x, actual_y);
            sprintf_s(buff, "adjust (x : %.5f, y : %.5f)", actual_x, actual_y);
            putText(frame, buff, Point(templRect.x, templRect.y - 20), FONT_HERSHEY_SIMPLEX, 0.5, color);
        }
        if (CHOSE && !FIRST) {
            cvDestroyWindow("img");
            namedWindow("tracking");//
            imshow("tracking", frame);
        }
        else
            imshow("img", frame);
        if (waitKey(1) == 27)
            break;


        if (CHOSE)
            nFrames++;
    }

    return 0;
}


void templatematchtracking(Mat frame, Mat &templ, Rect2d &rect)
{
    Mat grayFrame;
    cvtColor(frame, grayFrame, CV_RGB2GRAY);//由于模板匹配只支持单通道,因此需要转为灰度图像

                                            //设置搜索窗口大小,按照移动的速度,设置为原来兴趣窗口的2倍大小,也可以使很大。
    Rect2d findRect;
    findRect.width = min((int)rect.width * 2, frame.cols);
    findRect.height = min((int)rect.height * 2, frame.rows);
    findRect.x = rect.x + rect.width * 0.5 - findRect.width * 0.5;
    findRect.y = rect.y + rect.height * 0.5 - findRect.height * 0.5;
    findRect &= Rect2d(0, 0, frame.cols, frame.rows);

    Mat matchResult;
    matchTemplate(grayFrame(findRect), templ, matchResult, CV_TM_CCOEFF);//使用归一化相关系数匹配法,最强匹配法,值最大表示匹配最好 1表示最好。

    double maxVal = 0;
    Point maxLoc;
    //筛选出最大匹配点
    minMaxLoc(matchResult, 0, &maxVal, 0, &maxLoc);
    cout << "the maxVal =" << maxVal << endl;


    //找到下一次模板新的起始点  

    rect.x = maxLoc.x + findRect.x;
    rect.y = maxLoc.y + findRect.y;
    //更新模板,这样表示可能导致当初跟踪的目标会发生变化。 
    rect &= Rect2d(0, 0, frame.cols, frame.rows);
    templ = grayFrame(rect);
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值