void HOGDetectorGPU::processVideo(char* ptrNameInput, char* ptrNameOutput){
        VideoCapture inputVideo(ptrNameInput);        
        VideoWriter outputVideo;
        Size sizeVideo = Size((int) inputVideo.get(CV_CAP_PROP_FRAME_WIDTH),(int) inputVideo.get(CV_CAP_PROP_FRAME_HEIGHT));
        Mat* ptrMatOut;
        outputVideo.open(ptrNameOutput, CV_FOURCC('x','v','i','d'), inputVideo.get(CV_CAP_PROP_FPS), sizeVideo, true);
        Mat* ptrMat;
        vector<Mat> spl;
        while(inputVideo.grab()){
            ptrMat = new Mat();
            inputVideo >> *ptrMat; // get a new frame from video
            Mat finalMat;
            split(*ptrMat, spl);
            cvtColor(*ptrMat, *ptrMat, CV_BGR2GRAY);
            ptrMatOut = detectPeople(ptrMat);
            spl[0] = *(ptrMatOut);
            spl[1] = *(ptrMatOut);
            spl[2] = *(ptrMatOut);
            merge(spl, finalMat);
            outputVideo << finalMat;
            imshow("edges", *(ptrMatOut));
            if(waitKey(30) >= 0) break;
            //Deletes the processed frame
            delete ptrMatOut;

        }
        outputVideo.release();
 }
Esempio n. 2
0
void RApplication::writeVideo()
{
	char drive[_MAX_DRIVE];
    char dir[_MAX_DIR];
    char fname[_MAX_FNAME];
    char ext[_MAX_EXT];
	_splitpath_s( Pubvar::videoPath.c_str(), drive, dir, fname, ext);
	
	string outputPath = "";
	int start = 0, end = 0, idx = 0, winsize = 8 * fps;
	VideoWriter writer;
	VideoCapture capCut;
	CV_Assert(capCut.open(Pubvar::videoPath));	
	Mat cutFrame;

	for (int i = winsize; i < videoLen; ++i)
	{		
		if(fidOI[i])
		{				
			outputPath = "data/" + (string)fname + "_" + to_string(idx++) + ext;
			writer = VideoWriter(outputPath, CV_FOURCC('D', 'I', 'V', '3') , fps, frame.size());
			capCut.set(CV_CAP_PROP_POS_FRAMES, i-winsize);			
			for(int j=i-winsize ; j<=i ; j++)
			{
				capCut >> cutFrame;
				writer << cutFrame;
			}
			writer.release();			
		}
	}	
}
/* Funció que calcula l'histograma acumulat de cada una de les execucions d'una activitat */
Mat HistogramaOF::calcularHistogramaAcumulatOF(String path, int num_imatges, String nom_activitat, int num_repeticio, string ruta, bool video) {
	String nomVideo, nomImatgeRGBa, nomImatgeDa, nomImatgeRGBb, nomImatgeDb;
	VideoWriter outputVideo;
	if(video) {
		double fps = 15;
		CvSize mida = cvSize(399, 240);
		nomVideo = ruta+"/"+nom_activitat+"_acumulat_"+to_string(num_repeticio)+".avi";
		outputVideo.open(nomVideo, 0, fps, mida, true);
	}
	Mat imageA, depthA, imageB, depthB, resultat;
	nomImatgeRGBa = path+"/c_0.png";
	nomImatgeDa = path+"/d_0.png";
	imageA = imread(nomImatgeRGBa, IMREAD_COLOR);
	depthA = imread(nomImatgeDa, IMREAD_GRAYSCALE);
	resultat = calcularHistogramaOF(imageA, imageA, depthA, depthA);
	if(video) outputVideo << resultat;
	for(int k = 1; k <= num_imatges; ++k) {
		cout << "Imatge: " << num_repeticio << " - " << k << "/" << num_imatges << endl;
		nomImatgeRGBb = path+"/c_"+to_string(k)+".png";
		nomImatgeDb = path+"/d_"+to_string(k)+".png";
		imageB = imread(nomImatgeRGBb, IMREAD_COLOR);
		depthB= imread(nomImatgeDb, IMREAD_GRAYSCALE);
		resultat = calcularHistogramaOF(imageA, imageB, depthA, depthB);
		if(video) outputVideo << resultat;
		nomImatgeRGBa = nomImatgeRGBb;
		nomImatgeDa = nomImatgeDb;
		imageB.copyTo(imageA);
		depthB.copyTo(depthA);
	}
	if(video) outputVideo.release();

	return repr;
}
VOID inline GlobalExits(VOID)
{
	g_writer.release();
	g_cap.release();
	g_captureStat = capture_IDLE;
	SecureEndThread(threadStat);
	cv::destroyAllWindows();
	g_runningONE = FALSE;
}
Esempio n. 5
0
int main(int argc, char* argv[])
{
	// 基本画像データ
	Mat src = Mat::zeros(480, 640, CV_8UC1);
	Mat tmp;

	// 録画用リソース確保
#ifdef _REC
	VideoWriter vw = VideoWriter("./test.avi", CV_FOURCC('X','V','I','D'), 30, Size(640, 480), false);
#endif	/* _REC */

	char time[256];
	int hh=0, mm=0, ss=0, frame=0;
	string wname = "window";
	namedWindow(wname);
	moveWindow(wname, 61, 0);

	while (1) {
		src.copyTo(tmp);

		sprintf_s(time, 256, "%02d:%02d:%02d.%02d", hh, mm, ss, frame);

		putText(tmp, time, Point(100, 100), FONT_HERSHEY_SIMPLEX, 1.5, Scalar::all(200), 1, CV_AA);

		if (29 < ++frame) {
			frame = 0;
			if (59 < ++ss) {
				ss = 0;
				if (59 < ++mm) {
					mm = 0;
					++hh;
				}
			}
		}
		// 以下で録画秒数指定
		if (0 < mm)
			break;

#ifdef _REC
		vw << tmp;
#endif	/* _REC */

		imshow(wname, tmp);
		waitKey(30);
	}
	destroyAllWindows();
#ifdef _REC
	vw.release();
#endif	/* _REC */
	tmp.release();

	return 0;
}
Esempio n. 6
0
  void run(){
    
    depth=Mat(480,640,DataType<float>::type);
    
   pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr nuage3(&nuage2);// (new pcl::PointCloud<pcl::PointXYZRGB>);
   pcl::PointXYZRGBA point;
   
   it=1000;
   pcl::OpenNIGrabber* interface =new pcl::OpenNIGrabber();//creation d'un objet interface qui vient de l'include openni_grabber
   //namedWindow( "Display Image", CV_WINDOW_AUTOSIZE );
   namedWindow( "Harris Image", CV_WINDOW_AUTOSIZE );
   //namedWindow( "Depth Image", CV_WINDOW_AUTOSIZE );
  // VideoCapture capture(1);
  // Mat frame;
  // capture >> frame;
  // record=VideoWriter("/home/guerric/Bureau/test.avi", CV_FOURCC('M','J','P','G'), 30, frame.size(), true);
   
   boost::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> 
  f = boost::bind (&ImageVIewer::cloud_cb_, this, _1);

  boost::function<void(const boost::shared_ptr<openni_wrapper::Image>&)> 
  g = boost::bind (&ImageVIewer::image_cb_, this, _1);
  
  boost::function<void(const boost::shared_ptr<openni_wrapper::DepthImage>&)> 
  h = boost::bind (&ImageVIewer::depth_cb_, this, _1);


  interface->registerCallback (f);
  interface->registerCallback (g);
  interface->registerCallback (h);
  
   
   interface->start();
   //on reste dans cet état d'acquisition tant qu'on ne stoppe pas dans le viewer

   
   while(!viewer.wasStopped()){
     boost::this_thread::sleep(boost::posix_time::seconds(1));	//met la fonction en attente pendant une seconde <=> sleep(1) mais plus précis pour les multicores     
     viewer.showCloud(nuage3);     
  }
   
  interface->stop();
  record.release();
  destroyAllWindows();  

  }
// Save the current state of the buffer to a file
XnStatus MovieMng::DumpMovie(void)
{
	static VideoWriter writer_image;
	static VideoWriter writer_depth;

	Mat image(m_nImageHeight, m_nImageWidth, CV_8UC3);
	Mat depth(m_nDepthHeight, m_nDepthWidth, CV_16UC1);
	Mat detect(m_nDepthHeight, m_nDepthWidth, CV_16UC1);
	Mat detect8UC1(m_nDepthHeight, m_nDepthWidth, CV_8UC1);
	Mat detect8UC3(m_nDepthHeight, m_nDepthWidth, CV_8UC3);

	static double scale = 255.0/65535.0;

	static XnUInt64 nLastDepthTime = 0;
	static XnUInt64 nLastImageTime = 0;
	static XnUInt32 nMissedDepthFrames = 0;
	static XnUInt32 nMissedImageFrames = 0;
	static XnUInt32 nDepthFrames = 0;
	static XnUInt32 nImageFrames = 0;

	SingleFrame* pFrames = m_pFrames + m_nWritten;

	// ファイル変更チェック
	XnUInt64 timeStamp = pFrames->depthFrame.Timestamp();
	if (Util::GetTimeDiff(timeStamp, m_fOpenTimestamp) > (m_nMovieLength * 60 * 1000))
	{
		m_fOpenTimestamp = timeStamp;
		writer_image.release();
	}
	
	// ファイルオープン
	if(!writer_image.isOpened())
	{
		char timeStr[TIME_STR_LEN];
		g_util.GetTimeStr(pFrames->depthFrame.Timestamp(), sizeof(timeStr), timeStr);
		Util::ChangeIntoNum(timeStr);
		
		// ファイル名作成
		XnChar strFileName[XN_FILE_MAX_PATH];
	
		if (m_bDepth)
		{
			sprintf(strFileName, "%s/%s/%s%s.avi", m_strDirName, "depth/movie", "depth_", timeStr);
			writer_depth.open(strFileName, CV_FOURCC('x','v','i','d'), 29.97, Size(m_nDepthWidth,m_nDepthHeight));
		}

		if (m_bImage)
		{
			sprintf(strFileName, "%s/%s/%s%s.avi", m_strDirName, "video/movie", "image_", timeStr);
			writer_image.open(strFileName, CV_FOURCC('x','v','i','d'), 29.97, Size(640,480));
		}
	}

	XnUInt64 nTimestamp;
	if (m_bDepth)
	{
#ifdef LOG_WRITE_ENABLE
		fprintf(mmng_fp, "[%s] Depth Write.  buffer:%d FrameId:%d Addr:0x%x\n", 
			__FUNCTION__, m_nWritten, pFrames->depthFrame.FrameID(), pFrames);
#endif
		// フレーム落ちチェック
		nTimestamp = pFrames->depthFrame.Timestamp();
		int missed = Util::CheckMissedFrame("depth", nTimestamp, &nDepthFrames, &nLastDepthTime, &nMissedDepthFrames);
		AddDummyFrame(writer_depth, missed);
		
		memcpy(depth.data, pFrames->depthFrame.Data(), depth.step*depth.rows);
		detect = depth.clone();

		detect.convertTo(detect8UC1, CV_8UC1, scale, 0.0);	//16UC1to8UC1 画像として保存する場合に必要
		cvtColor(detect8UC1, detect8UC3, CV_GRAY2RGB);		//8UC1to8UC3 動画として保存する場合に必要

//		imshow("depth", depth);
		writer_depth<<detect8UC3;
	}

	if (m_bImage)
	{
#ifdef LOG_WRITE_ENABLE
		fprintf(mmng_fp, "[%s] Image Write.  buffer:%d FrameId:%d Addr:0x%x\n", 
			__FUNCTION__, m_nWritten, pFrames->imageFrame.FrameID(), pFrames);
#endif
		// フレーム落ちチェック
		nTimestamp = pFrames->imageFrame.Timestamp();
		int missed = Util::CheckMissedFrame("image", nTimestamp, &nImageFrames, &nLastImageTime, &nMissedImageFrames);
		AddDummyFrame(writer_image, missed);

		memcpy(image.data, pFrames->imageFrame.Data(), image.step*image.rows);
		cvtColor(image, image, CV_BGR2RGB);
//		imshow("image", image);
		writer_image << image;
	}

	return XN_STATUS_OK;
}
Esempio n. 8
0
	~GenericClassnameOneTracker9000()
	{
		tracking_recorder.release();
		logger.close();
	}
