1. 程式人生 > >用Camshift算法對指定目標進行跟蹤

用Camshift算法對指定目標進行跟蹤

namespace opened callback 總結 edr spl ng- his 選擇

原理

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算法對指定目標進行跟蹤