python,OpenCV,camShift,目標跟蹤
阿新 • • 發佈:2019-02-08
之前一直都是用的網上c++版本的程式碼,最近想做一些拓展,要用python來實現。在網上找 了一下,感覺不是很好用。於是參照官方文件和c++版本的程式碼改寫了一些。引數也沒怎麼調整就直接用了。
import cv2 import numpy as np xs,ys,ws,hs = 0,0,0,0 #selection.x selection.y xo,yo=0,0 #origin.x origin.y selectObject = False trackObject = 0 def onMouse(event, x, y, flags, prams): global xs,ys,ws,hs,selectObject,xo,yo,trackObject if selectObject == True: xs = min(x, xo) ys = min(y, yo) ws = abs(x-xo) hs = abs(y-yo) if event == cv2.EVENT_LBUTTONDOWN: xo,yo = x, y xs,ys,ws,hs= x, y, 0, 0 selectObject = True elif event == cv2.EVENT_LBUTTONUP: selectObject = False trackObject = -1 cap = cv2.VideoCapture(0) ret,frame = cap.read() cv2.namedWindow('imshow') cv2.setMouseCallback('imshow',onMouse) term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 ) while(True): ret,frame = cap.read() if trackObject != 0: hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, np.array((0., 30.,10.)), np.array((180.,256.,255.))) if trackObject == -1: track_window=(xs,ys,ws,hs) maskroi = mask[ys:ys+hs, xs:xs+ws] hsv_roi = hsv[ys:ys+hs, xs:xs+ws] roi_hist = cv2.calcHist([hsv_roi],[0],maskroi,[180],[0,180]) cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX) trackObject = 1 dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1) dst &= mask ret, track_window = cv2.CamShift(dst, track_window, term_crit) pts = cv2.boxPoints(ret) pts = np.int0(pts) img2 = cv2.polylines(frame,[pts],True, 255,2) if selectObject == True and ws>0 and hs>0: cv2.imshow('imshow1',frame[ys:ys+hs,xs:xs+ws]) cv2.bitwise_not(frame[ys:ys+hs,xs:xs+ws],frame[ys:ys+hs,xs:xs+ws]) cv2.imshow('imshow',frame) if cv2.waitKey(10)==27: break cv2.destroyAllWindows()
還有就是參考的c++程式碼
//---------------------------------【標頭檔案、名稱空間包含部分】---------------------------- // 描述:包含程式所使用的標頭檔案和名稱空間 //------------------------------------------------------------------------------------------------- #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> #include <ctype.h> #include <windows.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; int vmin = 10, vmax = 256, smin = 30; //--------------------------------【onMouse( )回撥函式】------------------------------------ // 描述:滑鼠操作回撥 //------------------------------------------------------------------------------------------------- static void onMouse( int event, int x, int y, int, void* ) { 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); selection &= Rect(0, 0, image.cols, image.rows); } switch( event ) { //此句程式碼的OpenCV2版為: //case CV_EVENT_LBUTTONDOWN: //此句程式碼的OpenCV3版為: case EVENT_LBUTTONDOWN: origin = Point(x,y); selection = Rect(x,y,0,0); selectObject = true; break; //此句程式碼的OpenCV2版為: //case CV_EVENT_LBUTTONUP: //此句程式碼的OpenCV3版為: case EVENT_LBUTTONUP: selectObject = false; if( selection.width > 0 && selection.height > 0 ) trackObject = -1; break; } } //--------------------------------【help( )函式】---------------------------------------------- // 描述:輸出幫助資訊 //------------------------------------------------------------------------------------------------- static void ShowHelpText() { cout <<"\n\n\t\t\t非常感謝購買《OpenCV3程式設計入門》一書!\n" <<"\n\n\t\t\t此為本書OpenCV3版的第8個配套示例程式\n" << "\n\n\t\t\t 當前使用的OpenCV版本為:" << CV_VERSION <<"\n\n ----------------------------------------------------------------------------" ; cout << "\n\n\t此Demo顯示了基於均值漂移的追蹤(tracking)技術\n" "\t請用滑鼠框選一個有顏色的物體,對它進行追蹤操作\n"; cout << "\n\n\t操作說明: \n" "\t\t用滑鼠框選物件來初始化跟蹤\n" "\t\tESC - 退出程式\n" "\t\tc - 停止追蹤\n" "\t\tb - 開/關-投影檢視\n" "\t\th - 顯示/隱藏-物件直方圖\n" "\t\tp - 暫停視訊\n"; } const char* keys = { "{1| | 0 | camera number}" }; //-----------------------------------【main( )函式】-------------------------------------------- // 描述:控制檯應用程式的入口函式,我們的程式從這裡開始 //------------------------------------------------------------------------------------------------- int main( int argc, const char** argv ) { ShowHelpText(); VideoCapture cap; Rect trackWindow; int hsize = 16; float hranges[] = {0,180}; const float* phranges = hranges; cap.open(0); //cap.open("H:\\opencv\\ai.avi"); if( !cap.isOpened() ) { cout << "不能初始化攝像頭\n"; } namedWindow( "Histogram", 0 );//顏色直方圖視窗 namedWindow( "CamShift Demo", 0 );//跟蹤影象視窗 setMouseCallback( "CamShift Demo", onMouse, 0 );//關聯滑鼠事件 createTrackbar( "Vmin", "CamShift Demo", &vmin, 256, 0 );//顏色空間引數設定 createTrackbar( "Vmax", "CamShift Demo", &vmax, 256, 0 ); createTrackbar( "Smin", "CamShift Demo", &smin, 256, 0 ); Mat frame, hsv, hue, mask, hist, histimg = Mat::zeros(200, 320, CV_8UC3), backproj; bool paused = false;//暫停 LARGE_INTEGER _start, _stop; double start, stop; for(;;) { QueryPerformanceCounter(&_start); start = (double)_start.QuadPart; //獲得計數器計數初值 if( !paused ) { cap >> frame; if( frame.empty() ) break; } QueryPerformanceCounter(&_stop); //獲取計數器當前值 stop = (double)_stop.QuadPart; cout << (stop - start) * 10 / 25332 << endl;; frame.copyTo(image); if( !paused )//如果麼有暫停。。。要是我就不會那麼多事設定一個暫停在這 { cvtColor(image, hsv, COLOR_BGR2HSV);//將影象轉換為hsv顏色空間 if( trackObject )//只有等於0的時候不跟蹤? { int _vmin = vmin, _vmax = vmax;//顏色空間引數 inRange(hsv, Scalar(0, smin, MIN(_vmin,_vmax)), Scalar(180, 256, MAX(_vmin, _vmax)), mask); int ch[] = {0, 0}; hue.create(hsv.size(), hsv.depth());//反向直方圖 mixChannels(&hsv, 1, &hue, 1, ch, 1); if( trackObject < 0 )//已經用滑鼠選取完區域後就可以跟蹤了。。 { Mat roi(hue, selection), maskroi(mask, selection); calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges); //此句程式碼的OpenCV3版為: normalize(hist, hist, 0, 255, NORM_MINMAX); //此句程式碼的OpenCV2版為: //normalize(hist, hist, 0, 255, CV_MINMAX); trackWindow = selection; trackObject = 1; histimg = Scalar::all(0); int binW = histimg.cols / hsize; Mat buf(1, hsize, CV_8UC3); for( int i = 0; i < hsize; i++ ) buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180./hsize), 255, 255); //此句程式碼的OpenCV3版為: cvtColor(buf, buf, COLOR_HSV2BGR); //此句程式碼的OpenCV2版為: //cvtColor(buf, buf, CV_HSV2BGR); for( int i = 0; i < hsize; i++ ) { int val = saturate_cast<int>(hist.at<float>(i)*histimg.rows/255); rectangle( histimg, Point(i*binW,histimg.rows), Point((i+1)*binW,histimg.rows - val), Scalar(buf.at<Vec3b>(i)), -1, 8 ); } } calcBackProject(&hue, 1, 0, hist, backproj, &phranges); cv::imshow("backproj", backproj); backproj &= mask; RotatedRect trackBox = CamShift(backproj, trackWindow, //此句程式碼的OpenCV3版為: TermCriteria( TermCriteria::EPS | TermCriteria::COUNT, 10, 1 )); //此句程式碼的OpenCV2版為: //TermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 )); if( trackWindow.area() <= 1 ) { int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6; trackWindow = Rect(trackWindow.x - r, trackWindow.y - r, trackWindow.x + r, trackWindow.y + r) & Rect(0, 0, cols, rows); } if( backprojMode ) cvtColor( backproj, image, COLOR_GRAY2BGR ); //此句程式碼的OpenCV3版為: ellipse( image, trackBox, Scalar(0,0,255), 3, LINE_AA ); //此句程式碼的OpenCV2版為: //ellipse( image, trackBox, Scalar(0,0,255), 3, CV_AA ); } } else if( trackObject < 0 )//也就是說滑鼠選定區域後,暫停鍵失效 paused = false; if( selectObject && selection.width > 0 && selection.height > 0 ) { Mat roi(image, selection); bitwise_not(roi, roi); } cv::imshow( "CamShift Demo", image ); cv::imshow( "Histogram", histimg ); char c = (char)waitKey(90); if( c == 27 ) break; switch(c) { case 'b': backprojMode = !backprojMode; break; case 'c': trackObject = 0; histimg = Scalar::all(0); break; case 'h': showHist = !showHist; if( !showHist ) destroyWindow( "Histogram" ); else namedWindow( "Histogram", 1 ); break; case 'p': paused = !paused; break; case 'k': { imwrite("pic.jpg", image); break; } default: ; } } return 0; }