标签:c++ opencv source code motion sensing game ubuntu
Here is the source code of the project based on OpenCV anc C++.
Before you run this code on Linux, you should install the OpenCV library first.
#include<opencv/highgui.h> #include<opencv2/opencv.hpp> #include<string> #include<sstream> #include<stdlib.h> #include<time.h> #include<stdio.h> using namespace std; using namespace cv; // The length and width of window frame const int FRAME_LENGTH = 640, FRAME_WIDTH = 480; // The stating point of BALL const int BALL_START_X = 320, BALL_START_Y = 26; // the constant value of PI const double PI = acos(-1); // The speed of the ball double SPEED = 35; // The redius of the ball int RADIUS = 20; // the diagonal points of the board int recX1 = 225, recY1 = 460; int recX2 = 415, recY2 = 480; const int boardLength = recX2 - recX1; const int boardWidth = recY2 - recY1; // The initial min and max of HSV filter values int H_MIN = 0; int H_MAX = 256; int S_MIN = 0; int S_MAX = 256; int V_MIN = 0; int V_MAX = 256; // The maximum number of object to be detected const int MAX_NUM_OBJECT = 50; // Minimum and maximum area of object const int MIN_OBJECT_AREA = 20 * 20; const int MAX_OBJECT_AREA = FRAME_LENGTH * FRAME_WIDTH / 1.5; // Name of different windows const string originalImage = "Original Image"; const string hsvImage = "HSV Image"; const string thresholdImage = "Threshold image"; const string trackbarName = "Trackbars"; // The flag to control whether tracking object bool trackObject = true; // Scoreboard int scoreBoard = 0; // GameOver bool gameOver = false; // Select the game mode int choice = 0; // acceleration int acc = 0; // This function will be called when a trackbar position is changed void onTrackbar(int, void *){ } // Convert the integer to string string intToString(int); // Create trackbars void createTrackbars(); // Draw crosshair to locate the position of the target void drawObject(int ,int , Mat&); // Reduce noise void morphOps(Mat&); // Locate the position of the object void trackFilteredObject(int& ,int&, Mat, Mat&); // Depict the board void depictBoard(Mat, Point, Point); // Depict Generator to generate the ball void depictGenerator(Mat); // Limit the board in case of the board out of border void limitBoard(int&, int&, int); // Class of BALL class NewBall{ private: // The driction of the ball at the beginning double angle; // the moving vector of the ball for each frame int Vx, Vy; // the center point of the ball Point point; public: NewBall(); void reset(); // Movement the ball like baseball void baseballMoving(Point, Point); // Movement the ball like ping pong ball void pingpongMoving(Point, Point); // Depict the ball void depictBall(Mat); void accelerate(); }; NewBall::NewBall(){ // the center point of the ball point = Point(BALL_START_X, BALL_START_Y); // Initialize the random seed srand(time(NULL)); // The driction of the ball at the beginning // Filter the angle of the driection let it between PI/4 and PI/4*3 angle = (rand() % 51 + 25) / 100.0 * PI; // the moving vector of the ball for each frame Vx = (int)(cos(angle) * SPEED); Vy = (int)(sin(angle) * SPEED); } void NewBall::accelerate(){ Vx = (int)(cos(angle) * SPEED); Vy = (int)(sin(angle) * SPEED); } void NewBall::reset(){ // the center point of the ball point = Point(BALL_START_X, BALL_START_Y); // Initialize the random seed // The driction of the ball at the beginning angle = (rand() % 51 + 25) / 100.0 * PI; // the moving vector of the ball for each frame Vx = (int)(cos(angle) * SPEED); Vy = (int)(sin(angle) * SPEED); } // Depict the ball on the frame void NewBall::depictBall(Mat img){ int lineType = 8; circle(img, point, RADIUS, Scalar(0,0,255), CV_FILLED, lineType); } // Movement of the ball void NewBall::baseballMoving(Point a, Point b){ if(point.x - RADIUS < 0 || point.x + RADIUS > FRAME_LENGTH){ Vx = -Vx; } if(point.y + RADIUS > FRAME_WIDTH + 5){ // the ball will dispear and then appear in the original position gameOver = true; } if((point.y + RADIUS > FRAME_WIDTH - boardWidth - 10) && (point.x >= a.x - 12 && point.x <= b.x + 12)){ cout << a.x - 12<< " " << b.x + 12<< endl; scoreBoard++; if(scoreBoard == 5 && acc == 0){ SPEED += 5; }else if (scoreBoard == 10 && acc == 1){ SPEED += 5; }else if (scoreBoard == 15 && acc == 2){ SPEED += 5; }else if (scoreBoard == 20 && acc == 3){ SPEED += 5; } Vy = -Vy; } if(point.y - RADIUS < 0){ this->reset(); } point.x = point.x + Vx; point.y = point.y + Vy; } // Movement of the ball void NewBall::pingpongMoving(Point a, Point b){ if(point.x - RADIUS < 0 || point.x + RADIUS > FRAME_LENGTH){ Vx = -Vx; } if(point.y + RADIUS > FRAME_WIDTH + 5){ // the ball will dispear and then appear in the original position gameOver = true; } if((point.y + RADIUS > FRAME_WIDTH - boardWidth - 10) && (point.x >= a.x - 12 && point.x <= b.x + 12)){ cout << a.x - 12<< " " << b.x + 12<< endl; cout << Vx << " " << Vy << endl; scoreBoard++; if(scoreBoard == 5 && acc == 0){ SPEED += 5; this->accelerate(); }else if (scoreBoard == 10 && acc == 1){ SPEED += 5; this->accelerate(); }else if (scoreBoard == 15 && acc == 2){ SPEED += 5; this->accelerate(); acc++; }else if (scoreBoard == 20 & acc == 3){ SPEED += 5; this->accelerate(); acc++; } Vy = -Vy; } if(point.y - RADIUS < 0){ Vy = -Vy; } point.x = point.x + Vx; point.y = point.y + Vy; } int main(int argc, char*argv[]){ // two boolean variables to control the two functions, one is to track object and the other //reduce noise bool useMorphOps = true; //Matrix to store each frame from the webcam feed Mat cameraFeed; //Martrix storage for HSV image Mat HSV; //Matrix sotrage for binary threshold image Mat threshold; //x and y values for the current location of the object int x = 0, y = 0; //The position of the object on the last frame int lastX = 0, lastY = 0; //Create slider bars for HSV filtering createTrackbars(); //video capture object to acquire webcam feed VideoCapture cap(0); char name[] = "camera"; if(!cap.isOpened()){ cout << "Camera can not opened." << endl; return -1; } //Window of original image namedWindow(originalImage, WINDOW_AUTOSIZE); //Window of HSV image namedWindow(hsvImage, WINDOW_AUTOSIZE); //Window of threshold image namedWindow(thresholdImage, WINDOW_AUTOSIZE); // move windows to its proper location moveWindow(originalImage, 20, 20); moveWindow(hsvImage, 20, 600); moveWindow(thresholdImage, 700, 20); // flag to control the movement of the ball bool ballMoveFlag = 0; NewBall ball; while(1){ bool bSuccess = cap.read(cameraFeed); if(!bSuccess){ cout << "Can not read a frame from video stream" << endl; break; } //Convert the original image to HSV cvtColor(cameraFeed, HSV, COLOR_BGR2HSV); //Select a range of H,S,V properties and then it can filter the //specific color inRange(HSV, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX,S_MAX,V_MAX), threshold); //Reduce noise if(useMorphOps){ morphOps(threshold); } // press the button to go on the game if(waitKey(30) == 27){ // press the ESC button cout << "You exit the game" << endl; break; } if(waitKey(30) == 32){ // press the space button ballMoveFlag = 1; ball.reset(); gameOver = false; acc = 0; SPEED = 35; } if(waitKey(30) == 49){ choice = 1; } if(waitKey(30) == 50){ choice = 2; } //On the last frame keep the location of the frame lastX = x; lastY = y; //Parameters x and y record the current position of the objcet if(trackObject){ trackFilteredObject(x, y, threshold, cameraFeed); int diffX = x - lastX, diffY = y - lastY; //Control the movement of the rectangle and do not let it out of the boarder limitBoard(recX1, recX2, diffX); } // Depict the image of the board and the ball depictGenerator(cameraFeed); depictBoard(cameraFeed, Point(recX1, recY1), Point(recX2, recY2)); ball.depictBall(cameraFeed); putText(cameraFeed,"Your Score " + intToString(scoreBoard), Point(350,50),1,2,Scalar(0,255,255),2); if(ballMoveFlag == false){ putText(cameraFeed, "Press space bar to start", Point(30,400),2,1,Scalar(0,0,255),4); } if(choice != 1 && choice != 2){ putText(cameraFeed, "Press 1 to select baseball mode", Point(30,200),2,1,Scalar(0,0,255),4); putText(cameraFeed, "Press 2 to select pingpong mode", Point(30,300),2,1,Scalar(0,0,255),4); } if(ballMoveFlag == 1){ // Generate the ball //Move the center fo the circle to the next position if(choice == 1){ ball.baseballMoving(Point(recX1, recY1), Point(recX2, recY2)); }else if(choice == 2){ ball.pingpongMoving(Point(recX1, recY1), Point(recX2, recY2)); } if(gameOver == true){ choice = 0; ballMoveFlag = 0; scoreBoard = 0; } } //If the ball is out of boarder, GameOver if(gameOver == true && choice == 0 && ballMoveFlag == 0){ putText(cameraFeed, "GAME OVER", Point(30,100),2,1,Scalar(0,0,255),4); } imshow(originalImage, cameraFeed); imshow(hsvImage, HSV); imshow(thresholdImage, threshold); } return 0; } // Limit the board in case of the board out of border void limitBoard(int &recX1, int &recX2, int diffX){ if(recX1 + diffX < 0){ recX1 = 0; recX2 = boardLength; }else if(recX2 + diffX > FRAME_LENGTH){ recX2 = FRAME_LENGTH; recX1 = FRAME_LENGTH - boardLength; }else{ recX1 += diffX; recX2 += diffX; } } // Depict the generator void depictGenerator(Mat img){ int thickness = CV_FILLED; int lineType = 8; Point a(300,0); Point b(340,5); rectangle(img, a, b, Scalar(0,255,0), thickness, lineType); } void depictBoard(Mat img, Point a, Point b){ int thickness = CV_FILLED; int lineType = 8; rectangle(img, a, b, Scalar(255,0,0), thickness, lineType); } void createTrackbars(){ namedWindow(trackbarName, 0); moveWindow(trackbarName, 800, 500); createTrackbar("H_MIN", trackbarName, &H_MIN, H_MAX, onTrackbar); createTrackbar("H_MAX", trackbarName, &H_MAX, H_MAX, onTrackbar); createTrackbar("S_MIN", trackbarName, &S_MIN, S_MAX, onTrackbar); createTrackbar("S_MAX", trackbarName, &S_MAX, S_MAX, onTrackbar); createTrackbar("V_MIN", trackbarName, &V_MIN, V_MAX, onTrackbar); createTrackbar("V_MAX", trackbarName, &V_MAX, V_MAX, onTrackbar); } // Draw crosshair to locate the position of the target void drawObject(int x,int y, Mat &frame){ circle(frame,Point(x, y), 20, Scalar(255,0,0), 2); if(y - 25 > 0){ line(frame, Point(x, y), Point(x, y-25), Scalar(255,0,0), 2); }else{ line(frame, Point(x, y), Point(x, 0), Scalar(255,0,0), 2); } if(y + 25 < FRAME_WIDTH){ line(frame, Point(x,y), Point(x,y+25),Scalar(255,0,0), 2); }else{ line(frame, Point(x,y), Point(x,FRAME_WIDTH),Scalar(255,0,0), 2); } if(x - 25 > 0){ line(frame, Point(x,y), Point(x-25, y), Scalar(255,0,0), 2); }else{ line(frame, Point(x,y), Point(0, y), Scalar(255,0,0), 2); } if(x + 25 < FRAME_LENGTH){ line(frame, Point(x,y), Point(x+25,y), Scalar(255,0,0),2); }else{ line(frame,Point(x,y), Point(FRAME_LENGTH,y), Scalar(255,0,0),2); } putText(frame, intToString(x)+","+intToString(y), Point(x,y+30),1,1,Scalar(255,0,0),2); } // Locate the position of the object void trackFilteredObject(int& x,int& y, Mat threshold, Mat& cameraFeed){ Mat temp; threshold.copyTo(temp); // these two vectors needed for output of findContours vector< vector<Point> > contours; vector< Vec4i > hierarchy; // find contours of filtered image using openCV findContours function findContours(temp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); // use moments method to find our filtered object double refArea = 0; bool objectFound = false; if(hierarchy.size() > 0){ int numObjects = hierarchy.size(); // if number of objects greater than MAX_NUM_OBJECTS we have noisy filter if(numObjects < MAX_NUM_OBJECT){ for(int index = 0; index >= 0; index = hierarchy[index][0]){ Moments moment = moments((cv::Mat)contours[index]); double area = moment.m00; if(area > MIN_OBJECT_AREA && area < MAX_OBJECT_AREA && area > refArea){ x = moment.m10 / area; y = moment.m01 / area; objectFound = true; refArea = area; }else{ objectFound = false; } if(objectFound == true){ putText(cameraFeed, "Tracking Object", Point(0,50),2,1,Scalar(0,255,0),2); drawObject(x,y,cameraFeed); } } } else{ putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER", Point(0,50),1,2,Scalar(0,0,255),2); } } } // Convert the integer to string string intToString(int number){ std::stringstream ss; ss << number; return ss.str(); } void morphOps(Mat &thresh){ Mat erodeElement = getStructuringElement( MORPH_RECT, Size(3,3)); Mat dilateElement = getStructuringElement( MORPH_RECT, Size(8,8)); erode(thresh, thresh, erodeElement); erode(thresh, thresh, erodeElement); dilate(thresh, thresh, dilateElement); dilate(thresh, thresh, dilateElement); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
Motion sensing game (Ping Pong Game)
标签:c++ opencv source code motion sensing game ubuntu
原文地址:http://blog.csdn.net/worldmakewayfordream/article/details/46654423