用Camshift算法對指定目標進行跟蹤
阿新 • • 發佈:2017-07-26
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算法對指定目標進行跟蹤