CamShift算法(利用目标直方图)进行目标跟踪

CamShift算法是对MeanShift算法的改进算法,可以在跟踪的过程中随着目标大小的变化实时调整搜索窗口大小,对于视频序列中的每一帧还是采用MeanShift来寻找最优迭代结果。

下面的代码是这个博客中来的,自己添加了一些注释

Mat image;
Mat rectImage;
Mat imageCopy; // 绘制矩形框时用来拷贝原图的图像
bool leftButtonDownFlag=false; // 左键单击后视频暂停播放的标志位
Point originalPoint; // 矩形框起点
Point processPoint; // 矩形框终点

Mat targetImageHSV;
int histSize=200;
float histR[]={0, 255};
const float * histRange=histR;
int channels[]={0,1};
Mat dstHist;
Rect rect;
vector<Point> pt; // 保存目标轨迹
void onMouse(int event, int x, int y, int flags, void * ustc); // 鼠标回调函数


int main(int argc, char*argv[])
{
    VideoCapture cap(0);
    double delay = (double)1000/30;
    namedWindow("跟踪木头人",WINDOW_AUTOSIZE);
    setMouseCallback("跟踪木头人", onMouse);
    while (true)
    {
        if(!leftButtonDownFlag) // 判定鼠标左键没有按下去,采取播放视频,否则暂停
        {
            cap >> image;
        }

        if(!image.data||waitKey(delay)=='q')
            break;

        if(originalPoint!=processPoint && !leftButtonDownFlag)
        {
            Mat imageHSV;
            Mat calcBackImage;
            cvtColor(image, imageHSV, COLOR_BGR2HSV);

            // // 用回调函数中计算得到的目标直方图,在图像中计算存在的特征概率分布(反向投影)
            calcBackProject(&imageHSV,2, channels,dstHist,calcBackImage,&histRange);

            // // 运行camshift 算法
            TermCriteria criteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 100, 0.001);
            CamShift(calcBackImage, /*输入图像直方图的反向投影图*/
                     rect,         /*要跟踪目标的初始位置矩形框*/ /*也是实时跟踪目标后的位置*/
                     criteria);   /*s算法结束条件*/

            // camShift更新后的目标,计算目标直反图,用于下一帧分析
            Mat imageROI = imageHSV(rect);
            targetImageHSV = imageHSV(rect);
            calcHist(&imageROI,2, channels, Mat(),dstHist,1, &histSize, &histRange);
            normalize(dstHist, dstHist, 0.0, 1.0, NORM_MINMAX); // 归一化


            rectangle(image, rect, Scalar(255,0,0), 3); // 目标绘制

            // 绘制目标移动轨迹
            pt.push_back(Point(rect.x + rect.width/2, rect.y+rect.height/2));
            for (int i=0; i<pt.size()-1; i++)
            {
                line(image, pt[i], pt[i+1], Scalar(0, 255, 0), 2.5);
            }
        }
        imshow("跟踪木头人",image);
        waitKey(100);

    }
    return 0;
}

// 鼠标回调函数
void onMouse(int event, int x, int y, int flags, void * ustc)
{
    if (event == EVENT_LBUTTONDOWN) // 左键按下
    {
        leftButtonDownFlag=true;  // 标志位
        originalPoint=Point(x,y);  // 设置左键按下点的矩形起点
        processPoint=originalPoint;
        if (pt.size() > 0) pt.erase(pt.begin(), pt.end()); // 清空轨迹
    }

    if (event == EVENT_MOUSEMOVE&&leftButtonDownFlag) // 左键按下的时候鼠标移动
    {
        imageCopy=image.clone();
        processPoint=Point(x,y);
        if(originalPoint != processPoint)
        {
            //在复制的图像上绘制矩形
            rectangle(imageCopy, originalPoint, processPoint, Scalar(255,0,0), 2);
        }
        imshow("跟踪木头人", imageCopy);
    }

    if (event == EVENT_LBUTTONUP) // 左键抬起
    {
        leftButtonDownFlag=false;

        // 获得目标框区域
        rect = Rect(originalPoint, processPoint);
        rectImage=image(rect);
        imshow("sub Image", rectImage);

        // 目标框区域转HSV
        cvtColor(rectImage, targetImageHSV, COLOR_BGR2HSV);
        imshow("targetImageHSV", targetImageHSV);

        // 获得目标框直方图(用于后续分析)
        calcHist(&targetImageHSV, 2, channels, Mat(), dstHist, 1, &histSize, &histRange);
        normalize(dstHist, dstHist, 0, 255, NORM_MINMAX); // 归一化
//        imshow("dstHist", dstHist);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值