Demo entry 6336745

ww

   

Submitted by anonymous on Dec 08, 2016 at 08:26
Language: C++. Code size: 12.2 kB.

#include "config.hpp"
#include "score_region_segmentation.hpp"
#include "bullet_hole_detection.hpp"
#include "scoring_of_shooting_target.hpp"


const int MAX_QUEUE_SIZE = 7; // default: 7(i.e., alpha is 0.5 second) max previous frame queue size
const int FRAME_GAP = 45; // default: 30(i.e., beta is 2 seconds). the number of pivot_frame and the current frame
const int DEFAULT_FPS = 15; // default: 15
const double DEFAULT_WIDTH = 640; // default frame width
const double DEFAULT_HEIGHT = 480; // default frame height
const string INPUT_VIDEO_FILE = "/home/shkim/Desktop/input.mpg";
const string OUTPUT_VIDEO_FILE_PREFIX = "/home/shkim/Desktop/output";
const string OUTPUT_VIDEO_FILE_EXTENSION = "mpg";
const bool IS_CAMERA_CAPTURE = true;
const bool IS_FRAME_FLIP = true; // default: true
const int DEVICE_NUM = 1; // 0: embeded or built-in camera, 1: external usb camera
const int IDX_READY = 0; // frame id when score base is ready.
const int SCORE_RING_NUMBER = 10; // normal(default): 10

Mat score_base;	// score base. each level represents each score.
vector<vector<Point> > score_base_contours;
bool score_base_ready = false;

Mat bullet_hole_gray; // point of impact
vector<vector<Point> > bullet_hole_contours; // points of contours. It may be multiple.
bool bullet_hole_detected = false;

string winname0 = "Main";

#ifdef INFO
string winname1 = "score_base";
string winname2 = "bullet_hole";
string winname3 = "pivot_frame";
#endif


std::string unique_name(const string& prefix, const string& extension)
{ // generate unique log name, depending on local time
  // example output: "prefix-2015-03-15-12-23-45.extension"

    time_t t = time(0);
    struct tm * now = localtime( & t );

    std::string time_name(80, '\0');
    strftime( &time_name[0], time_name.size(), "%Y-%m-%d-%H-%M-%S", now);

    std::ostringstream buffer;
    buffer << prefix << "-" << time_name.c_str();
    buffer << "." << extension; // add extension

    return buffer.str();
}

