#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 = , *hsv = , *hue = , *mask = , *backproject = , *histimg = ;
CvHistogram *hist = ;
int select_object = ; //select_object = 0,還沒圈選物件 1,已圈選
int track_object = ; //1代表開始tracking, 0代表無追縱物件, -1代表初始化 先建model
CvPoint origin; //取得滑鼠座標所在位置
CvRect selection; //取得選擇ROI的資訊
CvRect track_window;
CvConnectedComp track_comp;
int hdims = ; //histo要分幾維
float hranges_arr[] = { , }; //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, ); //X Y OFFSET至少要大於0 如果滑鼠拖超過視窗外 則設為0
selection.y = MAX(selection.y, );
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, , ); //按鍵一押下去 初始化 先得到roi的初始點(但有可能是roi四個角的其中一個點)
select_object = ; //一旦押了滑鼠鍵 就等於開始選物件
break;
}
case CV_EVENT_LBUTTONUP:
{
select_object = ; //一旦放了滑鼠鍵 物件選完
if (selection.width > && selection.height > )
track_object = -; //有了roi了 可以開始進行tracking的工具了
break;
}
}
}
//把原hue轉成RGB
CvScalar hsv2rgb(float hue)
{
int rgb[], p, sector;
static const int sector_data[][] =
{ { , , }, { , , }, { , , }, { , , }, { , , }, { , , } };
hue *= 0.033333333333333333333333333333333f;
sector = cvFloor(hue);
p = cvRound( * (hue - sector));
p ^= sector & ? : ;
rgb[sector_data[sector][]] = ;
rgb[sector_data[sector][]] = ;
rgb[sector_data[sector][]] = p;
return cvScalar(rgb[], rgb[], rgb[], );
}
// 開始播放影像
void PlayVideo()
{
CvCapture* capture = ;
//capture = cvCaptureFromAVI("1.avi");
capture = cvCreateCameraCapture();
if (!capture)
{
fprintf(stderr, "Could not initialize capturing...\n");
return;
}
cvNamedWindow("Tracking Demo", );
cvNamedWindow("Histogram", );
cvNamedWindow("Back Project", );
cvSetMouseCallback("Tracking Demo", (CvMouseCallback)on_mouse);
for (;;)
{
IplImage* frame = ;
int i, bin_w, c;
frame = cvQueryFrame(capture);
if (!frame)
{ // 影片播放結束
g_bIsFinished = true;
break;
}
if (!image)
{
image = cvCreateImage(cvGetSize(frame), , );
image->origin = frame->origin; //如果不加這一行的話 下面copy動作完之後,image->origin會從尾巴開始算 整張影像會倒過來
hsv = cvCreateImage(cvGetSize(frame), , );
hue = cvCreateImage(cvGetSize(frame), , );
mask = cvCreateImage(cvGetSize(frame), , );
backproject = cvCreateImage(cvGetSize(frame), , );
backproject->origin = frame->origin;
hist = cvCreateHist(, &hdims, CV_HIST_ARRAY, &hranges, );
histimg = cvCreateImage(cvGetSize(frame), , );
cvZero(histimg);
}
cvCopy(frame, image, );
cvCvtColor(image, hsv, CV_BGR2HSV);
if (track_object)
{
cvInRangeS(hsv, cvScalar(, , , ), cvScalar(, , , ), mask);
cvSplit(hsv, hue, , , );
if (track_object < )
{
float max_val = .f;
cvSetImageROI(hue, selection);
cvSetImageROI(mask, selection);
cvCalcHist(&hue, hist, , mask);
cvGetMinMaxHistValue(hist, , &max_val, , );
cvConvertScale(hist->bins, hist->bins, max_val ? . / max_val : ., );
cvResetImageROI(hue);
cvResetImageROI(mask);
track_window = selection;
track_object = ; //此值等於1代表model建好 可以追縱了
//下面為 建立histogram image
cvZero(histimg);
bin_w = histimg->width / hdims;
for (i = ; i < hdims; i++)
{
int val = cvRound(cvGetReal1D(hist->bins, i)*histimg->height / );
CvScalar color = hsv2rgb(i*.f / hdims);
cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),
cvPoint((i + )*bin_w, histimg->height - val),
color, -, , );
}
}
cvCalcBackProject(&hue, backproject, hist);
cvAnd(backproject, mask, backproject, );
cvMeanShift(backproject, track_window,
cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, , ),
&track_comp);
track_window = track_comp.rect;
CvScalar cc;
cc = cvScalar(, , );
cvRectangle(image, cvPoint(track_window.x, track_window.y),
cvPoint(track_window.x + track_window.width, track_window.y + track_window.height),
cc, , , );
}
if (select_object && selection.width > && selection.height > )
{
cvSetImageROI(image, selection);
cvXorS(image, cvScalarAll(), image, );
cvResetImageROI(image);
}
cvShowImage("Tracking Demo", image);
cvShowImage("Histogram", histimg);
cvShowImage("Back Project", backproject);
c = cvWaitKey();
if (c == ) // ESC鍵,跳出程式
break;
}
cvReleaseCapture(&capture);
cvDestroyWindow("Back Project");
cvDestroyWindow("Histogram");
cvDestroyWindow("Tracking Demo");
}
int main()
{
while (g_bIsFinished)
{
g_bIsFinished = false;
PlayVideo();
}
return ;
}