int main(int argc, char** argv)
{
	if(argc >= 3)
	{
		VideoCapture inputVideo(argv[1]); // open the default camera
		if(!inputVideo.isOpened())  // check if we succeeded
		    return -1; 
		
		// Initialize
	    VideoWriter outputVideo;  // Open the output
	    const string source      = argv[2];                                // the source file name
		const string NAME = source + ".mp4";   // Form the new name with container
	    int ex = inputVideo.get(CV_CAP_PROP_FOURCC);                       // Get Codec Type- Int form
		std::cout << ex << "\n" << (int)inputVideo.get(CV_CAP_PROP_FOURCC) << "\n";
    	Size S = Size((int) inputVideo.get(CV_CAP_PROP_FRAME_WIDTH),       //Acquire input size
        	          (int) inputVideo.get(CV_CAP_PROP_FRAME_HEIGHT));    
		outputVideo.open(NAME, ex, inputVideo.get(CV_CAP_PROP_FPS), S, false);
    	char EXT[] = {(char)(ex & 0XFF) , (char)((ex & 0XFF00) >> 8),(char)((ex & 0XFF0000) >> 16),(char)((ex & 0XFF000000) >> 24), 0};
	    cout << "Input codec type: " << EXT << endl;

        if (!outputVideo.isOpened())
        {
            cout  << "Could not open the output video for write \n";
            return -1;
        }
        
		namedWindow("Result Window", 1);
		
		// Mat declaration
		Mat prev_frame, prev_gray, cur_frame, cur_gray;
        Mat frame_blurred, frameHSV;
        
        // take the first frame
        inputVideo >> prev_frame;
				
        /* manual ball selection */
        MouseParams mp;
        prev_frame.copyTo( mp.ori ); 
        prev_frame.copyTo( mp.img ); 
        setMouseCallback("Result Window", BallSelectFunc, &mp );

		int enterkey = 0;
		while(enterkey != 32 && enterkey != 113)
		{
			enterkey = waitKey(30) & 0xFF;
        	imshow("Result Window", mp.img);
		}
		
		outputVideo.write( mp.img );
		/* Kalman Filter
		   Kalman filter is a prediction-correction filter. It has two stages: predict and correct.
		   In predict stage, the filter uses the states of previous frame to predict the
		   state of current frame. In correct stage, the filter takes in current measurement
		   to "correct" the prediction made in prediction stage. 
		   Here we are using an adaptive Kalman filter to do ball tracking.
		   (noise matrix P, Q changes depending on the occulusion index)
		*/
		
		/* Initialization
		   four parameters:  x, y, vx, vy
		   two measurements: mx, my
		   Here we're implementing a constant velocity model.
		   x_t = x_t-1 + vx_t-1;
		   y_t = y_t-1 + vy_t-1;
		   vx_t = vx_t-1;
		   vy_t = vy_t-1;
		   These linear equations can be written as transition matrix A.
		*/
		KalmanFilter KF(4, 2, 0);
		float transMatrixData[16] = {1,0,1,0, 
		                             0,1,0,1,
		                             0,0,1,0,
		                             0,0,0,1};
		                             
		KF.transitionMatrix = Mat(4, 4, CV_32F, transMatrixData);
		Mat_<float> measurement(2,1);
		measurement.setTo(Scalar(0));
		
		/* We put the first point in predicted state */
		KF.statePost.at<float>(0) = mp.pt.x;
		KF.statePost.at<float>(1) = mp.pt.y;
		KF.statePost.at<float>(2) = 0;
		KF.statePost.at<float>(3) = 0;
		setIdentity(KF.measurementMatrix);                        // measurement matrix H
		setIdentity(KF.processNoiseCov, Scalar::all(1e-4));       // process noise covariance matrix Q
		setIdentity(KF.measurementNoiseCov, Scalar::all(1e-1));   // measurement noise covariance matrix R
		// priori error estimate covariance matrix P'(t)		
		/*
		KF.errorCovPre.at<float>(0)  = 1;
		KF.errorCovPre.at<float>(5)  = 1;
		KF.errorCovPre.at<float>(10) = 1;
		KF.errorCovPre.at<float>(15) = 1;   
		*/
		setIdentity(KF.errorCovPre);                              // priori error estimate covariance matrix P'(t)	
		setIdentity(KF.errorCovPost, Scalar::all(.1));            // posteriori error estimate cov matrix P(t)
	
		/* params related to previous frames */
		Rect    prev_box;
		Point2f prev_motion;
		Point   noFoundStartPt;
        vector<cv::Point2f> prev_ball_centers;
        int noFoundCount = 0;
        
        /* start tracking */		
		setMouseCallback("Result Window", CallBackFunc, &frameHSV);			
        for(int frame_num=1; frame_num < inputVideo.get(CAP_PROP_FRAME_COUNT); ++frame_num)
        {
        	cout << "===FRAME #" << frame_num << "===" << endl;
        	
        	/* get current frame */
            inputVideo >> cur_frame;
            
            // Blur & convert frame to HSV color space
            cv::GaussianBlur(cur_frame, frame_blurred, cv::Size(5, 5), 3.0, 3.0);
            cvtColor(frame_blurred, frameHSV, COLOR_BGR2HSV);
            
            // gray scale current frame
    		cvtColor(prev_frame, prev_gray, CV_BGR2GRAY);            
    		cvtColor(cur_frame, cur_gray, CV_BGR2GRAY);
            
            // mask generation
            Mat mask;
			mask = getMask(frameHSV);

			// Hough Transform
			Mat frame_filtered, frame_filtered_gray;
            cur_frame.copyTo( frame_filtered, mask );
            cv::cvtColor( frame_filtered, frame_filtered_gray, CV_BGR2GRAY );
            vector<cv::Vec3f> circles;
            cv::GaussianBlur(frame_filtered_gray, frame_filtered_gray, cv::Size(5, 5), 3.0, 3.0);
            HoughCircles( frame_filtered_gray, circles, CV_HOUGH_GRADIENT, 1, frame_filtered_gray.rows/8, 120, 18, 5,300);
			
            // contour generation
            vector< vector<cv::Point> > contours_ball;
            cv::findContours(mask, contours_ball, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
            
            Mat result;
            cur_frame.copyTo( result );

			// OpticalFlow
            vector<Point2f> optFlow_ball_centers;
            vector<uchar> featuresFound;
            Mat err;
            TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS, 20, 0.03);
            Size winSize(31, 31);
            if( prev_ball_centers.size() > 0 )
                calcOpticalFlowPyrLK(prev_gray, cur_gray, prev_ball_centers, optFlow_ball_centers, featuresFound, err, winSize, 0, termcrit, 0, 0.001);    
            
            // Kalman Filter: Extract previous point & prediction point
            Point2f statePt   = Point( KF.statePost.at<float>(0), KF.statePost.at<float>(1) );  
            Mat prediction    = KF.predict();  
            Point2f predictPt = Point2f( prediction.at<float>(0), prediction.at<float>(1) );

		    cout << "state:" << statePt << endl;
		    cout << "predict:" << predictPt << endl;
			cout << "prev_motion: " << prev_motion << " sqr: " << prev_motion.x * prev_motion.x + prev_motion.y * prev_motion.y << endl;
            
            // Search current frame for good candidate measurements
            vector<Point2f>   cur_contour_centers;
            vector<cv::Point> best_ball_contour;
            Point2f best_ball_center;
            Rect    best_ball_box;
			bool 	ballFound = false;
			
			// TODO dynamic search range
			int closest_dist = (prev_motion.x * prev_motion.x + prev_motion.y * prev_motion.y) * 15;
	    	if(closest_dist == 0) closest_dist = 10000;
	    	//circle( result, predictPt, sqrt(closest_dist), CV_RGB(255,255,0), 2 );
			
            for (size_t i = 0; i < contours_ball.size(); i++)
			{
			    drawContours(result, contours_ball, i, CV_RGB(255,0,0), 1);  // draw the area
			     
		        cv::Rect bBox;
		        bBox = cv::boundingRect(contours_ball[i]);
			    Point2f center;
			    center.x = bBox.x + bBox.width / 2;
			    center.y = bBox.y + bBox.height / 2;		         

				cur_contour_centers.push_back(center);
				
				// find corresponding optical flow center
				float optFlow_dist = 2500;
				int   best_j = -1;
				for( size_t j=0; j < optFlow_ball_centers.size(); ++j )
				{
		        	float diff_x = center.x - optFlow_ball_centers[j].x;
		        	float diff_y = center.y - optFlow_ball_centers[j].y;
		        	float distance  = diff_x * diff_x + diff_y * diff_y;
					if(distance < optFlow_dist)
					{
						distance = optFlow_dist;
						best_j   = j;
					}
			    }
			    
				/* TODO
				Point2f optPredictPt = center;
				if(best_j != -1)
				{
					Point2f motion = optFlow_ball_centers[best_j] - prev_ball_centers[best_j];
					optPredictPt = center + motion;
					line( result, optPredictPt, center, CV_RGB(190,60,70), 2 );
				}
				*/
					
		        // If we find a contour that includes our prediction point,
		        // it's the best choice then.
				// If we cannot found a contour to contain prediction point, 
				// we search the rest contours. The one with closest distance
				// should be picked.
				if( pointPolygonTest( contours_ball[i], predictPt, false ) >= 0)
				{
					best_ball_contour = contours_ball[i];
					best_ball_center  = center;
					best_ball_box     = bBox;
					ballFound = true;
					break;
				}
				else 
				{
		        	float diff_x = center.x - predictPt.x;
		        	float diff_y = center.y - predictPt.y;
		        	float distance  = diff_x * diff_x + diff_y * diff_y;
					
					//if( bBox.area() < 200 )
					//	continue;
					/*
					stringstream sstr;
					sstr << "(dot= " << dot_product << ")";
					cv::putText(result, sstr.str(),
					cv::Point(center.x + 3, center.y - 3),
					cv::FONT_HERSHEY_SIMPLEX, 0.5, CV_RGB(0,255,100), 2);						
					*/
					
					//if(bBox.area() < 250)
					//	continue;
											
					// if distance is close enough
					if( distance < closest_dist )
					{
						best_ball_contour = contours_ball[i];
						best_ball_center  = center;
						best_ball_box     = bBox;		
						closest_dist      = distance;
						ballFound = true;
					}
				}
            }
	
			if(ballFound)
	        {
	        	// calculte occulusion rate
			    float occ = fabs( (float)best_ball_box.area() / (float)prev_box.area() - 1.0 );
			    if(occ > 1.0) occ = 1.0;
				
				// check threshold
				float threshold = 0.3;
				if(occ < threshold)
				{				
					setIdentity(KF.processNoiseCov, Scalar::all(1.0-occ));  // Q = 1 - occ
					setIdentity(KF.measurementNoiseCov, Scalar::all(occ));  // R = occ    
				}
				else
				{
					setIdentity(KF.processNoiseCov, Scalar::all(0.0));      // Q = 0
					setIdentity(KF.measurementNoiseCov, Scalar::all(1e10)); // R = infinite			    				
					cout << "NON_CONFIDENTIAL_MEASUREMENT\n";
				}
				
				// correction
			    measurement.at<float>(0) = best_ball_center.x;  
				measurement.at<float>(1) = best_ball_center.y;  
				Mat estimated = KF.correct(measurement);
			
				cout << "measured:" << best_ball_center << endl;
				cout << "estimated:" << estimated.at<float>(0) << ", " << estimated.at<float>(1) << endl;
          	
				// remember to update prev parameters
				prev_box     = best_ball_box;
				prev_motion  = best_ball_center - statePt;
				noFoundCount = 0;
		    } 
		    else
		    {
				// TODO
				prev_motion = predictPt - statePt;
				
				if( noFoundCount == 0 )
				{
					noFoundStartPt = statePt;
				}
    		    circle( result, noFoundStartPt, 5, CV_RGB(255,255,255), 2 );
				
				// if Kalman filter failed... we "CORRECT" the frame
				if(noFoundCount > 1)
				{
					closest_dist = 1e8;
				    for( size_t i = 0; i < circles.size(); i++ )
				    {                
				        Point center_circle(cvRound(circles[i][0]), cvRound(circles[i][1]));
				        int radius_circle = cvRound(circles[i][2]);
						if( radius_circle < 6 )
							continue;
						/*	
						cv::Rect bBox;
						bBox = cv::boundingRect(circles[i]);
						Point center;
						center.x = bBox.x + bBox.width / 2;
						center.y = bBox.y + bBox.height / 2;		         
			    		*/
				    	int diff_x = center_circle.x - noFoundStartPt.x;
				    	int diff_y = center_circle.y - noFoundStartPt.y;
				    	int distance  = diff_x * diff_x + diff_y * diff_y;

						if( distance < closest_dist)
						{
							closest_dist = distance;
							best_ball_center = center_circle;
							//best_ball_box    = bBox;
							ballFound = true;						
						}
				    }
				    
				    if(ballFound)
				    {
	    			    //measurement.at<float>(0) = best_ball_center.x;  
						//measurement.at<float>(1) = best_ball_center.y;  
	    				//Mat estimated = KF.correct(measurement);	
						KF.statePost.at<float>(0) = best_ball_center.x;
						KF.statePost.at<float>(1) = best_ball_center.y;
						KF.statePost.at<float>(2) = 0;
						KF.statePost.at<float>(3) = 0;

						prev_box     = best_ball_box;
						prev_motion  = Point2f(0, 0);
				    	noFoundCount = 0;
				    }
				    else {
				    	cout << "UNABLE TO CORRECT..." << endl;
				    }
				}
				noFoundCount++;
				cout << "NO FOUND: " << noFoundCount << endl;
		    }
		    
		    // rendering result
			line( result, statePt, predictPt, CV_RGB(255,0,255), 2 );	
	    	circle( result, predictPt, 2, CV_RGB(255,0,255), 2 );	         
		    circle( result, best_ball_center, 2, CV_RGB(255,255,255), 2 );
		    rectangle( result, best_ball_box, CV_RGB(0,255,0), 2 );

			// Optical Flow   
            /*
            for (size_t i = 0; i < optFlow_ball_centers.size(); i++)
			{
				line( result, prev_ball_centers[i], optFlow_ball_centers[i], CV_RGB(120,70,255), 2 );
		    	circle( result, optFlow_ball_centers[i], 2, CV_RGB(120,70,255), 2 );
            }			   
			*/
			
			// Hough
            /*
            for( size_t circle_i = 0; circle_i < circles.size(); circle_i++ )
            {                
                Point center(cvRound(circles[circle_i][0]), cvRound(circles[circle_i][1]));
                int radius = cvRound(circles[circle_i][2]);
                circle( result, center, radius, Scalar(12,12,255), 2 );
            }			
			*/
			
			prev_ball_centers = cur_contour_centers;
			
		    imshow("Result Window", result);
 			outputVideo.write( result );
          
            /* UPDATE FRAME */
            cur_frame.copyTo( prev_frame );
            
            /* KEY INPUTS */
            int keynum = waitKey(30) & 0xFF;
            if(keynum == 113)      // press q
            	break;
            else if(keynum == 32)  // press space
			{
				keynum = 0;
				while(keynum != 32 && keynum != 113)
					keynum = waitKey(30) & 0xFF;
				if(keynum == 113) 
					break;
			}
        }
        inputVideo.release();
        outputVideo.release();
    }
int main(int argc, char *argv[])
{
    int frame_num = 0;
    int non_decode_frame =0;
    int count = 1, idx =0;
    int frame_pos =0;
    int p = 0;
	vector<vector<Point> > contours;
  vector<Vec4i> hierarchy;
    MOG2 = createBackgroundSubtractorMOG2(); //MOG2 approach
    std::cout<<"Video File "<<argv[1]<<std::endl;
   // cv::VideoCapture input_video(argv[1]);
    cv::VideoCapture cap("IM-4559-%04d.png");
    namedWindow("My_Win",1);
    cvSetMouseCallback("My_Win", mouse_click, 0);
    sleep(1);
    while(cap.grab())
    {
        cap_img.release();
	p++;
        if(cap.retrieve(cap_img))
        {
            imshow("My_Win", cap_img);
            if(!got_roi)
            {
                            //Wait here till user select the desire ROI
                waitKey(0);
            }
            else
            {
                std::cout<<"Got ROI disp prev and curr image"<<std::endl;
                std::cout<<"PT1"<<pt1.x<<" "<<pt1.y<<std::endl;
                std::cout<<"PT2"<<pt2.x<<" "<<pt2.y<<std::endl;
			
		if(vw.isOpened()){
			std::cout<<"VW Opened\n";
		}
                Mat curr_img_t1;
                Mat roi2(cap_img,Rect(pt1, pt2));
                Mat curr_imgT = roi2.clone();
      		MOG2->apply(curr_imgT, fgMaskMOG2);
        	//get the frame number and write it on the current frame
        	stringstream ss;
        	rectangle(curr_imgT, cv::Point(10, 2), cv::Point(100,20),cv::Scalar(255,255,255), -1);
        	ss << vw.get(CAP_PROP_POS_FRAMES);
        	string frameNumberString = ss.str();
        	putText(curr_imgT, frameNumberString.c_str(), cv::Point(15, 15),
                FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0));
		float morph_size = 2;
		Mat grad;
		Mat canny_output;
		Mat thrld;
		Mat element = getStructuringElement(MORPH_RECT,Size(2*morph_size+1,2*morph_size+1), Point(morph_size,morph_size));
                morphologyEx(fgMaskMOG2,grad,MORPH_GRADIENT,element, Point(-1,-1),1);
		Canny(curr_imgT, canny_output, thresh,thresh*2 , 3);	
		findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
		Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
  for( int i = 0; i< contours.size(); i++ )
     {
       Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
       drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
     }
	namedWindow( "Contours", WINDOW_AUTOSIZE );
  imshow( "Contours", drawing );
		threshold(grad,thrld,200,0,3);
		char file_name[100];
		sprintf(file_name, "final%d.png",p);
        	//show the current frame and the fg masks
                imwrite(file_name,drawing);
		imshow("background", fgMaskMOG2);
                waitKey(30);
                        }
                  }
	std::cout<<p<<std::endl;
}
vw.release();
}
Esempio n. 11
0
DEFINE_THREAD_ROUTINE(camera_top, data)
{
	if (threadAttr == NULL)
		{
			threadAttr = new ThreadAttr;

			vp_os_mutex_init(&threadAttr->mutex2);
		}
	/*
#ifndef aaa
#define aaa
	if (threadAttr == NULL)
			threadAttr = new ThreadAttr;

	vp_os_mutex_init(&threadAttr->mutex2);
	sem_init(&threadAttr->mutex, 0, 1);
#endif
*/
	string times;

	struct timeval start, end;

	long seconds, useconds, mtime = 0;
	long mtime2 = 0;

//	ThreadAttr *args = (ThreadAttr *) data;

	printf("\r\n----------------------------------------\r\n");
	printf("\t\tPID: %d", (unsigned int) pthread_self());
	printf("\r\n----------------------------------------\r\n");

	// color que busco -> umbral minimo y maximo
	hsv.max.val[0] = 179;
	hsv.max.val[1] = 255;
	hsv.max.val[2] = 255;

	hsv.min.val[0] = 135; // 0.75 135
	hsv.min.val[1] = 50; //76 bien  56  0.25 66   estaba en 80
	hsv.min.val[2] = 80; //125  //130 0.54 140  estaba en 130


	// amarillo
	hsvDestinos[0].max.val[0] = 81;
	hsvDestinos[0].max.val[1] = 127;
	hsvDestinos[0].max.val[2] = 195;

	hsvDestinos[0].min.val[0] = 0; // 0.75 135
	hsvDestinos[0].min.val[1] = 91; //76 bien  56  0.25 66
	hsvDestinos[0].min.val[2] = 185; //125  //130 0.54 140

	// verde
	hsvDestinos[1].max.val[0] = 101;
	hsvDestinos[1].max.val[1] = 149;
	hsvDestinos[1].max.val[2] = 108;

	hsvDestinos[1].min.val[0] = 83;
	hsvDestinos[1].min.val[1] = 101;
	hsvDestinos[1].min.val[2] = 101;

	// azul
	hsvDestinos[2].max.val[0] = 125;
	hsvDestinos[2].max.val[1] = 255;
	hsvDestinos[2].max.val[2] = 232;

	hsvDestinos[2].min.val[0] = 86;
	hsvDestinos[2].min.val[1] = 101;
	hsvDestinos[2].min.val[2] = 145;

	// naranja
	hsvDestinos[3].max.val[0] = 21;
	hsvDestinos[3].max.val[1] = 255;
	hsvDestinos[3].max.val[2] = 233;

	hsvDestinos[3].min.val[0] = 10;
	hsvDestinos[3].min.val[1] = 55;
	hsvDestinos[3].min.val[2] = 145;


	gettimeofday(&start, NULL);

	Environment* env = new Environment(1);

	Mat img = env->getVideoFrame();
	cv::Size imgSize = img.size();

	printf("width: %d, height: %d", imgSize.width, imgSize.height);

	threadAttr->data.imgSize.height = imgSize.height;
	threadAttr->data.imgSize.width = imgSize.width;

	//Defino los destinos
//	env->addDestination(Point2i(320, 240));

	namedWindow("Deteccion", WINDOW_AUTOSIZE);
	//Para detectar clicks en la ventana
	int destSize = DESTINOS; // = (int) env->getDestinations().size();
	setMouseCallback("Deteccion", callbackMouseDestinations, &destSize);

	/********************/
	//	Writers para guardar videos

	time_t rawtime;
	struct tm * timeinfo;
	char buffer[80];

	time(&rawtime);
	timeinfo = localtime(&rawtime);

	strftime(buffer, 80, "%d-%m-%Y %I:%M:%S", timeinfo);
	string str(buffer);

	VideoWriter outputVideo;
	VideoWriter outputVideo2;
	VideoWriter outputVideo3;

	/*******************/

	bool bContinue = true;

	int fps = 0;
	bool quit = false;
	while (!quit)
	{

		gettimeofday(&end, NULL);

		seconds = end.tv_sec - start.tv_sec;
		useconds = end.tv_usec - start.tv_usec;
		mtime2 = ((seconds) * 1000 + useconds / 1000.0) + 0.5;
		mtime += mtime2;
		fps++;
		if (mtime > 1000)
		{
			//printf("Red Object Elapsed time: %ld milliseconds, fps: %d \n",mtime, fps);
			fps = 0;
			mtime = 0;
		}

		gettimeofday(&start, NULL);

		Mat img = env->getVideoFrame();

		env->getVideo()->grabVideoAndData(PROYECT_PATH + "videos/", "avi", str,
				outputVideo, img);

		UI::drawWindow("Camara1", img);

		Mat segmentated(imgSize, CV_8UC3);

		// transformo a BN la matriz segmentated, para que el color HSV(hsv) se vea negro, y el resto blanco
		cv::cvtColor(img, segmentated, COLOR_BGR2HSV);

		if((int)env->getDestinations().size() != DESTINOS && BUSCAR_DESTINOS)
		{
			std::vector<ar::Point> *puntos_dest;
			puntos_dest = env->getVideo()->transformToBlackAndWihte(segmentated, hsvDestinos, DESTINOS);
			UI::drawWindow("colores", segmentated);
			ar::Point *destinos;
			destinos = env->getDestinoPositionInImage(puntos_dest, DESTINOS);

			env->clearDestinations();
			for(int i = 0; i < DESTINOS; i++)
			{
				if(destinos[i].x != -1)
					env->addDestination(cv::Point(destinos[i].x, destinos[i].y));
			}

			destSize = (int) env->getDestinations().size();
			cv::cvtColor(img, segmentated, COLOR_BGR2HSV);


		}
		//invento unos destinos:
		if((int)env->getDestinations().size() == 0 && !BUSCAR_DESTINOS)
		{
			env->addDestination(cv::Point(210, 160));
			env->addDestination(cv::Point(210, 320));
			env->addDestination(cv::Point(430, 320));
			env->addDestination(cv::Point(430, 160));
		}




		std::vector<ar::Point> puntos;
		puntos = env->getVideo()->transformToBlackAndWihte(segmentated, hsv);

		Mat grayImage(imgSize, CV_8UC3, cv::Scalar(255, 255, 255));

		vp_os_mutex_lock(&threadAttr->mutex2);
		ar::Point p = env->getRobotPositionInImage(puntos);

		//asigno un valor aleatorio  por q no tengo camara
	//	p.x = threadAttr->data.imgSize.width / 2 -50;
	//	p.y = threadAttr->data.imgSize.height / 2 -50;
		//modifico la posicion segun la altura del robot
		p.x = (threadAttr->data.imgSize.width / 2) + (p.x - (threadAttr->data.imgSize.width / 2)) * (ALT_CAMERA - threadAttr->data.copterValues.altitude) / ALT_CAMERA;
		p.y = (threadAttr->data.imgSize.height / 2) + (p.y - (threadAttr->data.imgSize.height / 2)) * (ALT_CAMERA - threadAttr->data.copterValues.altitude) / ALT_CAMERA;




		Position predecida = env->predictedPositionCalc();
		Position pos(p.x, p.y, 0);
		float dist = -1;

		threadAttr->data.bReadead = false;

		if(threadAttr->data.tPos.find == true)//si antes no encontro nada acumulo el tiempo
			threadAttr->data.elapsedTime = mtime2;

		else
			threadAttr->data.elapsedTime += mtime2;

		// meto datos en memoria compartida mientras tenga al robot visto
		if (threadAttr->data.tLastPos.size() != 0 && pos.x != -1) dist =
				Environment::distanceCalc(ar::Point(predecida.x, predecida.y),
						ar::Point(pos.x, pos.y));

		if (threadAttr->data.tLastPos.size() == 0 && pos.x != -1)
		{
			threadAttr->data.tPos = pos;
			threadAttr->data.tPos.find = true;
			env->addLastPosition(pos);
			threadAttr->data.tLastPos.push_back(pos);
		}
		else if (dist < 100 && dist != -1)
		{
			env->addLastPosition(pos);

			threadAttr->data.tLastPos.push_back(pos);
			threadAttr->data.tPos.find = true;
			threadAttr->data.tPos = pos;
			if (threadAttr->data.tLastPos.size() == FRAME)
			{
				env->deleteFirstPosition();
				threadAttr->data.tLastPos.erase(threadAttr->data.tLastPos.begin());
			}

		}
		else
		{
			// pierdo el robot
			printf("Robot Lost\n");
			Position p;
			p.x = -1;
			p.y = -1;
			threadAttr->data.tPos.find = false;
			threadAttr->data.tPos = p;

		}

		// dibujo un circulo donde esta el robot
		UI::drawRobot(grayImage, threadAttr->data);
		//UI::drawCircle(grayImage,
		//		ar::Point(threadAttr->data.tPos.x, threadAttr->data.tPos.y), 4, CF_BLACK);

		if(env->getDestinations().size() != 0)
		{
			// dibuja una cruz en los destinos
			UI::drawDestinations(grayImage, env->getDestinations());
			UI::drawNextDestination(grayImage, env->getDestinations(), nDestino);

			threadAttr->data.destino.x = env->getDestination(nDestino)->x;
			threadAttr->data.destino.y = env->getDestination(nDestino)->y;
		}


		// informacion en la pantalla.
		string line1 = format("SET-> Pitch: %.3f, Roll: %.3f, Yaw: %.3f, Dist: %d, D_x: %d, D_y: %d",
				threadAttr->data.copterSets.pitch, threadAttr->data.copterSets.roll,
				threadAttr->data.copterSets.yaw, threadAttr->data.dist_destino.z, threadAttr->data.dist_destino.x, threadAttr->data.dist_destino.y);

		string line2 = format(
				"GET--> Pitch: %.3f , Roll: %.3f, Yaw: %.3f, Altitude: %d cm, Desired Yaw: %.3f",
				threadAttr->data.copterValues.pitch, threadAttr->data.copterValues.roll,
				threadAttr->data.copterValues.yaw, threadAttr->data.copterValues.altitude, threadAttr->data.desired_yaw);
		string line3 = format(
				"Vel-Y: %f, Vel-X: %f, Vel-Z: %f cm/s",
				threadAttr->data.copterValues.vy, threadAttr->data.copterValues.vx,
				threadAttr->data.copterValues.vz);
		string line4 = format("Battery: %d %%, State: %s",
				threadAttr->data.copterValues.battery, threadAttr->data.copterValues.ctrl_state_sz.c_str());

		string line5 = format("POSICION--> X: %d, Y: %d, Z: %d",
				threadAttr->data.tPos.x, threadAttr->data.tPos.y, threadAttr->data.tPos.z);

		UI::drawText(grayImage, line1, ar::Point(10, 10), CF_RED);
		UI::drawText(grayImage, line2, ar::Point(10, 30), CF_BLUE);
		UI::drawText(grayImage, line3, ar::Point(10, 50), CF_BLUE);
		UI::drawText(grayImage, line4, ar::Point(10, 70), CF_BLUE);
		UI::drawText(grayImage, line5, ar::Point(10, 90), CF_BLACK);

		UI::drawMaxView(grayImage, threadAttr->data);

		UI::drawWindow("Deteccion", grayImage);

		//Genero los graficos sobre PID
		Mat graficos(cvSize(imgSize.width, HEIGHT_GRAF), CV_8UC3,
				cv::Scalar(255, 255, 255));

		UI::drawGraphics(graficos, threadAttr->data);

		vp_os_mutex_unlock(&threadAttr->mutex2);

		UI::drawWindow("Graficos", graficos);

		// compongo dos imagenes
		int height = imgSize.height;
		if(imgSize.height < HEIGHT_GRAF)
			height  = HEIGHT_GRAF;
		Mat grande(cvSize(imgSize.width * 2, height), CV_8UC3,
				cv::Scalar(255, 255, 255));

		grayImage.copyTo(
				grande.colRange(0, imgSize.width).rowRange(0, imgSize.height));
		graficos.copyTo(
				grande.colRange(imgSize.width, imgSize.width * 2).rowRange(0,
						HEIGHT_GRAF));
		// fin de composicion.

		env->getVideo()->grabVideoAndData(PROYECT_PATH + "videos/", "avi",
				str + "_2", outputVideo2, grande);

//		env->getVideo()->grabVideoAndData(PROYECT_PATH + "videos/", "avi",
//				str + "_3", outputVideo3, segmentated);

		UI::drawWindow("redMorphology", segmentated);

		char k = cvWaitKey(bContinue) & 0xff;

		vp_os_mutex_lock(&threadAttr->mutex2);
	//sem_wait(&threadAttr->mutex);
		threadAttr->data.key = k;
		vp_os_mutex_unlock(&threadAttr->mutex2);
	//sem_post(&threadAttr->mutex);

		switch (k)
		{
			case 27:
			case 'q':
			case 'Q':
				quit = true;
			break;
			case 's':
			case 'S':
				bContinue = false;
			break;
			case 'n':
			case 'N':
				bContinue = true;
			break;
		}
	}

	outputVideo.release();
	outputVideo2.release();
	outputVideo3.release();

	return 0;
}
Esempio n. 12
0
int main( int argc, const char** argv )
{
    CvCapture* capture = 0;
    Mat frame, frameCopy, image;
    Mat wframe;
    const string scaleOpt = "--scale=";
    size_t scaleOptLen = scaleOpt.length();
    const string cascadeOpt = "--cascade=";
    size_t cascadeOptLen = cascadeOpt.length();
    const string nestedCascadeOpt = "--nested-cascade";
    size_t nestedCascadeOptLen = nestedCascadeOpt.length();
    const string tryFlipOpt = "--try-flip";
    size_t tryFlipOptLen = tryFlipOpt.length();
    string inputName;
    bool tryflip = false;
	vw.open("rhogcomputed.avi",CV_FOURCC('D','I','V','X'),2,Size(128,128));
    help();

    CascadeClassifier cascade, nestedCascade;
    double scale = 1;

    for( int i = 1; i < argc; i++ )
    {
        cout << "Processing " << i << " " <<  argv[i] << endl;
        if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )
        {
            cascadeName.assign( argv[i] + cascadeOptLen );
            cout << "  from which we have cascadeName= " << cascadeName << endl;
        }
        else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )
        {
            if( argv[i][nestedCascadeOpt.length()] == '=' )
                nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );
            if( !nestedCascade.load( nestedCascadeName ) )
                cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
        }
        else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )
        {
            if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 )
                scale = 1;
            cout << " from which we read scale = " << scale << endl;
        }
        else if( tryFlipOpt.compare( 0, tryFlipOptLen, argv[i], tryFlipOptLen ) == 0 )
        {
            tryflip = true;
            cout << " will try to flip image horizontally to detect assymetric objects\n";
        }
        else if( argv[i][0] == '-' )
        {
            cerr << "WARNING: Unknown option %s" << argv[i] << endl;
        }
        else
            inputName.assign( argv[i] );
    }

    if( !cascade.load( cascadeName ) )
    {
        cerr << "ERROR: Could not load classifier cascade" << endl;
        help();
        return -1;
    }

    if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
    {
        capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );
        int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ;
        if(!capture) cout << "Capture from CAM " <<  c << " didn't work" << endl;
    }
    else if( inputName.size() )
    {
        image = imread( inputName, 1 );
        if( image.empty() )
        {
            capture = cvCaptureFromAVI( inputName.c_str() );
            if(!capture) cout << "Capture from AVI didn't work" << endl;
        }
    }
    else
    {
        image = imread( "lena.jpg", 1 );
        if(image.empty()) cout << "Couldn't read lena.jpg" << endl;
    }

   // cvNamedWindow( "result", 1 );

    if( capture )
    {
        cout << "In capture ..." << endl;
        for(;;)
        {
            IplImage* iplImg = cvQueryFrame( capture );
            frame = cv::cvarrToMat(iplImg);
            if( frame.empty() )
                break;
            if( iplImg->origin == IPL_ORIGIN_TL )
                frame.copyTo( frameCopy );
            else
                flip( frame, frameCopy, 0 );

            wframe = detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip  );
   	         
			c= waitKey(10);
			
            if( c=='e' )
                
                {
                	return 0;
                	
                	goto _cleanup_;
                	
                }
                
        }

        waitKey(0);