int main( int argc, char** argv )
{
	VideoCapture cap;
	VideoWriter videoout;

	double fps = DEFAULT_FPS;
	double height = 0.0;
	double width = 0.0;

	int frame_duration;

	string inputfile = INPUT_VIDEO_FILE;
	string outputfile =   unique_name(OUTPUT_VIDEO_FILE_PREFIX, OUTPUT_VIDEO_FILE_EXTENSION);

	if (IS_CAMERA_CAPTURE)
	{
		cout << "[INFO] start from video camera." << endl;
		cap.open(DEVICE_NUM);
	}
	else
	{
		cout << "[INFO] start from video file." << endl;
		cout << "[INFO] input video file: " << inputfile << endl;

		/**
		 * open video file.
		 */
		 cap.open(inputfile);
	}

	if ( !cap.isOpened() )  // if not success, exit program
	{
		cout << "[ERROR] cannot open the video capture." << endl;
		return -1;
	}

//	if (!cameraready)
//	{
//		fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
//	}

	height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the frames per seconds of the video
	width = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the frames per seconds of the video

	if (height < 0 || width < 0)
	{
		width = DEFAULT_WIDTH;
		height = DEFAULT_HEIGHT;
	}

	frame_duration = (int)1000.0/fps; // miliseconds
	cout << "[INFO] frame per seconds: " << fps << endl;
	cout << "[INFO] frame height: " << height << endl;
	cout << "[INFO] frame width: " << width << endl;
	cout << "[INFO] frame durations: " << frame_duration << " miliseconds" << endl;


	videoout.open(outputfile, CV_FOURCC('M', 'P', 'E', 'G'), fps, Size(width, height), true);  // CV_FOURCC_DEFAULT: linux only
	if (!videoout.isOpened())
	{
		cout << "[ERROR] cannot open the output video file: " << outputfile << endl;
		return -1;
	}
	else
	{
		cout << "[INFO] output video file: " << outputfile << endl;
	}



#ifdef DEBUG
	namedWindow(winname1, WINDOW_NORMAL);  moveWindow(winname1, 50, 50);
	namedWindow(winname2, WINDOW_NORMAL);  moveWindow(winname2, 50, 350);
	namedWindow(winname3, WINDOW_NORMAL);  moveWindow(winname3, 50, 650);
#endif

	/**
	 * crate window and set position.
	 */
	namedWindow(winname0, WINDOW_NORMAL);  moveWindow(winname0, 400, 50);


	/**
	 * generate suffix message.
	 */
#ifdef DEEP_DEBUG
	int frame_sequence_id = 1; // navie frame sequence id
#endif
	int idx = -1;
	ostringstream ss_fps, ss_id, ss_score_log, ss_score_log_sum, ss_wait;
	ss_fps << "fps: " << fps;

	std::queue<Mat> previous_frame_queue; // just previous frame of the current frame.
	Mat pivot_frame;    // the base frame for differece image with the current frame.
	int score = 0, score_sum = 0;

	ss_score_log << "score: ";

	bool bullet_hole_temp_detected = false;
	int frame_count = 0;

	/**
	 * read each frame from the video.
	 */
	while(1)
	{
		Mat frame;

		Mat score_base_temp;	// score base. each level represents each score.
		vector<vector<Point> > score_base_temp_contours;

		bool bSuccess = cap.read(frame); // read a new frame from video

		if (!bSuccess && idx == -1) //if not success, break loop
		{
			cout << "[ERROR] video read failed!!" << endl;

			/**
			 * wait until user presses a key.
			 */
			while(char choice=(char)waitKey())
			{
				if(choice=='q') {
					return 0;
				}
			}

		}

		/// flip frame if FRAME_FLIP is true..
		/// 0: vertical, 1: horizontal, -1: both axes

		if (IS_FRAME_FLIP)
		{
			flip(frame, frame, -1);
		}

		videoout << frame;

		/**
		 * segment score region.
		 */
		if(idx < IDX_READY)
		{
			imshow(winname0, frame);
		    score_base_temp = score_region_segmentation(frame, width, height, score_base_temp_contours);

#ifdef INFO
			imshow(winname1, score_base_temp);
#endif

		}
		else
		{
			idx++;
			bullet_hole_gray = bullet_hole_detection(frame, previous_frame_queue.front(), bullet_hole_temp_detected);

		}

		/**
		 * if temprary bullet hole is detected, just pass by the number of FRAME_GAP frames, and
		 * detect bullet hole again, i.e. there the number of FRAME_GAP gaps of two frames(frame, and old_frame).
		 */
		if(bullet_hole_temp_detected && frame_count == 0)
		{
			/// keep current frame for image difference processing
			previous_frame_queue.front().copyTo(pivot_frame);
			bullet_hole_detected = true;
#ifdef INFO
			imshow(winname3, pivot_frame);
#endif

		}

		if( bullet_hole_detected)
		{
			if(frame_count < FRAME_GAP)
			{

				frame_count++;
#ifdef DEEP_DEBUG
				cout << "\tframe gap count: " << frame_count << endl;
#endif
			}
			else
			{
#ifdef INFO
		cout << "[INFO] <-- bullet detection --> " << endl;
#endif
				/// detect bullet hole
				bullet_hole_gray = bullet_hole_detection(frame, pivot_frame, bullet_hole_detected);

#ifdef INFO
				imshow(winname2, bullet_hole_gray);
#endif

				score = scoring_of_shooting_target(score_base, bullet_hole_gray, bullet_hole_contours);
				if(score != 0)
				{
					score_sum = score_sum + score;
					ss_score_log << score << " ";

					ss_score_log_sum.str(""); ss_score_log_sum.clear();
					ss_score_log_sum << ss_score_log.str() << "[" << score_sum << "]" ;
				}
				/// reset
				bullet_hole_temp_detected = false;
				bullet_hole_detected = false;
				frame_count = 0;
			}
		}

#ifdef DEEP_DEBUG
		cout << "\tbullet temp-detection: " << bullet_hole_temp_detected << "," << bullet_hole_detected << " frame_count: " << frame_count << endl;
#endif


		/// keep current frame for image difference processing
//		frame.copyTo(previous_frame_queue);
		previous_frame_queue.push(frame.clone());

		if(previous_frame_queue.size() > MAX_QUEUE_SIZE)
		{
			previous_frame_queue.pop();
		}

		/**
		 * generate frame index message followed by suffix message.
		 */
		ss_id.str(""); ss_id.clear();
		ss_id << "frame id: " << idx;
		putText(frame, ss_fps.str(), Point(10,30), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 1);
		putText(frame, ss_id.str(), Point(10,60), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 1);
		putText(frame, ss_score_log_sum.str(), Point(10,90), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 1);

		/// menu info.
		putText(frame, "1: start, 2: reset, q: quit", Point(10, height - 30), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,255), 1);

#ifdef DEEP_DEBUG
		/// menu info.
		putText(frame, "1: start, 2: reset, q: quit, n: next frame", Point(10, height - 30), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,255), 1);
