#include "stdio.h" #include "string.h" #include "iostream" #include "opencv/cv.h" #include "opencv/cxcore.h" #include "opencv/cvaux.h" #include "opencv/highgui.h" #include "opencv/ml.h" #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/video/video.hpp" #include "opencv2/videostab/videostab.hpp" #include "opencv2/stitching/stitcher.hpp" #include "opencv2/contrib/contrib.hpp" #include "opencv2/objdetect/objdetect.hpp" #pragma comment(lib,"opencv_calib3d2410d.lib") #pragma comment(lib,"opencv_contrib2410d.lib") #pragma comment(lib,"opencv_core2410d.lib") #pragma comment(lib,"opencv_features2d2410d.lib") #pragma comment(lib,"opencv_highgui2410d.lib") #pragma comment(lib,"opencv_imgproc2410d.lib") #pragma comment(lib,"opencv_objdetect2410d.lib") #pragma comment(lib,"opencv_video2410d.lib") #pragma comment(lib,"opencv_flann2410d.lib") #pragma comment(lib,"opencv_gpu2410d.lib") #pragma comment(lib,"opencv_legacy2410d.lib") #pragma comment(lib,"opencv_ml2410d.lib") #pragma comment(lib,"opencv_nonfree2410d.lib") #pragma comment(lib,"opencv_ocl2410d.lib") #pragma comment(lib,"opencv_photo2410d.lib") #pragma comment(lib,"opencv_stitching2410d.lib") #pragma comment(lib,"opencv_superres2410d.lib") #pragma comment(lib,"opencv_ts2410d.lib") #pragma comment(lib,"opencv_stitching2410d.lib") IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0; CvHistogram *hist = 0; int select_object = 0; //select_object = 0,還沒圈選物件 1,已圈選 int track_object = 0; //1代表開始tracking, 0代表無追縱物件, -1代表初始化 先建model CvPoint origin; //取得滑鼠座標所在位置 CvRect selection; //取得選擇ROI的資訊 CvRect track_window; CvConnectedComp track_comp; int hdims = 30; //histo要分幾維 float hranges_arr[] = { 0, 180 }; //hue只有0~180而已 float* hranges = hranges_arr; bool g_bIsFinished = true; // OpenCV 滑鼠觸發後的回呼函式 void on_mouse(int event, int x, int y, int flags, void* param) //x-軸 往右為正 最左為0, y-軸 往下為正 最上為0 { if (!image) //至少要有image才能點滑鼠指標 才能產生下面的ROI 不然跳出 return; if (image->origin) //如果image->origin為1代表該圖以左下為原點 0則是以左上為原點 y = image->height - y; //1則把y值倒置 從下往上是正值 變成左下為0 match原圖座標軸 if (select_object) //一開始select_object為0 所以進不來 但是只要一押了滑鼠鍵 就進得來了 代表開始選roi { selection.x = MIN(x, origin.x); //滑鼠按下去後 左上角的值隨時在變 所以一直update 取最左的x selection.y = MIN(y, origin.y); selection.width = selection.x + CV_IABS(x - origin.x); //OFFSET加X Y的長度,不能超過整個視窗大小 selection.height = selection.y + CV_IABS(y - origin.y); //CV_IAB取絕對值 代表 整個視窗佔整個window的位置 selection.x = MAX(selection.x, 0); //X Y OFFSET至少要大於0 如果滑鼠拖超過視窗外 則設為0 selection.y = MAX(selection.y, 0); selection.width = MIN(selection.width, image->width); //如果寬或長大過視窗 則先取視窗長度 selection.height = MIN(selection.height, image->height); //最大也不會超過視窗大小 selection.width -= selection.x; //上面所取的視窗長度扣掉OFFSET 不怕滑鼠拖移到視窗外 selection.height -= selection.y; } switch (event) { case CV_EVENT_LBUTTONDOWN: { origin = cvPoint(x, y); selection = cvRect(x, y, 0, 0); //按鍵一押下去 初始化 先得到roi的初始點(但有可能是roi四個角的其中一個點) select_object = 1; //一旦押了滑鼠鍵 就等於開始選物件 break; } case CV_EVENT_LBUTTONUP: { select_object = 0; //一旦放了滑鼠鍵 物件選完 if (selection.width > 0 && selection.height > 0) track_object = -1; //有了roi了 可以開始進行tracking的工具了 break; } } } //把原hue轉成RGB CvScalar hsv2rgb(float hue) { int rgb[3], p, sector; static const int sector_data[][3] = { { 0, 2, 1 }, { 1, 2, 0 }, { 1, 0, 2 }, { 2, 0, 1 }, { 2, 1, 0 }, { 0, 1, 2 } }; hue *= 0.033333333333333333333333333333333f; sector = cvFloor(hue); p = cvRound(255 * (hue - sector)); p ^= sector & 1 ? 255 : 0; rgb[sector_data[sector][0]] = 255; rgb[sector_data[sector][1]] = 0; rgb[sector_data[sector][2]] = p; return cvScalar(rgb[2], rgb[1], rgb[0], 0); } // 開始播放影像 void PlayVideo() { CvCapture* capture = 0; //capture = cvCaptureFromAVI("1.avi"); capture = cvCreateCameraCapture(0); if (!capture) { fprintf(stderr, "Could not initialize capturing...\n"); return; } cvNamedWindow("Tracking Demo", 1); cvNamedWindow("Histogram", 1); cvNamedWindow("Back Project", 1); cvSetMouseCallback("Tracking Demo", (CvMouseCallback)on_mouse); for (;;) { IplImage* frame = 0; int i, bin_w, c; frame = cvQueryFrame(capture); if (!frame) { // 影片播放結束 g_bIsFinished = true; break; } if (!image) { image = cvCreateImage(cvGetSize(frame), 8, 3); image->origin = frame->origin; //如果不加這一行的話 下面copy動作完之後,image->origin會從尾巴開始算 整張影像會倒過來 hsv = cvCreateImage(cvGetSize(frame), 8, 3); hue = cvCreateImage(cvGetSize(frame), 8, 1); mask = cvCreateImage(cvGetSize(frame), 8, 1); backproject = cvCreateImage(cvGetSize(frame), 8, 1); backproject->origin = frame->origin; hist = cvCreateHist(1, &hdims, CV_HIST_ARRAY, &hranges, 1); histimg = cvCreateImage(cvGetSize(frame), 8, 3); cvZero(histimg); } cvCopy(frame, image, 0); cvCvtColor(image, hsv, CV_BGR2HSV); if (track_object) { cvInRangeS(hsv, cvScalar(0, 0, 0, 0), cvScalar(180, 255, 255, 0), mask); cvSplit(hsv, hue, 0, 0, 0); if (track_object < 0) { float max_val = 0.f; cvSetImageROI(hue, selection); cvSetImageROI(mask, selection); cvCalcHist(&hue, hist, 0, mask); cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0); cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0); cvResetImageROI(hue); cvResetImageROI(mask); track_window = selection; track_object = 1; //此值等於1代表model建好 可以追縱了 //下面為 建立histogram image cvZero(histimg); bin_w = histimg->width / hdims; for (i = 0; i < hdims; i++) { int val = cvRound(cvGetReal1D(hist->bins, i)*histimg->height / 255); CvScalar color = hsv2rgb(i*180.f / hdims); cvRectangle(histimg, cvPoint(i*bin_w, histimg->height), cvPoint((i + 1)*bin_w, histimg->height - val), color, -1, 8, 0); } } cvCalcBackProject(&hue, backproject, hist); cvAnd(backproject, mask, backproject, 0); cvMeanShift(backproject, track_window, cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1), &track_comp); track_window = track_comp.rect; CvScalar cc; cc = cvScalar(255, 0, 0); cvRectangle(image, cvPoint(track_window.x, track_window.y), cvPoint(track_window.x + track_window.width, track_window.y + track_window.height), cc, 2, 8, 0); } if (select_object && selection.width > 0 && selection.height > 0) { cvSetImageROI(image, selection); cvXorS(image, cvScalarAll(255), image, 0); cvResetImageROI(image); } cvShowImage("Tracking Demo", image); cvShowImage("Histogram", histimg); cvShowImage("Back Project", backproject); c = cvWaitKey(150); if (c == 27) // ESC鍵,跳出程式 break; } cvReleaseCapture(&capture); cvDestroyWindow("Back Project"); cvDestroyWindow("Histogram"); cvDestroyWindow("Tracking Demo"); } int main() { while (g_bIsFinished) { g_bIsFinished = false; PlayVideo(); } return 0; }
时间: 2024-10-08 12:21:13