_cleanup_:
        cvReleaseCapture( &capture );
        vw.release();
    }
    else
    {
        cout << "In image read" << endl;
        if( !image.empty() )
        {
            wframe = detectAndDraw( image, cascade, nestedCascade, scale, tryflip  );
            waitKey(0);
        }
        else if( !inputName.empty() )
        {
            /* assume it is a text file containing the
            list of the image filenames to be processed - one per line */
            FILE* f = fopen( inputName.c_str(), "rt" );
            if( f )
            {
                char buf[1000+1];
                while( fgets( buf, 1000, f ) )
                {
                    int len = (int)strlen(buf), c;
                    while( len > 0 && isspace(buf[len-1]) )
                        len--;
                    buf[len] = '\0';
                    cout << "file " << buf << endl;
                    image = imread( buf, 1 );
                    if( !image.empty() )
                    {
                        wframe = detectAndDraw( image, cascade, nestedCascade, scale, tryflip  );
                        c = waitKey(0);
                        if( c == 27 || c == 'q' || c == 'Q' )
                            break;
                    }
                    else
                    {
                        cerr << "Aw snap, couldn't read image " << buf << endl;
                    }
                }
                fclose(f);
            }
        }
    }

    cvDestroyWindow("result");
	
    return 0;
}
Esempio n. 13
0
void test_video(const Size & size)
{
	char key = 27;
	Mat img, draw;
	Ptr<SVM> svm;
	HOGDescriptor hog;
	hog.winSize = size;
	vector< Rect > locations;
	vector< Rect > found_filtered;

	// Load the trained SVM.
	svm = StatModel::load<SVM>(TRAINED_SVM);
	// Set the trained svm to my_hog
	vector< float > hog_detector;
	get_svm_detector(svm, hog_detector);
	hog.setSVMDetector(hog_detector);
	printHOGParams(hog);

	VideoCapture video;
	// Open the video file.
	video.open(TRAFFIC_VIDEO_FILE);
	if (!video.isOpened())
	{
		cerr << "Unable to open the device" << endl;
		exit(-1);
	}
	// Get the frame rate
	double rate = video.get(CV_CAP_PROP_FPS);
	cout << " Frame rate : " << rate << endl;
	cout << " Input video codec :" << video.get(CV_CAP_PROP_FOURCC);
	// initilaize the video writer object to write the video output
	std::string outputFile(OUT_Video_File);
	VideoWriter writer;
	int codec = static_cast<int>(video.get(CV_CAP_PROP_FOURCC));
	//int codec = CV_FOURCC('M', 'J', 'P', 'G');
	bool isWriterInitialized = false;

	int num_of_vehicles = 0;
	bool end_of_process = false;
	while (!end_of_process)
	{
		video >> img;
		if (img.empty())
			break;


		draw = img.clone();
		Mat cropped;
		cv::resize(draw, cropped, Size(720, 560));

		Mat temp, temp3;
		cvtColor(cropped, temp, COLOR_BGR2GRAY);
		/*Mat bgr[3];   //destination array
		split(temp3,bgr);//split source
		temp = bgr[0]+bgr[2];
		*/
		if (isWriterInitialized) {
			//execute only once
			isWriterInitialized = true;
			/*writer.open(outputFile,
			capture.get(CV_CAP_PROP_FOURCC),
			capture.get(CV_CAP_PROP_FPS),
			Size(capture.get(CV_CAP_PROP_FRAME_WIDTH),capture.get(CV_CAP_PROP_FRAME_HEIGHT)),
			true);*/
			writer.open(outputFile, codec, rate, cropped.size(), true);
		}


		locations.clear();
		// Rect(x,y,w,h) w->width=cols;h->rows
		// first remove the upper 50% from height  Original Cropped =size(720,560)=(cols,rows)
		Mat roi = temp(Rect(0, temp.rows*0.5, temp.cols, temp.rows - temp.rows*0.5));
		//size(roi) = size(720,280)
		//cout<<"roi.size() = "<<roi.size()<<endl;
		int y_offset = temp.rows*0.5;
		//again crop the lower 10 % to remove the images near dashboard-> remove false positives
		roi = roi(Rect(0, 0, roi.cols, roi.rows - 100));
		//cout<<"roi.size() = "<<roi.size()<<endl;
		//no offset required as this is the lower row colums.

		//hog.detectMultiScale(roi, locations);
		//hog.detectMultiScale(roi, locations, 1, Size(50, 50), Size(32, 32), 1, 2);//对图片进行多尺度行人检测

		hog.detectMultiScale(roi, locations, 0.00, Size(4, 8), Size(0, 0), 1.05, 2);//less false positive
																					//hog.detectMultiScale(roi, locations, 0.00, Size(8,8), Size(0,0), 1.05, 2);// less true negative(missed)
																					// add the offset



		std::vector<Rect>::iterator it = locations.begin();
		std::vector<Rect>::iterator itend = locations.end();
		vector<Rect> actuallocations;
		bool isVehicle = false;
		for (; it != itend; it++)
		{
			Rect current = *it;
			//cout<<" Rect current = "<< current<<endl;
			//cout<<" roi size= "<<roi.size()<<endl;
			Mat roi2Check = roi(Rect(current.x, current.y, current.width, current.height));//define a roi of 50x50
																						   //cout<<" roi2Check size= "<<roi2Check.size()<<endl;
			isVehicle = checkIfpatchIsVehicle(roi2Check);
			if (isVehicle)
				actuallocations.push_back(Rect(current.x, current.y + y_offset, current.width, current.height));
		}
		if (0 != actuallocations.size())
			draw_locations(cropped, actuallocations, Scalar(0, 255, 0));

		imshow(WINDOW_NAME, cropped);





		if (save_video)
			writer.write(cropped);
		//wait  infinite fro keypress
		key = (char)waitKey(3);
		if (27 == key)
			end_of_process = true;
	}
	// Close the video file.
	// Not required since called by destructor
	writer.release();
	video.release();
}
Esempio n. 14
0
int main(int argc, char** argv ) {

    ofstream outfile;

    srand( time(NULL) );

    if( argc < 2 || argc > 3 ) {
        cerr << "Argc " << argc << endl;
        cerr << "Usage: " << argv[0] << " VIDEO_CAPTURE_FILE " << "[VIDEO_OUTPUT_FILE.mp4]" << endl;
        cerr << "Matej Minarik (C) ElectroMeter " << VERSION << endl;
        cerr << "OpenCV " << CV_VERSION << endl;
        return 1;
    }

    outfile.open( "data.txt" );
    VideoCapture cap( argv[1] );
    if( cap.isOpened() == false && outfile.is_open() ) {
        cerr << "Cannot open file" << endl;
        return -1;
    }

    double frameWidth  = cap.get( CV_CAP_PROP_FRAME_WIDTH );
    double frameHeight = cap.get( CV_CAP_PROP_FRAME_HEIGHT );
    double videoFPS    = cap.get( CV_CAP_PROP_FPS );

    VideoWriter vw;
    if( argc == 3 ) {
        bool open = vw.open( argv[2], CV_FOURCC('m', 'p', '4', 'v'), videoFPS, Size((int)frameWidth, (int)frameHeight));
        if( false == open || false == vw.isOpened() ) {
            cerr << "Cannot open file " << argv[2] << endl;
            return -1;
        }
    }

    cout << " Width:  " << frameWidth << endl;
    cout << " Height: " << frameHeight << endl;
    cout << " FPS:    " << videoFPS << endl;

    int indicatorY = (int) ((float) frameHeight * 0.1);
    int indicatorX = (int) ((float) frameWidth * 0.8);

    namedWindow(WIN_TITLE);
    resizeWindow(WIN_TITLE, frameHeight, frameWidth);

    Mat currFrame, cloneFrame;
    Vec3b currPixel;
    Vec3b filterPixel;
    unsigned long sumR, sumG, sumB;
    unsigned long frameNo = 0;
    unsigned long lastR = 0;
    while( cap.read(currFrame) ) {
        sumR = sumG = sumB = 0;

        cloneFrame = currFrame.clone();

        for( int i = 0; i < frameHeight; i++ ) {
            for( int j = 0; j < frameWidth; j++ ) {
                currPixel = currFrame.at<Vec3b>(Point(j, i));
                sumR += currPixel[2];
                if( cloneFrame.at<Vec3b>(Point(j, i))[0] + filterPixel[0] > 255 ) {
                    cloneFrame.at<Vec3b>(Point(j, i))[0] = 255;
                } else {
                    cloneFrame.at<Vec3b>(Point(j, i))[0] += filterPixel[0];
                }
                if( cloneFrame.at<Vec3b>(Point(j, i))[1] + filterPixel[1] > 255 ) {
                    cloneFrame.at<Vec3b>(Point(j, i))[1] = 255;
                } else {
                    cloneFrame.at<Vec3b>(Point(j, i))[1] += filterPixel[1];
                }
                if( cloneFrame.at<Vec3b>(Point(j, i))[2] + filterPixel[2] > 255 ) {
                    cloneFrame.at<Vec3b>(Point(j, i))[2] = 255;
                } else {
                    cloneFrame.at<Vec3b>(Point(j, i))[2] += filterPixel[2];
                }
            }
        }

        vw.write( cloneFrame );

        outfile << frameNo;
        outfile << " " << sumR;
        outfile << endl;

        ++frameNo;
        if( lastR != 0 ) {
            float ratio = (float) sumR / (float) lastR;
            if( ratio > 1.08 ) {
                showIndicator(indicatorX, indicatorY, cloneFrame);
                cout << "Dot " << frameNo << " " << indicatorX << ":" << indicatorY;
                cout << " ratio " << ratio << endl;
                if( true == filterShouldChange(frameNo) ) {
                    filterPixel = getRandomFilter();
                }
            } else {
                lastR = sumR;
            }
        } else {
            lastR = sumR;
        }

        imshow(WIN_TITLE, cloneFrame);
        if( waitKey(29) >= 0 ) break;
    }

    outfile.close();
    cap.release();

    if( argc == 3) {
        vw.release();
    }

    return 0;
}
Esempio n. 15
0
int main(int argc, char** argv)
{
//**********************************************************************
//-- Network code ------------------------------------------------------
//**********************************************************************
    int localSocket;
    int remoteSocket;
    int port = 8080;

    struct sockaddr_in localAddr;
    struct sockaddr_in remoteAddr;
           
    int addrLen = sizeof(struct sockaddr_in);

    localSocket = socket(AF_INET , SOCK_STREAM , 0);
    
    if (localSocket == -1)
        exit(1);

    localAddr.sin_family = AF_INET;
    localAddr.sin_addr.s_addr = INADDR_ANY;
    localAddr.sin_port = htons(port);

    if (bind(localSocket, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0)
        exit(1);

    // Listening
    listen(localSocket , 1);

    // Accept connection from an incoming client
    remoteSocket = accept(localSocket, (struct sockaddr *)&remoteAddr, (socklen_t*)&addrLen);
    
    if (remoteSocket < 0)
        exit(1);

//**********************************************************************
//-- OpenCV code -------------------------------------------------------
//**********************************************************************
    VideoCapture cap(0);                                                // "0": Open the default camera
    Mat img, imgGray;
    img = Mat::zeros(480 , 640, CV_8U);    

    if (!img.isContinuous())
        img = img.clone();

    int imgSize = img.total() * img.elemSize();
    int bytes = 0;
    int key;

    if (!img.isContinuous())
    {
          img = img.clone();
          imgGray = img.clone();
    }

	VideoWriter videoOut;

	videoOut.open("rec.avi", CV_FOURCC('P','I','M','1'),                // File name, MPEG-1, 25 fps, 640x480, isColor = true
                  20, Size(640,480), false);
 
    while(1)
    {
        cap >> img;
        
        resize(img, img, Size(640, 480));

        // Video processing 
        cvtColor(img, imgGray, CV_BGR2GRAY);

		videoOut << imgGray;

        // Send processed image
        if ((bytes = send(remoteSocket, imgGray.data, imgSize, 0)) < 0)
             break;
    }

	videoOut.release();
    close(remoteSocket);

    return 0;
}
Esempio n. 16
0
int main(int argc, char** argv ){


    //init capture devices
    cap0 = ConfigVideoCapture(cap0dev);
    cap1 = ConfigVideoCapture(cap1dev);
    namedWindow("cap0",WINDOW_NORMAL);
    namedWindow("cap1",WINDOW_NORMAL);

    outputVideocap0.open("RecoredVideo/Cam0.avi",CV_FOURCC('M', 'J', 'P', 'G'),11,Size(720,960),true);
    outputVideocap1.open("RecoredVideo/Cam1.avi",CV_FOURCC('M', 'J', 'P', 'G'),11,Size(720,960),true);
    if (!outputVideocap0.isOpened() || !outputVideocap1.isOpened())
    {
            printf("Output video could not be opened\n");
            return 0;
    }


    if (!cap0.isOpened() || !cap1.isOpened()){
            printf("Output video could not be opened\n");
            return 0;
    }

    //record video
    printf("Starting to record video... \n(Press 'c'-key to stop)\n");
    fflush(stdout);
    for(;;){
            clock_t begin = clock();
            thread Grab0(threadGrab0);
            thread Grab1(threadGrab1);
            Grab0.join();
            Grab1.join();
            
	    

            char c = (char)waitKey(1);
            if( c == 'c')
                break;

	    clock_t end = clock();
	    double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
	    double fps = 1.0/elapsed_secs;
	    printf("FPS: %f (Press 'c'-key to stop)\n",fps);
	    fflush(stdout);
    }
    
    printf("Writeing video to harddrive...");
    fflush(stdout);
    for(Mat img : leftImgs)
    {
        outputVideocap0.write(img);
    }

    for(Mat img : rightImgs)
    {
        outputVideocap1.write(img);
    }
    outputVideocap0.release();
    outputVideocap1.release();

    printf(" done\n");
    fflush(stdout);
    return 0;
}
int main(int argc, char** argv) {
	/* the input and output dir */
	string input_dir = "/home/user/ccv/data/sunny_day-img-left";

	/* initialize the ccv states */
	ccv_enable_default_cache();
	ccv_dpm_mixture_model_t* model = ccv_dpm_read_mixture_model(argv[1]);

	/* set the pedestrian detection parameters */
	ccv_dpm_param_t myparameters;
	myparameters.threshold = 0.4;
	myparameters.interval = 8;
	myparameters.min_neighbors = 1;
	myparameters.flags = 0;

	/* debug */
	string source = "/home/user/ccv/demo1.avi";
	VideoCapture inputVideo(source);              // Open input
	if (!inputVideo.isOpened()) {
		cout  << "Could not open the input video: " << source << endl;
		return -1;
	}
	int ex = static_cast<int>(inputVideo.get(CV_CAP_PROP_FOURCC));     // Get Codec Type- Int form
	cout<<"The coding is "<<ex<<endl;
	cout<<"The fps is "<<inputVideo.get(CV_CAP_PROP_FPS)<<endl;

	/* initialize the video writer */
	Mat getSize = imread(input_dir + "/image_00000100_0.png");
	Size videoSize = getSize.size();
	getSize.release();
	VideoWriter outputVideo;
	outputVideo.open("/home/user/ccv/data/output/eth2_reg_overlaps.avi", ex, fps, videoSize, true);
	if (!outputVideo.isOpened()) {
		cout<<"Could not open the output video"<<endl;
		return false;
	}


	/* process one by one */
	for (int iImage = imageStart; iImage <= imageEnd; iImage++) {

		/* read the image, ccv_image for detection, and opencv Mat for recording */
		string imageTail;
		if (iImage < 10) imageTail = "0000000" + patch::to_string(iImage);
		else if (iImage < 100) imageTail = "000000" + patch::to_string(iImage);
		else imageTail = "00000" + patch::to_string(iImage);
		string image_name = input_dir + "/image_" + imageTail + "_0.png";

		ccv_dense_matrix_t* image = 0;
		ccv_read(image_name.c_str(), &image, CCV_IO_ANY_FILE);
		Mat plot_result = imread(image_name);
		if (image == 0) cerr<<"The reading of dataset failed!"<<endl;
		cout<<"Image succussfully read"<<endl;

		/* processing the image one by one */
		unsigned int elapsed_time = get_current_time();
		ccv_array_t* seq = ccv_dpm_detect_objects(image, &model, 1, myparameters);
		elapsed_time = get_current_time() - elapsed_time;
		cout<<"Using "<<elapsed_time<<"ms on detecting the "<<iImage<<"th image"<<endl;

		if (seq != NULL) { 
			/* get the overlaps */
			bool* flag = new bool[seq->rnum];
			for (int i = 0; i < seq->rnum; i++) flag[i] = true;
			for (int i = 0; i < seq->rnum; i++) {
				for (int j = 0; i < seq->rnum; i++) {
					/* a bigger area */
					ccv_root_comp_t* comp1 = (ccv_root_comp_t*)ccv_array_get(seq, i); /* get the ith number */
					ccv_root_comp_t* comp2 = (ccv_root_comp_t*)ccv_array_get(seq, j); /* get the jth number */
					float dx1 = comp1->rect.x - comp2->rect.x;
					float dx2 = comp1->rect.x + comp1->rect.width - comp2->rect.x + comp2->rect.width;
					if (abs(dx1) / comp1->rect.width < 0.2 && abs(dx2) / comp2->rect.width < 0.2 &&
							abs(dx1) / comp2->rect.width < 0.2 && abs(dx2) / comp1->rect.width < 0.2 &&
							get_overlaps(comp1, comp2) > 0.5) {
						rectangle(plot_result, 
								cv::Point(int(min(comp1->rect.x, comp2->rect.x)), int(min(comp1->rect.y, comp2->rect.y))),
								cv::Point(int(max(comp1->rect.x + comp1->rect.width, comp2->rect.x + comp2->rect.width)), 
										int(max(comp1->rect.y + comp1->rect.height, comp2->rect.y + comp2->rect.height))),
								cvScalar(255, 0, 0), 2, 8, 0);
					}

				}
			}
			/* the detection has something to say */
			for (int i = 0; i < seq->rnum; i++) {
				ccv_root_comp_t* comp = (ccv_root_comp_t*)ccv_array_get(seq, i); /* get the ith number */
				/* a simple regression trick */
				float predHeight = ((float)videoSize.height / 2 - comp->rect.y) * 2 + 10;
				if (predHeight - comp->rect.height > predHeight * 0.5) {
					rectangle(plot_result, 
							cv::Point(int(comp->rect.x), int(comp->rect.y)),
							cv::Point(int(comp->rect.x + comp->rect.width), int(comp->rect.y + comp->rect.height)),
							cvScalar(0, 0, 255), 2, 8, 0);
				} else{
					rectangle(plot_result, 
							cv::Point(int(comp->rect.x), int(comp->rect.y)),
							cv::Point(int(comp->rect.x + comp->rect.width), int(comp->rect.y + comp->rect.height)),
							cvScalar(0, 255, 0), 2, 8, 0);
				}
			}
			ccv_array_free(seq); /* release the sequence */
		}
		outputVideo << plot_result;

		/* free the images */
		ccv_matrix_free(image);
		plot_result.release();
	}


	outputVideo.release();
	ccv_drain_cache();
	ccv_dpm_mixture_model_free(model);
	return 0;
}
Esempio n. 18
0
	JNIEXPORT void JNICALL Java_com_test_opencvtest_OpenCvUtility_releaseVideo(JNIEnv* jEnv, jobject jObj) {
		if (!videoWriterReleased) {
			videoWriter.release();
			videoWriterReleased=-1;
		}
	}
int main(int argc, char** argv)
{
    if(argc >= 3)
    {
        VideoCapture inputVideo(argv[1]); // open the default camera
        if(!inputVideo.isOpened())  // check if we succeeded
            return -1; 
        
        // Initialize
        VideoWriter outputVideo;  // Open the output
        const string source      = argv[2];                                // the source file name
        const string NAME = source + ".mp4";   // Form the new name with container
        int ex = inputVideo.get(CV_CAP_PROP_FOURCC);                       // Get Codec Type- Int form
        std::cout << ex << "\n" << (int)inputVideo.get(CV_CAP_PROP_FOURCC) << "\n";
        Size S = Size((int) inputVideo.get(CV_CAP_PROP_FRAME_WIDTH),       //Acquire input size
                      (int) inputVideo.get(CV_CAP_PROP_FRAME_HEIGHT));    
        outputVideo.open(NAME, ex, inputVideo.get(CV_CAP_PROP_FPS), S, false);
        char EXT[] = {(char)(ex & 0XFF) , (char)((ex & 0XFF00) >> 8),(char)((ex & 0XFF0000) >> 16),(char)((ex & 0XFF000000) >> 24), 0};
        cout << "Input codec type: " << EXT << endl;

         if (!outputVideo.isOpened())
        {
            cout  << "Could not open the output video for write \n";
            return -1;
        }
                // Basketball Color
        int iLowH = 180;
        int iHighH = 16;
        
        int iLowS =  95;
        int iHighS = 200;
        
        int iLowV = 75;
        int iHighV = 140;
        
        // court Color
        int courtLowH = 0;
        int courtHighH = 20;
        
        int courtLowS = 50;
        int courtHighS = 150;
        
        int courtLowV = 160;
        int courtHighV = 255;
        
        namedWindow("Result Window", 1);
        //namedWindow("Court Window", 1);
        
        // Mat declaration
        Mat prev_frame, prev_gray, cur_frame, cur_gray;
        Mat frame_blurred, frameHSV, frameGray;
        
        // take the first frame
        inputVideo >> prev_frame;
        
        /* manual ball selection */
        MouseParams mp;
        prev_frame.copyTo( mp.ori );
        prev_frame.copyTo( mp.img );
        setMouseCallback("Result Window", BallSelectFunc, &mp );
        
        int enterkey = 0;
        while(enterkey != 32 && enterkey != 113)
        {
            enterkey = waitKey(30) & 0xFF;
            imshow("Result Window", mp.img);
        }
        Rect  lastBallBox;
        Point lastBallCenter;
        Point lastMotion;
        
        /* Kalman Filter Initialization */
        KalmanFilter KF(4, 2, 0);
        float transMatrixData[16] = {1,0,1,0, 0,1,0,1, 0,0,1,0, 0,0,0,1};
        KF.transitionMatrix = Mat(4, 4, CV_32F, transMatrixData);
        Mat_<float> measurement(2,1);
        measurement.setTo(Scalar(0));
        
        KF.statePre.at<float>(0) = mp.pt.x;
        KF.statePre.at<float>(1) = mp.pt.y;
        KF.statePre.at<float>(2) = 0;
        KF.statePre.at<float>(3) = 0;
        setIdentity(KF.measurementMatrix);
        setIdentity(KF.processNoiseCov, Scalar::all(1e-4));
        setIdentity(KF.measurementNoiseCov, Scalar::all(1e-1));
        setIdentity(KF.errorCovPost, Scalar::all(.1));
        int pre_status_7=0;
        
        /* start tracking */
        setMouseCallback("Result Window", CallBackFunc, &frameHSV);
        
        for(int frame_num=1; frame_num < inputVideo.get(CAP_PROP_FRAME_COUNT); ++frame_num)
        {
            int cur_status_7=pre_status_7;
            
            inputVideo >> cur_frame; // get a new frame
            // Blur & convert frame to HSV color space
            cv::GaussianBlur(prev_frame, frame_blurred, cv::Size(5, 5), 3.0, 3.0);
            cvtColor(frame_blurred, frameHSV, COLOR_BGR2HSV);
            
            // gray scale current frame
            cvtColor(prev_frame, prev_gray, CV_BGR2GRAY);
            cvtColor(cur_frame, cur_gray, CV_BGR2GRAY);
            
            /*
             * STAGE 1: mask generation
             * creating masks for balls and courts.
             */
            Mat mask, mask1, mask2, court_mask;
            inRange(frameHSV, Scalar(2, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), mask1);
            inRange(frameHSV, Scalar(iLowH, iLowS, iLowV), Scalar(180, iHighS, iHighV), mask2);
            inRange(frameHSV, Scalar(courtLowH, courtLowS, courtLowV), Scalar(courtHighH, courtHighS, courtHighV), court_mask);
            
            mask = mask1 + mask2;
            
            // morphological opening (remove small objects from the foreground)
            erode(mask, mask, getStructuringElement(MORPH_ELLIPSE, Size(7, 7)) );
            dilate(mask, mask, getStructuringElement(MORPH_ELLIPSE, Size(7, 7)) );
            
            // morphological closing (fill small holes in the foreground)
            dilate(mask, mask, getStructuringElement(MORPH_ELLIPSE, Size(7, 7)) );
            erode(mask, mask, getStructuringElement(MORPH_ELLIPSE, Size(7, 7)) );
            
            /*
             * Method:  HoughCircles
             * creating circles and radius.
             */
            // Basketball Color for Hough circle
            
            int iLowH = 180;
            int iHighH = 16;
            
            int iLowS =  95;
            int iHighS = 200;
            
            int iLowV = 75;
            int iHighV = 140;
            
            Mat mask1_circle, mask2_circle, mask_circle, frameHSV_circle, frameFiltered,frameGray2;
            cvtColor(frame_blurred, frameHSV_circle, COLOR_BGR2HSV);
            inRange(frameHSV_circle, Scalar(0, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), mask1_circle);
            inRange(frameHSV_circle, Scalar(iLowH, iLowS, iLowV),Scalar(180, iHighS, iHighV), mask2_circle);
            mask_circle = mask1_circle + mask2_circle;
            erode(mask_circle, mask_circle, getStructuringElement(MORPH_ELLIPSE, Size(7, 7)) );
            dilate(mask_circle, mask_circle, getStructuringElement(MORPH_ELLIPSE, Size(7, 7)) );
            
            prev_frame.copyTo( frameFiltered, mask_circle );
            cv::cvtColor( frameFiltered, frameGray2, CV_BGR2GRAY );
            vector<cv::Vec3f> circles;
            cv::GaussianBlur(frameGray2, frameGray2, cv::Size(5, 5), 3.0, 3.0);
            HoughCircles( frameGray2, circles, CV_HOUGH_GRADIENT, 1, frameGray2.rows/8, 120, 18, 5,300);
            
            /*
             * STAGE 2: contour generation
             * creating contours with masks.
             */
            vector< vector<cv::Point> > contours_ball;
            vector< vector<cv::Point> > contours_court;
            cv::findContours(mask, contours_ball, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
            
            Mat result;
            
            prev_frame.copyTo( result );
            
            /*
             // court mask refinement: eliminate small blocks
             Mat buffer;
             court_mask.copyTo( buffer );
             cv::findContours(buffer, contours_court, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
             
             for (size_t i = 0; i < contours_court.size(); i++)
             {
             double tmp_area = contourArea( contours_court[i] );
             if(tmp_area < 900.0)
             drawContours(court_mask, contours_court, i, 0, CV_FILLED);
             }
             bitwise_not(court_mask, court_mask);
             court_mask.copyTo( buffer );
             cv::findContours(buffer, contours_court, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
             for (size_t i = 0; i < contours_court.size(); i++)
             {
             double tmp_area = contourArea( contours_court[i] );
             if(tmp_area < 900.0)
             drawContours(court_mask, contours_court, i, 0, CV_FILLED);
             }
             bitwise_not(court_mask, court_mask);
             
             Mat canny_mask;
             Canny(court_mask, canny_mask, 50, 150, 3);
             vector<Vec4i> lines;
             HoughLinesP(canny_mask, lines, 1, CV_PI/180, 80, 30, 10);
             
             Point l_top( mask.cols/2, mask.rows );
             Point l_bot( mask.cols/2, mask.rows );
             
             for( size_t i = 0; i < lines.size(); i++ )
             {
             Point p1 = Point(lines[i][0], lines[i][1]);
             Point p2 = Point(lines[i][2], lines[i][3]);
             
             if(p1.y < l_top.y)
             {
             l_top = p1;
             l_bot = p2;
             }
             if(p2.y < l_top.y)
             {
             l_top = p2;
             l_bot = p1;
             }
             }
             // stretch the line
             Point v_diff = l_top - l_bot;
             Point p_left, p_right;
             
             
             int left_t  = l_top.x / v_diff.x;
             int right_t = (mask.cols - l_top.x) / v_diff.x;
             
             p_left = l_top - v_diff * left_t;
             p_right = l_top + v_diff * right_t;
             
             line( court_mask, p_left, p_right, Scalar(128), 2, 8 );
             imshow("Court Window", court_mask);
             */
            
            // sieves
            vector< vector<cv::Point> > balls;
            vector<cv::Point2f> prev_ball_centers;
            vector<cv::Rect> ballsBox;
            Point best_candidate;
            for (size_t i = 0; i < contours_ball.size(); i++)
            {
                drawContours(result, contours_ball, i, CV_RGB(255,0,0), 1);  // fill the area
                
                cv::Rect bBox;
                bBox = cv::boundingRect(contours_ball[i]);
                Point center;
                center.x = bBox.x + bBox.width / 2;
                center.y = bBox.y + bBox.height / 2;
                
                // meet prediction!
                if( mp.pt.x > bBox.x && mp.pt.x < bBox.x + bBox.width &&
                   mp.pt.y > bBox.y && mp.pt.y < bBox.y + bBox.height)
                {
                    // initialization of ball position at first frame
                    if( frame_num == 1 || ( bBox.area() <= lastBallBox.area() * 1.5 && bBox.area() >= lastBallBox.area() * 0.5) )
                    {
                        lastBallBox = bBox;
                        lastBallCenter = center;
                        
                        balls.push_back(contours_ball[i]);
                        prev_ball_centers.push_back(center);
                        ballsBox.push_back(bBox);
                        best_candidate = center;
                    }
                    else
                    {
                        cout << "area changed!" << endl;
                        // if the block containing ball becomes too large,
                        // we use last center + motion as predicted center
                        balls.push_back(contours_ball[i]);
                        prev_ball_centers.push_back( lastBallCenter+lastMotion );
                        ballsBox.push_back(bBox);
                        best_candidate = lastBallCenter + lastMotion;
                    }
                }
                else
                {
                    // ball size sieve
                    
                    if(  bBox.area() > 1600 )
                        continue;
                    
                    // ratio sieve
                    //                     float ratio = (float) bBox.width / (float) bBox.height;
                    //                     if( ratio < 1.0/2.0 || ratio > 2.0 )
                    //                     continue;
                    
                    // ball center sieve: since we've done dilate and erode, not necessary to do.
                    /*
                     uchar center_v = mask.at<uchar>( center );*
                     if(center_v != 1)
                     continue;
                     */
                    
                    // ball-on-court sieve: not useful in basketball =(
                    //if(court_mask.at<uchar>(center) != 255)
                    //  continue;
                    
                    balls.push_back(contours_ball[i]);
                    prev_ball_centers.push_back(center);
                    ballsBox.push_back(bBox);
                }
            }
            
            
            // store the center of the hough circle
            vector<cv::Point2f> prev_ball_centers_circle;
            for( size_t circle_i = 0; circle_i < circles.size(); circle_i++ )
            {
                Point center_circle(cvRound(circles[circle_i][0]), cvRound(circles[circle_i][1]));
                int radius_circle = cvRound(circles[circle_i][2]);
                prev_ball_centers_circle.push_back(center_circle);
            }
            // Kalman Filter Prediction
            //Mat prediction = KF.predict();
            //Point predictPt(prediction.at<float>(0),prediction.at<float>(1));
            // Kalman Filter Update
            //Mat estimated = KF.correct( best_candidate );
            
            //OpticalFlow for HSV
            vector<Point2f> cur_ball_centers;
            vector<uchar> featuresFound;
            Mat err;
            TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS, 20, 0.03);
            Size winSize(31, 31);
            if( prev_ball_centers.size() > 0 )
                calcOpticalFlowPyrLK(prev_gray, cur_gray, prev_ball_centers, cur_ball_centers, featuresFound, err, winSize, 3, termcrit, 0, 0.001);
            
            //OpticalFlow for circle
            vector<Point2f> cur_ball_centers_circle;
            vector<uchar> featuresFound_circle;
            Mat err2;
            if( prev_ball_centers_circle.size() > 0 )
                calcOpticalFlowPyrLK(prev_gray, cur_gray, prev_ball_centers_circle, cur_ball_centers_circle, featuresFound_circle, err2, winSize, 3, termcrit, 0, 0.001);
            
            //plot MP
            circle(result, mp.pt, 2, CV_RGB(255,255,255), 5);
            cout<<"frame_num :"<<frame_num<<endl;
            cout<<"lastMotion"<<lastMotion<<endl;
            bool ball_found = false;
            
            for (size_t i = 0; i < balls.size(); i++)
            {
                cv::Point center;
                center.x = ballsBox[i].x + (ballsBox[i].width / 2);
                center.y = ballsBox[i].y + (ballsBox[i].height/2);
                // consider hough circle
                int circle_in_HSV=0;
                int in=0;
                for( size_t circle_i = 0; circle_i < circles.size(); circle_i++ )
                {
                    
                    
                    Point center2(cvRound(circles[circle_i][0]), cvRound(circles[circle_i][1]));
                    int radius = cvRound(circles[circle_i][2]);
                    double dis_center =  sqrt(pow(center2.x-center.x,2)+pow(center2.y-center.y,2));
                    
                    if( frame_num >2 && radius<40 && dis_center<radius+3 && mp.pt.x > ballsBox[i].x && mp.pt.x < ballsBox[i].x + ballsBox[i].width && mp.pt.y > ballsBox[i].y && mp.pt.y < ballsBox[i].y + ballsBox[i].height){
                        circle_in_HSV=1;
                        Point motion = cur_ball_centers_circle[circle_i] - prev_ball_centers_circle[circle_i];
                        mp.pt = Point2f(cur_ball_centers_circle[circle_i].x, cur_ball_centers_circle[circle_i].y);
                        lastMotion = motion;
                        cout<<mp.pt<<endl;
                        cout<<"status 1"<<endl;
                        cout<<motion<<endl;
                        ball_found = true;
                        in=1;
                        cout<<in<<endl;
                        cv::circle( result, center2, radius, Scalar(0,255,0), 2 );
                    }
                    
                    //                    if(radius<40){
                    //                        stringstream sstr;
                    //                        sstr << "(" << center2.x << "," << center2.y << ")";
                    ////                        cv::putText(result, sstr.str(),
                    ////                                    cv::Point(center2.x + 3, center2.y - 3),
                    ////                                    cv::FONT_HERSHEY_SIMPLEX, 0.5, CV_RGB(20,150,20), 2);
                    //                        cv::circle( result, center2, radius, Scalar(12,12,255), 2 );}
                }
                
                // see if any candidates contains out ball
                if( circle_in_HSV==0 && mp.pt.x > ballsBox[i].x && mp.pt.x < ballsBox[i].x + ballsBox[i].width && mp.pt.y > ballsBox[i].y && mp.pt.y < ballsBox[i].y + ballsBox[i].height)
                {
                    cv::rectangle(result, ballsBox[i], CV_RGB(0,255,0), 2);
                    Point motion = cur_ball_centers[i] - prev_ball_centers[i];
                    // update points and lastMotion
                    
                    float ratio = (float) ballsBox[i].width / (float) ballsBox[i].height;
                    if( ballsBox[i].area() < 1000 && ratio>0.7 && ratio<1.35 && ballsBox[i].area() > 200){
                        mp.pt = Point2f(center.x, center.y);
                        cout<<"status 2"<<endl;
                        cout<<"AREA:"<<ballsBox[i].area()<<endl;
                    }else{
                        mp.pt = Point2f(mp.pt.x+motion.x, mp.pt.y+motion.y);
                        cout<<"status 3"<<endl;
                    }
                    // TODO replace with predicted points of kalman filter here.
                    lastMotion = motion;
                    ball_found = true;
                }
                
                // draw optical flow
                if(!featuresFound[i])
                    continue;
                
                cv::Point2f prev_center = prev_ball_centers[i];
                cv::Point2f curr_center = cur_ball_centers[i];
                cv::line( result, prev_center, curr_center, CV_RGB(255,255,0), 2);
                
            }
            
            // if ball is not found, search for the closest ball candidate within a distance.
            if(!ball_found)
            {
                int search_distance_threshold = 35*35;
                int closest_dist      = 2000;
                //                int closest_dist2      = 2000;
                int closest_area_diff = 10000;
                int best_i = 0;
                
                for (size_t i = 0; i < balls.size(); i++)
                {
                    int diff_x = prev_ball_centers[i].x - mp.pt.x;
                    int diff_y = prev_ball_centers[i].y - mp.pt.y;
                    int area_threshold_high = 100*100;
                    int area_threshold_low = 15*15;
                    int distance  = diff_x * diff_x + diff_y * diff_y;
                    int area_diff = abs(ballsBox[i].area()-lastBallBox.area());
                    float ratio = (float) ballsBox[i].width / (float) ballsBox[i].height;
                    //                    if(distance<closest_dist2){
                    //                        closest_dist2=distance;
                    //                        best_i = i;}
                    // if distance is small
                    if( distance < search_distance_threshold &&
                       distance < closest_dist && ratio>0.7 && ratio<1.45 && ballsBox[i].area()<area_threshold_high && ballsBox[i].area()>area_threshold_low)
                    {
                        closest_dist      = distance;
                        closest_area_diff =  area_diff;
                        best_i = i;
                        ball_found = true;
                    }
                }
                //                cout<<"ballsBox[i].area()"<<ballsBox[best_i].area()<<endl;
                //                cout<<"Ratio"<<(float) ballsBox[best_i].width / (float) ballsBox[best_i].height<<endl;
                int best_radius;
                if(ball_found)
                {
                    // reset mp.pt
                    cout<<"here! yello"<<endl;
                    
                    int search_distance_threshold = 80*80;
                    int closest_dist = 2000;
                    int best_circle_i = 0;
                    bool circle_found = false;
                    for( size_t circle_i = 0; circle_i < circles.size(); circle_i++ )
                    {
                        int radius = cvRound(circles[circle_i][2]);
                        int diff_x = prev_ball_centers_circle[circle_i].x - mp.pt.x;
                        int diff_y = prev_ball_centers_circle[circle_i].y - mp.pt.y;
                        int distance  = diff_x * diff_x + diff_y * diff_y;
                        if( distance < search_distance_threshold && radius>8 && radius<13)
                        {
                            closest_dist      = distance;
                            best_circle_i = circle_i;
                            circle_found = true;
                            cout<<"radius"<<radius<<endl;
                            best_radius = radius;
                        }
                    }
                    if(circle_found){
                        cv::circle( result, cur_ball_centers_circle[best_circle_i], best_radius, CV_RGB(255,255,0), 2 );
                        mp.pt = Point2f(cur_ball_centers_circle[best_circle_i].x, cur_ball_centers_circle[best_circle_i].y);
                        cout<<"status 4"<<endl;
                    } else{
                        cv::rectangle(result, ballsBox[best_i], CV_RGB(255,255,0), 2);
                        Point motion = cur_ball_centers[best_i] - prev_ball_centers[best_i];
                        mp.pt = Point2f(cur_ball_centers[best_i].x, cur_ball_centers[best_i].y);
                        lastMotion = motion;
                        cout<<"status 5"<<endl;
                    }
                    
                }
                else
                {
                    // if ball still not found... stay at the same direction
                    circle(result, mp.pt, 5, CV_RGB(255,255,255), 2);
                    int search_distance_threshold, closest_dist,best_i,radius_threshold_low, radius_threshold_high, ball_found;
                    if(cur_status_7>1){
                        search_distance_threshold = 200*200;
                        closest_dist      = 55000;
                        best_i = 0;
                        radius_threshold_low=4;
                        radius_threshold_high=16;
                        ball_found = false;}
                    else{
                        search_distance_threshold = 80*80;
                        closest_dist      = 6000;
                        best_i = 0;
                        radius_threshold_low=7;
                        radius_threshold_high=13;
                        ball_found = false;
                    }
                    int best_radius;
                    for( size_t circle_i = 0; circle_i < circles.size(); circle_i++ )
                    {
                        int radius = cvRound(circles[circle_i][2]);
                        int diff_x = prev_ball_centers_circle[circle_i].x - mp.pt.x;
                        int diff_y = prev_ball_centers_circle[circle_i].y - mp.pt.y;
                        int distance  = diff_x * diff_x + diff_y * diff_y;
                        if( distance < search_distance_threshold && radius>radius_threshold_low && radius<radius_threshold_high)
                        {
                            closest_dist      = distance;
                            best_i = circle_i;
                            ball_found = true;
                            best_radius =radius;
                            cout<<"radius"<<radius<<endl;
                            cout<<mp.pt<<endl;
                        }
                    }
                    if(ball_found){
                        cv::circle( result, cur_ball_centers_circle[best_i], best_radius, CV_RGB(255,255,0), 2 );
                        Point motion = cur_ball_centers_circle[best_i] - prev_ball_centers_circle[best_i];
                        mp.pt = Point2f(cur_ball_centers_circle[best_i].x, cur_ball_centers_circle[best_i].y);
                        lastMotion = motion;
                        cout<<mp.pt<<endl;
                        cout<<motion<<endl;
                        cout<<"status 6"<<endl;
                    }else{
                        //                        mp.pt = lastBallCenter + lastMotion;
                        cout<<"status 7"<<endl;
                        cout<<"lastBallCenter"<<lastBallCenter<<endl;
                    }
                    //                          mp.pt = Point2f(mp.pt.x+lastMotion.x, mp.pt.y+lastMotion.y);
                    pre_status_7+=1;
                }
            }
            
            if(lastMotion.x*lastMotion.x+lastMotion.y*lastMotion.y>1200){
                cout<<"HIGH SPEED"<<endl;
                cout<<"HIGH SPEED"<<endl;
                cout<<"HIGH SPEED"<<endl;
                cout<<"MP before"<<mp.pt<<endl;
                int search_distance_threshold = 200*200;
                int closest_dist = 55000;
                int best_circle_i = 0;
                int best_i=0;
                bool ball_found = false;
                for (size_t i = 0; i < balls.size(); i++)
                {
                    int diff_x = prev_ball_centers[i].x - mp.pt.x;
                    int diff_y = prev_ball_centers[i].y - mp.pt.y;
                    int area_threshold_high = 100*100;
                    int area_threshold_low = 10*10;
                    int distance  = diff_x * diff_x + diff_y * diff_y;
                    int area_diff = abs(ballsBox[i].area()-lastBallBox.area());
                    float ratio = (float) ballsBox[i].width / (float) ballsBox[i].height;
                    //                    if(distance<closest_dist2){
                    //                        closest_dist2=distance;
                    //                        best_i = i;}
                    // if distance is small
                    if( distance < search_distance_threshold &&
                       distance < closest_dist && ratio>0.7 && ratio<1.45 && ballsBox[i].area()<area_threshold_high && ballsBox[i].area()>area_threshold_low)
                    {
                        closest_dist    = distance;
                        best_i = i;
                        ball_found = true;
                    }
                }
                if(ball_found)
                {
                    cv::rectangle(result, ballsBox[best_i], CV_RGB(255,255,0), 2);
                    Point motion = cur_ball_centers[best_i] - prev_ball_centers[best_i];
                    mp.pt = Point2f(cur_ball_centers[best_i].x, cur_ball_centers[best_i].y);
                    lastMotion = motion;
                    cout<<"ball"<<endl;
                }
                
                circle(result, mp.pt, 5, CV_RGB(255,255,255), 2);
                int radius_threshold_low, radius_threshold_high;
                int best_radius;
                search_distance_threshold = 200*200;
                closest_dist      = 55000;
                best_i = 0;
                radius_threshold_low=5;
                radius_threshold_high=13;
                ball_found = false;
                
                for( size_t circle_i = 0; circle_i < circles.size(); circle_i++ )
                {
                    int radius = cvRound(circles[circle_i][2]);
                    int diff_x = prev_ball_centers_circle[circle_i].x - mp.pt.x;
                    int diff_y = prev_ball_centers_circle[circle_i].y - mp.pt.y;
                    int distance  = diff_x * diff_x + diff_y * diff_y;
                    if( distance < search_distance_threshold && radius>radius_threshold_low && radius<radius_threshold_high)
                    {
                        closest_dist      = distance;
                        best_i = circle_i;
                        ball_found = true;
                        best_radius = radius;
                    }
                }
                if(ball_found)
                {
                    //                    cv::circle( result, cur_ball_centers_circle[best_i], best_radius, Scalar(255,255,0), 2 );
                    Point motion = cur_ball_centers_circle[best_i] - prev_ball_centers_circle[best_i];
                    mp.pt = Point2f(cur_ball_centers_circle[best_i].x, cur_ball_centers_circle[best_i].y);
                    lastMotion = motion;
                    cout<<"circle"<<endl;
                }
                cout<<"MP after"<<mp.pt<<endl;
                
            }
            
            for( size_t circle_i = 0; circle_i < circles.size(); circle_i++ )
            {
                
                
                Point center2(cvRound(circles[circle_i][0]), cvRound(circles[circle_i][1]));
                double dis_center =  sqrt(pow(center2.x-mp.pt.x,2)+pow(center2.y-mp.pt.y,2));
                int radius = cvRound(circles[circle_i][2]);
                if(dis_center<200)
                    continue;
                cv::circle( result, center2, radius, Scalar(12,12,255), 2 );
                
            }
            
            if(mp.pt.x<1)
                mp.pt.x=1;
            if(mp.pt.x>1279)
                mp.pt.x=1279;
            if(mp.pt.y<1)
                mp.pt.y=1;
            if(mp.pt.y>719)
                mp.pt.y=719;
            if(pre_status_7==cur_status_7)
                pre_status_7=0;
            imshow("Result Window", result);
            
            /* UPDATE FRAME */
            cur_frame.copyTo( prev_frame );
            
            /* KEY INPUTS */
            int keynum = waitKey(30) & 0xFF;
            if(keynum == 113)      // press q
                break;
            else if(keynum == 32)  // press space
            {
                keynum = 0;
                while(keynum != 32 && keynum != 113)
                    keynum = waitKey(30) & 0xFF;
                if(keynum == 113)
                    break;
            }
        }
        inputVideo.release();
        outputVideo.release();
    }
Esempio n. 20
0
int main(int argc, const char **argv)
{

    VideoCapture cap;
    Tracker objTracker;

    CommandLineParser parser(argc, argv, keys);
    if (parser.has("help")) {
        help();
        return 0;
    }

    cap.open(argv[1]);
    if (!cap.isOpened()) {
        help();
        cout << "***Could not access file...***\n";
        return -1;
    }
    Size S = Size((int) cap.get(CV_CAP_PROP_FRAME_WIDTH),    //Acquire input size
                  (int) cap.get(CV_CAP_PROP_FRAME_HEIGHT));

    cout << hot_keys;
    bool paused = false;

    Mat frame;
    cap >> frame;

    objTracker.Init(S, Tracker::InitParams());

    int ex = static_cast<int>(cap.get(CV_CAP_PROP_FOURCC));
    VideoWriter outputVideo;
    // outputVideo.open("output.mp4" , ex, cap.get(CV_CAP_PROP_FPS), S, true);

    Mat out;
    try {

        while (1) {

            if (!paused && Tracker::g_initTracking) {
                cap >> frame;
                if (frame.empty())
                    break;
            }

            if (!paused) {


                objTracker.ProcessFrame(frame, out);

            }
            imshow("CamShift", out);
            // outputVideo << out;

            char c = (char)waitKey(10);
            if (c == 27)
                break;
            switch (c) {
            case 'b':
                objTracker.ToggleShowBackproject();
                break;
            case 'c':
                // trackObject = 0;
                // histimg = Scalar::all(0);
                break;
            case 'h':
                objTracker.HideControlsGUI();
            //     showHist = !showHist;    
            //     if (!showHist)
            //         destroyWindow("Histogram");
            //     else
            //         namedWindow("Histogram", 1);
            //     break;
            case 'p':
                paused = !paused;
                break;
            case 'r':
                cap.set(CV_CAP_PROP_POS_AVI_RATIO, 0);
                // outputVideo.set(CV_CAP_PROP_POS_AVI_RATIO, 0);
                cap >> frame;
                objTracker.Init(S, Tracker::InitParams());

                break;
            default:
                ;
            }
        }
    }

    catch (const cv::Exception &e) {
        std::cerr << e.what();
        cap.release();
        outputVideo.release();

        return 1;
    }
    cap.release();
    outputVideo.release();

    return 0;
}
Esempio n. 21
0
int main(int argc, char** argv)
{
	// variable initialization
	int keyInput = 0;
	int nFrames = 0, nSmoothFrames = 0, nFailedFrames = 0, nBlindFrames = 0;
	int lastDx = 0, lastDy = 0;
	
	bool bOverlay = true;			// plot overlay?
	bool bTrace = true & bOverlay;	// plot 'bubble' trace? (only when overlay active)
	
	Ptr<BackgroundSubtractor> pMOG2;

	VideoCapture capture;		// input video capture
	VideoWriter outputVideo;	// output video writer

	Mat curFrame,		// current original frame
		fgMaskMOG2,		// foreground mask from MOG2 algorithm
		bgImg,			// container for background image from MOG2
		grayFrame,		// grayscale conversion of original frame
		frameDil,		// dilated grayscale frame
		canny_out;		// output of Canny algorithm for shape outline detection

	Mat *pOutMat = &curFrame;	// pointer to image that will be rendered once per input video frame
	Mat strucElem = getStructuringElement(MORPH_RECT, Size(3, 3)); // dilatation base element

	// containers for output of findContours()
	vector<Mat> contours;
	vector<Vec4i> hierarchy;
	
	// read video input filename from command line and construct output filename
	if (argc < 2) {
		cerr << "Please provide input video filename." << endl;
		return EXIT_FAILURE;
	}
	string filename(argv[1]);
	string outName = filename.substr(0, filename.length() - 4) + "_out.avi";

	Rect lastKnownRect, lastRect;
	Point lastKnownPos, lastPos, estimatePos, plotPos;
	list<Point> lastKnownPositions;

	// init 'live' video output window
	namedWindow("Motion tracking");

	// try to open input file
	capture.open(filename);
	if (!capture.isOpened()) {
		cerr << "Unable to open file '" << filename << "'." << endl;
		return EXIT_FAILURE;
	} else	{
		cout << "Successfully opened file '" << filename << "'." << endl;
	}

	// try to write to output file
	Size vidS = Size((int)capture.get(CV_CAP_PROP_FRAME_WIDTH), (int)capture.get(CV_CAP_PROP_FRAME_HEIGHT));
	outputVideo.open(outName, CV_FOURCC('P','I','M','1'), capture.get(CV_CAP_PROP_FPS), vidS, true);
	if (!outputVideo.isOpened()) {
		cerr << "Unable to write to output video." << endl;
		return EXIT_FAILURE;
	}

	// build frame buffer and background subtractor
	pMOG2 = createBackgroundSubtractorMOG2(500, 30., true);
	
	// main loop over frames
	while (capture.read(curFrame) && (char)keyInput != 'q')
	{
		++nFrames;
		
		cvtColor(curFrame, grayFrame, CV_BGR2GRAY);	// convert to grayscale
		threshold(grayFrame, grayFrame, 128., 0., CV_THRESH_TRUNC); // try to mitigate (white) reflections by truncating the current frame
		GaussianBlur(grayFrame, grayFrame, Size(7, 7), 0, 0);

		pMOG2->apply(grayFrame, fgMaskMOG2);
		
		// erode and dilate to remove some noise
		erode(fgMaskMOG2, frameDil, strucElem);
		dilate(frameDil, frameDil, strucElem);

		// dilate and erode to remove holes from foreground
		dilate(frameDil, frameDil, strucElem);
		erode(frameDil, frameDil, strucElem);

		// canny to find foreground outlines
		Canny(frameDil, canny_out, 100, 200, 3);

		// find contours, sort by contour size (descending)
		findContours(canny_out, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); // find contours
		sort(contours.begin(), contours.end(), rvs_cmp_contour_area); // sort by contour area, beginning with the largest

		// determine largest "moving" object
		int iMaxSize = 0;
		bool bFoundCloseContour = false;
		for (unsigned int i = 0; i < contours.size(); i++)
		{
			if (contourArea(contours[i]) < CONTOUR_AREA_THRESH) // ignore contours which are too small (noise)
				break;

			// ignore contours which are too far away from the last frame
			Rect boun = boundingRect(contours[i]); // bounding rect
			Point bounCenter = (boun.tl() + boun.br())/2;

			if (i == 0) // preemptively save largest contour to get back to if no "close" contour is found.
			{
				lastRect = boun;
				lastPos = bounCenter;
			}

			// distance validity check, but only if we recently had track of the object
			if (nFrames > 1 && nFailedFrames < 10)
			{
				int dx = bounCenter.x - lastPos.x;
				int dy = bounCenter.y - lastPos.y;
				int dist2 = dx*dx + dy*dy;
				//cout << bounCenter << " " << lastPos << endl;
				if (dist2 > DELTA_SQ_THRESH) // too far away... try next contour
					continue;
			}

			lastRect = boun;
			lastPos = bounCenter;
			bFoundCloseContour = true;
			++nSmoothFrames;
			break;
		}

		if (contours.size() == 0) {
			// we don't see anything.
			++nBlindFrames;
		} else { nBlindFrames = 0; }

		// update last known position if smooth transition occured
		if (bFoundCloseContour) {
			nFailedFrames = 0;
			lastDx = lastPos.x - lastKnownPos.x;
			lastDy = lastPos.y - lastKnownPos.y;

			lastKnownRect = lastRect;
			lastKnownPos = lastPos;

			plotPos = lastKnownPos;

			if (bTrace) { // draw trace
				if (lastKnownPositions.size() > LAST_POS_BUFFER_SIZE)
					lastKnownPositions.pop_front();
				lastKnownPositions.push_back(lastPos);
				
				list<Point>::iterator it;
				int i = 0;
				for (it = lastKnownPositions.begin(); it != lastKnownPositions.end(); it++)	{
					Scalar color(180, 90, 30);
					circle(*pOutMat, *it, 5, color, 2 * i);
					++i;
				}
			}
		} else {
			++nFailedFrames;
			// guess based on velocity extrapolation
			estimatePos.x = lastKnownPos.x + nFailedFrames*lastDx;
			estimatePos.y = lastKnownPos.y + nFailedFrames*lastDy;

			if (estimatePos.x < 0 || estimatePos.y < 0 || estimatePos.x >= capture.get(CV_CAP_PROP_FRAME_WIDTH) ||
				estimatePos.y >= capture.get(CV_CAP_PROP_FRAME_HEIGHT || nFailedFrames >= 10)) {
				// we've totally lost track, cancel velocity extrapolation guess
				plotPos = lastKnownPos;
				nFailedFrames = 0;
			} else {
				plotPos = estimatePos;
			}
		}

		// draw overlay (rect frame, mid point and text)
		if (bOverlay) {
			if (nBlindFrames < 6 && bFoundCloseContour) {
				circle(*pOutMat, plotPos, 5, Scalar(255, 120, 0), 10, 8);
				rectangle(*pOutMat, lastKnownRect, Scalar(0, 255, 0), 3);
			}

			vector<ostringstream> text(4);
			const int lineSkip = 16;
			text[0] << "Frame: " << nFrames; // frame counter
			text[1] << "Object X: " << lastKnownPos.x; // moving object coordinates
			text[2] << "Object Y: " << lastKnownPos.y;
			text[3] << "Smooth rate: " << setprecision(3) << 100.0*nSmoothFrames / nFrames << "%"; // tracking percentage

			for (unsigned int line = 0; line < text.size(); line++) {
				putText(*pOutMat, text[line].str(), Point(10, 22 + line*lineSkip), CV_FONT_HERSHEY_PLAIN, 1., Scalar(180., 0., 0.));
			}
		}
		
		// cleanup temporary vectors (VS2013 stability issues)
		contours.clear();
		hierarchy.clear();

		outputVideo << *pOutMat; // add output video frame
		imshow("Motion tracking", *pOutMat); // draw frame
		keyInput = waitKey(5); // allow time for event loop
	}

	// release files
	outputVideo.release(); 
	capture.release();

	return EXIT_SUCCESS;
}