#endif


		/// draw score rings temporarily.
		for( size_t i = 0; i< score_base_temp_contours.size(); i++ )
		{
			Scalar color = Scalar(0, 128, 255);
			drawContours( frame, score_base_temp_contours, (int)i, color, 1, 8, noArray(), 0, Point() );
		}

#ifdef INFO
		if (idx < IDX_READY)
		{
			cout << "[INFO] # of score rings: " << score_base_temp_contours.size() << endl;
		}
#endif

		/// if shooting ready...
		if (score_base_temp_contours.size() == SCORE_RING_NUMBER)
		{
			score_base_ready = true;

			score_base_temp.copyTo(score_base);

			score_base_contours.clear();
			score_base_contours  = score_base_temp_contours;
			score_base_temp_contours.clear();
		}

		/// when shooting ready, show message continously.
		if(score_base_ready)
		{

			for( size_t i = 0; i< score_base_contours.size(); i++ )
			{
				Scalar color = Scalar(0, 255, 0);
				drawContours( frame, score_base_contours, (int)i, color, 1, 8, noArray(), 0, Point() );
			}

			if(idx < IDX_READY)
			{
				putText(frame, "ready...start", Point( (width / 2) - 120,30), FONT_HERSHEY_SIMPLEX, 1, Scalar(0,255,0), 2);
			}
			else if(idx >= IDX_READY && !bullet_hole_detected)
			{
				putText(frame, "shoot!", Point( (width / 2) - 70,30), FONT_HERSHEY_SIMPLEX, 1, Scalar(0,255,0), 2);
			}
			else
			{
				ss_wait << "wait...(" << frame_count << "/" <<  FRAME_GAP << ")";
				putText(frame, ss_wait.str(), Point( (width / 2) - 120,30), FONT_HERSHEY_SIMPLEX, 1, Scalar(0,128,255), 2);
				ss_wait.str(""); ss_wait.clear();
			}

		}

		/// draw bullet hole.
		for( size_t i = 0; i< bullet_hole_contours.size(); i++ )
		{
			Scalar color = Scalar(0, 0, 255);
			drawContours( frame, bullet_hole_contours, (int)i, color, 1, 8, noArray(), 0, Point() );
		}

		/**
		 * show the frame in "MyVideo" window
		 */
		imshow(winname0, frame);

		/// 1: start, 2: reset, q: quit
		if(char choice=(char)waitKey(frame_duration))
		{
			if(choice=='1') // score region segmentation ok!
			{
				idx = IDX_READY;
				score_sum = 0;

#ifdef INFO
				imshow(winname1, score_base);
#endif
			}
			else if(choice=='2')
			{
				score_base_ready = false;
				idx = -1;
				ss_id.str(""); ss_id.clear();
				ss_score_log.str(""); ss_score_log.clear();
				ss_score_log_sum.str(""); ss_score_log_sum.clear();
				ss_score_log << "score: ";

				bullet_hole_temp_detected = false;
				bullet_hole_detected = false;
				frame_count = 0;

				bullet_hole_contours.clear();

				while (!previous_frame_queue.empty())
				{
					previous_frame_queue.pop();
				}

			}
			else if(choice=='q')
			{
				cap.release();
				videoout.release();
				return 0;
			}
		}
#ifdef DEEP_DEBUG


		/// print naive frame sequence id
		cout << "[DEEP_DEBUG] frame sequence id: " << frame_sequence_id++ << endl;

		/**
		 * wait until user presses a key.
		 */
		/// 1: start, 2: reset, q: quit
		while(char choice=(char)waitKey())
		{
			if(choice=='1') // score region segmentation ok!
			{
				idx = IDX_READY;
				score_sum = 0;
				break;
			}
			else if(choice=='n' || choice == 32) // 32: space
			{
				break;
			}
			else if(choice=='2')
			{
				score_base_ready = false;
				idx = -1;
				ss_id.str(""); ss_id.clear();
				ss_score_log.str(""); ss_score_log.clear();
				ss_score_log_sum.str(""); ss_score_log_sum.clear();
				ss_score_log << "score: ";

				bullet_hole_temp_detected = false;
				bullet_hole_detected = false;
				frame_count = 0;

				bullet_hole_contours.clear();

				while (!previous_frame_queue.empty())
				{
					previous_frame_queue.pop();
				}

			}
			else if(choice=='q')
			{
				cap.release();
				videoout.release();
				return 0;
			}
		}
#endif


	}

	return 0;

}

This snippet took 0.03 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).