本文主要是介绍用Camshift算法对指定目标进行跟踪,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原理
Camshift算法是Continuously Adaptive Mean Shift algorithm的简称。
它是一个基于MeanSift的改进算法。它首次由Gary R.Bradski等人提出和应用在人脸的跟踪上,并取得了不错的效果。因为它是利用颜色的概率信息进行的跟踪。使得它的执行效率比較高。 Camshift算法的过程由以下步骤组成:
(1)确定初始目标及其区域;
(2)计算出目标的色度(Hue)分量的直方图;
(3)利用直方图计算输入图像的反向投影图(后面做进一步的解释);
(4)利用MeanShift算法在反向投影图中迭代收索,直到其收敛或达到最大迭代次数。并保存零次矩。
(5)从第(4)步中获得收索窗体的中心位置和计算出新的窗体大小。以此为參数,进入到下一幀的目标跟踪。(即跳转到第(2)步);
代码
#include "stdafx.h" #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp"#include <iostream> #include <ctype.h>using namespace cv; using namespace std;Mat image;bool backprojMode = false; bool selectObject = false; int trackObject = 0; bool showHist = true; Point origin; Rect selection(0,0,50,50);static void onMouse( int event, int x, int y, int, void* ) {switch( event ){case CV_EVENT_LBUTTONDOWN:origin = Point(x,y);selection = Rect(x,y,0,0);selectObject = true;break;case CV_EVENT_LBUTTONUP:selectObject = false;if( selection.width > 0 && selection.height > 0 )trackObject = -1;break;}if( selectObject ){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);} }int main( int argc, const char** argv ) {cv::VideoCapture capture(0);capture.set( CV_CAP_PROP_FRAME_WIDTH,640);capture.set( CV_CAP_PROP_FRAME_HEIGHT,480 );if(!capture.isOpened())return -1;double rate = capture.get(CV_CAP_PROP_FPS); //获取帧率int delay = 1000 / rate; //计算帧间延迟;Mat frame,image,hsv,mask,hue;namedWindow("test",CV_WINDOW_AUTOSIZE);setMouseCallback("test",onMouse,0);while (1){capture>>frame;if(trackObject == -1){ //设置完检測的对象后開始跟踪frame.copyTo(image);cv::cvtColor(image,hsv,CV_RGB2HSV); cv::inRange(hsv,Scalar(0,130,50),Scalar(180,256,256),mask); //去掉低饱和度的点vector<cv::Mat> v;cv::split(hsv,v); //hsv的三个通道分开hue = v[1];cv::Mat ROI = hue(selection); //选择感兴趣的区域cv::Mat maskROI = mask(selection);cv::MatND hist;int histsize[1];histsize[0]= 16;float hranges[2];hranges[0] = 0;hranges[1] = 180;const float *ranges[1];ranges[0] = hranges;cv::calcHist(&ROI,1,0,maskROI,hist,1,histsize,ranges);//感兴趣区域的直方图。从參数太多cv::normalize(hist,hist,0,180,CV_MINMAX); //对直方图进行归一化处理;cv::Mat backpro;cv::calcBackProject(&hue,1,0,hist,backpro,ranges); //对h通道的进行反投影放入backpro中backpro &= mask;cv::RotatedRect trackBox = cv::CamShift(backpro,selection,TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER,10,1));//使用均值秒一算法找出RECT;cv::ellipse(frame,trackBox,cv::Scalar(0,0,255),2,CV_AA);}cv::imshow("test",frame);if(waitKey(30) >= 0)break;}capture.release();return 0; }
效果
用摄像头获取视频
直接读取视频
总结:
效果不是太好。可能是没有预处理或者參数设置的不好。
刚開始学习的人。期待大婶知道!
这篇关于用Camshift算法对指定目标进行跟踪的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!