├── LICENSE ├── README.md ├── auto-colour-filter └── AutoColourFilter.cpp ├── diy-security-cam ├── final-code │ └── surveillanceCam.cpp └── surveillanceCam.cpp ├── motion-tracking-tut ├── bouncingBall.avi ├── final-code │ └── motionTracking.cpp └── motionTracking.cpp ├── multiple-object-tracking-tut ├── fruits.jpg ├── part-one │ ├── Fruit.cpp │ ├── Fruit.h │ └── multipleObjectTracking.cpp ├── part-three │ ├── Fruit.cpp │ ├── Fruit.h │ └── multipleObjectTracking.cpp └── part-two │ └── multipleObjectTracking.cpp ├── object-tracking-tut └── objectTrackingTut.cpp └── video-writer-tut ├── final-code └── myVideoWriter.cpp ├── part-one └── myVideoWriter.cpp └── part-two └── myVideoWriter.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 kylehounslow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opencv-tuts 2 | -------------------------------------------------------------------------------- /auto-colour-filter/AutoColourFilter.cpp: -------------------------------------------------------------------------------- 1 | //objectTrackingTutorial.cpp 2 | 3 | //Written by Kyle Hounslow 2015 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software") 6 | //, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 14 | //IN THE SOFTWARE. 15 | 16 | #include 17 | #include 18 | #include 19 | #include "opencv\highgui.h" 20 | #include "opencv\cv.h" 21 | 22 | using namespace cv; 23 | using namespace std; 24 | //initial min and max HSV filter values. 25 | //these will be changed using trackbars 26 | int H_MIN = 0; 27 | int H_MAX = 256; 28 | int S_MIN = 0; 29 | int S_MAX = 256; 30 | int V_MIN = 0; 31 | int V_MAX = 256; 32 | //default capture width and height 33 | const int FRAME_WIDTH = 640; 34 | const int FRAME_HEIGHT = 480; 35 | //max number of objects to be detected in frame 36 | const int MAX_NUM_OBJECTS = 50; 37 | //minimum and maximum object area 38 | const int MIN_OBJECT_AREA = 20 * 20; 39 | const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH / 1.5; 40 | //names that will appear at the top of each window 41 | const string windowName = "Original Image"; 42 | const string windowName1 = "HSV Image"; 43 | const string windowName2 = "Thresholded Image"; 44 | const string windowName3 = "After Morphological Operations"; 45 | const string trackbarWindowName = "Trackbars"; 46 | 47 | bool calibrationMode;//used for showing debugging windows, trackbars etc. 48 | 49 | bool mouseIsDragging;//used for showing a rectangle on screen as user clicks and drags mouse 50 | bool mouseMove; 51 | bool rectangleSelected; 52 | cv::Point initialClickPoint, currentMousePoint; //keep track of initial point clicked and current position of mouse 53 | cv::Rect rectangleROI; //this is the ROI that the user has selected 54 | vector H_ROI, S_ROI, V_ROI;// HSV values from the click/drag ROI region stored in separate vectors so that we can sort them easily 55 | 56 | void on_trackbar(int, void*) 57 | {//This function gets called whenever a 58 | // trackbar position is changed 59 | 60 | //for now, this does nothing. 61 | 62 | 63 | 64 | } 65 | void createTrackbars(){ 66 | //create window for trackbars 67 | 68 | 69 | namedWindow(trackbarWindowName, 0); 70 | //create memory to store trackbar name on window 71 | char TrackbarName[50]; 72 | sprintf(TrackbarName, "H_MIN", H_MIN); 73 | sprintf(TrackbarName, "H_MAX", H_MAX); 74 | sprintf(TrackbarName, "S_MIN", S_MIN); 75 | sprintf(TrackbarName, "S_MAX", S_MAX); 76 | sprintf(TrackbarName, "V_MIN", V_MIN); 77 | sprintf(TrackbarName, "V_MAX", V_MAX); 78 | //create trackbars and insert them into window 79 | //3 parameters are: the address of the variable that is changing when the trackbar is moved(eg.H_LOW), 80 | //the max value the trackbar can move (eg. H_HIGH), 81 | //and the function that is called whenever the trackbar is moved(eg. on_trackbar) 82 | // ----> ----> ----> 83 | createTrackbar("H_MIN", trackbarWindowName, &H_MIN, 255, on_trackbar); 84 | createTrackbar("H_MAX", trackbarWindowName, &H_MAX, 255, on_trackbar); 85 | createTrackbar("S_MIN", trackbarWindowName, &S_MIN, 255, on_trackbar); 86 | createTrackbar("S_MAX", trackbarWindowName, &S_MAX, 255, on_trackbar); 87 | createTrackbar("V_MIN", trackbarWindowName, &V_MIN, 255, on_trackbar); 88 | createTrackbar("V_MAX", trackbarWindowName, &V_MAX, 255, on_trackbar); 89 | 90 | 91 | } 92 | void clickAndDrag_Rectangle(int event, int x, int y, int flags, void* param){ 93 | //only if calibration mode is true will we use the mouse to change HSV values 94 | if (calibrationMode == true){ 95 | //get handle to video feed passed in as "param" and cast as Mat pointer 96 | Mat* videoFeed = (Mat*)param; 97 | 98 | if (event == CV_EVENT_LBUTTONDOWN && mouseIsDragging == false) 99 | { 100 | //keep track of initial point clicked 101 | initialClickPoint = cv::Point(x, y); 102 | //user has begun dragging the mouse 103 | mouseIsDragging = true; 104 | } 105 | /* user is dragging the mouse */ 106 | if (event == CV_EVENT_MOUSEMOVE && mouseIsDragging == true) 107 | { 108 | //keep track of current mouse point 109 | currentMousePoint = cv::Point(x, y); 110 | //user has moved the mouse while clicking and dragging 111 | mouseMove = true; 112 | } 113 | /* user has released left button */ 114 | if (event == CV_EVENT_LBUTTONUP && mouseIsDragging == true) 115 | { 116 | //set rectangle ROI to the rectangle that the user has selected 117 | rectangleROI = Rect(initialClickPoint, currentMousePoint); 118 | 119 | //reset boolean variables 120 | mouseIsDragging = false; 121 | mouseMove = false; 122 | rectangleSelected = true; 123 | } 124 | 125 | if (event == CV_EVENT_RBUTTONDOWN){ 126 | //user has clicked right mouse button 127 | //Reset HSV Values 128 | H_MIN = 0; 129 | S_MIN = 0; 130 | V_MIN = 0; 131 | H_MAX = 255; 132 | S_MAX = 255; 133 | V_MAX = 255; 134 | 135 | } 136 | if (event == CV_EVENT_MBUTTONDOWN){ 137 | 138 | //user has clicked middle mouse button 139 | //enter code here if needed. 140 | } 141 | } 142 | 143 | } 144 | void recordHSV_Values(cv::Mat frame, cv::Mat hsv_frame){ 145 | 146 | //save HSV values for ROI that user selected to a vector 147 | if (mouseMove == false && rectangleSelected == true){ 148 | 149 | //clear previous vector values 150 | if (H_ROI.size()>0) H_ROI.clear(); 151 | if (S_ROI.size()>0) S_ROI.clear(); 152 | if (V_ROI.size()>0 )V_ROI.clear(); 153 | //if the rectangle has no width or height (user has only dragged a line) then we don't try to iterate over the width or height 154 | if (rectangleROI.width<1 || rectangleROI.height<1) cout << "Please drag a rectangle, not a line" << endl; 155 | else{ 156 | for (int i = rectangleROI.x; i(j, i)[0]); 161 | S_ROI.push_back((int)hsv_frame.at(j, i)[1]); 162 | V_ROI.push_back((int)hsv_frame.at(j, i)[2]); 163 | } 164 | } 165 | } 166 | //reset rectangleSelected so user can select another region if necessary 167 | rectangleSelected = false; 168 | //set min and max HSV values from min and max elements of each array 169 | 170 | if (H_ROI.size()>0){ 171 | //NOTE: min_element and max_element return iterators so we must dereference them with "*" 172 | H_MIN = *std::min_element(H_ROI.begin(), H_ROI.end()); 173 | H_MAX = *std::max_element(H_ROI.begin(), H_ROI.end()); 174 | cout << "MIN 'H' VALUE: " << H_MIN << endl; 175 | cout << "MAX 'H' VALUE: " << H_MAX << endl; 176 | } 177 | if (S_ROI.size()>0){ 178 | S_MIN = *std::min_element(S_ROI.begin(), S_ROI.end()); 179 | S_MAX = *std::max_element(S_ROI.begin(), S_ROI.end()); 180 | cout << "MIN 'S' VALUE: " << S_MIN << endl; 181 | cout << "MAX 'S' VALUE: " << S_MAX << endl; 182 | } 183 | if (V_ROI.size()>0){ 184 | V_MIN = *std::min_element(V_ROI.begin(), V_ROI.end()); 185 | V_MAX = *std::max_element(V_ROI.begin(), V_ROI.end()); 186 | cout << "MIN 'V' VALUE: " << V_MIN << endl; 187 | cout << "MAX 'V' VALUE: " << V_MAX << endl; 188 | } 189 | 190 | } 191 | 192 | if (mouseMove == true){ 193 | //if the mouse is held down, we will draw the click and dragged rectangle to the screen 194 | rectangle(frame, initialClickPoint, cv::Point(currentMousePoint.x, currentMousePoint.y), cv::Scalar(0, 255, 0), 1, 8, 0); 195 | } 196 | 197 | 198 | } 199 | string intToString(int number){ 200 | 201 | 202 | std::stringstream ss; 203 | ss << number; 204 | return ss.str(); 205 | } 206 | void drawObject(int x, int y, Mat &frame){ 207 | 208 | //use some of the openCV drawing functions to draw crosshairs 209 | //on your tracked image! 210 | 211 | 212 | //'if' and 'else' statements to prevent 213 | //memory errors from writing off the screen (ie. (-25,-25) is not within the window) 214 | 215 | circle(frame, Point(x, y), 20, Scalar(0, 255, 0), 2); 216 | if (y - 25>0) 217 | line(frame, Point(x, y), Point(x, y - 25), Scalar(0, 255, 0), 2); 218 | else line(frame, Point(x, y), Point(x, 0), Scalar(0, 255, 0), 2); 219 | if (y + 250) 223 | line(frame, Point(x, y), Point(x - 25, y), Scalar(0, 255, 0), 2); 224 | else line(frame, Point(x, y), Point(0, y), Scalar(0, 255, 0), 2); 225 | if (x + 25 > contours; 257 | vector hierarchy; 258 | //find contours of filtered image using openCV findContours function 259 | findContours(temp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); 260 | //use moments method to find our filtered object 261 | double refArea = 0; 262 | int largestIndex = 0; 263 | bool objectFound = false; 264 | if (hierarchy.size() > 0) { 265 | int numObjects = hierarchy.size(); 266 | //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter 267 | if (numObjects= 0; index = hierarchy[index][0]) { 269 | 270 | Moments moment = moments((cv::Mat)contours[index]); 271 | double area = moment.m00; 272 | 273 | //if the area is less than 20 px by 20px then it is probably just noise 274 | //if the area is the same as the 3/2 of the image size, probably just a bad filter 275 | //we only want the object with the largest area so we save a reference area each 276 | //iteration and compare it to the area in the next iteration. 277 | if (area>MIN_OBJECT_AREA && arearefArea){ 278 | x = moment.m10 / area; 279 | y = moment.m01 / area; 280 | objectFound = true; 281 | refArea = area; 282 | //save index of largest contour to use with drawContours 283 | largestIndex = index; 284 | } 285 | else objectFound = false; 286 | 287 | 288 | } 289 | //let user know you found an object 290 | if (objectFound == true){ 291 | putText(cameraFeed, "Tracking Object", Point(0, 50), 2, 1, Scalar(0, 255, 0), 2); 292 | //draw object location on screen 293 | drawObject(x, y, cameraFeed); 294 | //draw largest contour 295 | //drawContours(cameraFeed, contours, largestIndex, Scalar(0, 255, 255), 2); 296 | } 297 | 298 | } 299 | else putText(cameraFeed, "TOO MUCH NOISE! ADJUST FILTER", Point(0, 50), 1, 2, Scalar(0, 0, 255), 2); 300 | } 301 | } 302 | int main(int argc, char* argv[]) 303 | { 304 | //some boolean variables for different functionality within this 305 | //program 306 | bool trackObjects = true; 307 | bool useMorphOps = true; 308 | calibrationMode = true; 309 | //Matrix to store each frame of the webcam feed 310 | Mat cameraFeed; 311 | //matrix storage for HSV image 312 | Mat HSV; 313 | //matrix storage for binary threshold image 314 | Mat threshold; 315 | //x and y values for the location of the object 316 | int x = 0, y = 0; 317 | //video capture object to acquire webcam feed 318 | VideoCapture capture; 319 | //open capture object at location zero (default location for webcam) 320 | capture.open(0); 321 | //set height and width of capture frame 322 | capture.set(CV_CAP_PROP_FRAME_WIDTH, FRAME_WIDTH); 323 | capture.set(CV_CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT); 324 | //must create a window before setting mouse callback 325 | cv::namedWindow(windowName); 326 | //set mouse callback function to be active on "Webcam Feed" window 327 | //we pass the handle to our "frame" matrix so that we can draw a rectangle to it 328 | //as the user clicks and drags the mouse 329 | cv::setMouseCallback(windowName, clickAndDrag_Rectangle, &cameraFeed); 330 | //initiate mouse move and drag to false 331 | mouseIsDragging = false; 332 | mouseMove = false; 333 | rectangleSelected = false; 334 | 335 | //start an infinite loop where webcam feed is copied to cameraFeed matrix 336 | //all of our operations will be performed within this loop 337 | while (1){ 338 | //store image to matrix 339 | capture.read(cameraFeed); 340 | //convert frame from BGR to HSV colorspace 341 | cvtColor(cameraFeed, HSV, COLOR_BGR2HSV); 342 | //set HSV values from user selected region 343 | recordHSV_Values(cameraFeed, HSV); 344 | //filter HSV image between values and store filtered image to 345 | //threshold matrix 346 | inRange(HSV, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX, S_MAX, V_MAX), threshold); 347 | //perform morphological operations on thresholded image to eliminate noise 348 | //and emphasize the filtered object(s) 349 | if (useMorphOps) 350 | morphOps(threshold); 351 | //pass in thresholded frame to our object tracking function 352 | //this function will return the x and y coordinates of the 353 | //filtered object 354 | if (trackObjects) 355 | trackFilteredObject(x, y, threshold, cameraFeed); 356 | 357 | //show frames 358 | if (calibrationMode == true){ 359 | 360 | //create slider bars for HSV filtering 361 | createTrackbars(); 362 | imshow(windowName1, HSV); 363 | imshow(windowName2, threshold); 364 | } 365 | else{ 366 | 367 | destroyWindow(windowName1); 368 | destroyWindow(windowName2); 369 | destroyWindow(trackbarWindowName); 370 | } 371 | imshow(windowName, cameraFeed); 372 | 373 | 374 | 375 | //delay 30ms so that screen can refresh. 376 | //image will not appear without this waitKey() command 377 | //also use waitKey command to capture keyboard input 378 | if (waitKey(30) == 99) calibrationMode = !calibrationMode;//if user presses 'c', toggle calibration mode 379 | } 380 | 381 | 382 | 383 | 384 | 385 | 386 | return 0; 387 | } 388 | -------------------------------------------------------------------------------- /diy-security-cam/final-code/surveillanceCam.cpp: -------------------------------------------------------------------------------- 1 | //DIYsc.cpp 2 | 3 | //Written by Kyle Hounslow, March 2014 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software") 6 | //, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 14 | //IN THE SOFTWARE. 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | using namespace cv; 22 | 23 | //our sensitivity value to be used in the absdiff() function 24 | //for higher sensitivity, use a lower value 25 | const static int SENSITIVITY_VALUE = 40; 26 | //size of blur used to smooth the intensity image output from absdiff() function 27 | const static int BLUR_SIZE = 10; 28 | //these two can be toggled by pressing 'd' or 't' 29 | bool debugMode; 30 | bool trackingEnabled; 31 | 32 | //int to string helper function 33 | string intToString(int number){ 34 | 35 | //this function has a number input and string output 36 | std::stringstream ss; 37 | ss << number; 38 | return ss.str(); 39 | } 40 | 41 | string getDateTime(){ 42 | //get the system time 43 | SYSTEMTIME theTime; 44 | GetLocalTime(&theTime); 45 | //create string to store the date and time 46 | string dateTime; 47 | //convert year to string 48 | string year = intToString(theTime.wYear); 49 | //use stringstream to add a leading '0' to the month (ie. 3 -> 03) 50 | //we use 'setw(2)' so that we force the string 2 characters wide with a zero in front of it. 51 | //if the month is '10' then it will remain '10' 52 | std::stringstream m; 53 | m< > contours; 121 | vector hierarchy; 122 | //find contours of filtered image using openCV findContours function 123 | //findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );// retrieves all contours 124 | findContours(temp,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE );// retrieves external contours 125 | 126 | //if contours vector is not empty, we have found some objects 127 | //we can simply say that if the vector is not empty, motion in the video feed has been detected. 128 | if(contours.size()>0)motionDetected=true; 129 | else motionDetected = false; 130 | 131 | return motionDetected; 132 | 133 | } 134 | int main(){ 135 | //set recording and startNewRecording initially to false. 136 | bool recording = false; 137 | bool startNewRecording = false; 138 | int inc=0; 139 | bool firstRun = true; 140 | //if motion is detected in the video feed, we will know to start recording. 141 | bool motionDetected = false; 142 | 143 | //pause and resume code (if needed) 144 | bool pause = false; 145 | //set debug mode and trackingenabled initially to false 146 | //these can be toggled using 'd' and 't' 147 | debugMode = false; 148 | trackingEnabled = false; 149 | //set up the matrices that we will need 150 | //the two frames we will be comparing 151 | Mat frame1,frame2; 152 | //their grayscale images (needed for absdiff() function) 153 | Mat grayImage1,grayImage2; 154 | //resulting difference image 155 | Mat differenceImage; 156 | //thresholded difference image (for use in findContours() function) 157 | Mat thresholdImage; 158 | //video capture object. 159 | VideoCapture capture; 160 | capture.open(0); 161 | VideoWriter oVideoWriter;//create videoWriter object, not initialized yet 162 | double dWidth = capture.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video 163 | double dHeight = capture.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video 164 | 165 | cout << "Frame Size = " << dWidth << "x" << dHeight << endl; 166 | 167 | //set framesize for use with videoWriter 168 | Size frameSize(static_cast(dWidth), static_cast(dHeight)); 169 | 170 | if(!capture.isOpened()){ 171 | cout<<"ERROR ACQUIRING VIDEO FEED\n"; 172 | getchar(); 173 | return -1; 174 | } 175 | while(1){ 176 | 177 | if(startNewRecording==true){ 178 | 179 | oVideoWriter = VideoWriter("D:/MyVideo"+intToString(inc)+".avi", CV_FOURCC('D', 'I', 'V', '3'), 20, frameSize, true); //initialize the VideoWriter object 180 | recording = true; 181 | startNewRecording = false; 182 | cout<<"New video file created D:/MyVideo"+intToString(inc)+".avi "< 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | using namespace cv; 22 | 23 | //our sensitivity value to be used in the absdiff() function 24 | //for higher sensitivity, use a lower value 25 | const static int SENSITIVITY_VALUE = 40; 26 | //size of blur used to smooth the intensity image output from absdiff() function 27 | const static int BLUR_SIZE = 10; 28 | //these two can be toggled by pressing 'd' or 't' 29 | bool debugMode; 30 | bool trackingEnabled; 31 | 32 | //int to string helper function 33 | string intToString(int number){ 34 | 35 | //this function has a number input and string output 36 | std::stringstream ss; 37 | ss << number; 38 | return ss.str(); 39 | } 40 | 41 | 42 | string getDateTime(){ 43 | //get the system time 44 | SYSTEMTIME theTime; 45 | GetLocalTime(&theTime); 46 | //create string to store the date and time 47 | string dateTime; 48 | //convert year to string 49 | string year = intToString(theTime.wYear); 50 | //use stringstream to add a leading '0' to the month (ie. 3 -> 03) 51 | //we use 'setw(2)' so that we force the string 2 characters wide with a zero in front of it. 52 | //if the month is '10' then it will remain '10' 53 | std::stringstream m; 54 | m< > contours; 123 | vector hierarchy; 124 | //find contours of filtered image using openCV findContours function 125 | //findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );// retrieves all contours 126 | findContours(temp,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE );// retrieves external contours 127 | 128 | //if contours vector is not empty, we have found some objects 129 | //we can simply say that if the vector is not empty, motion in the video feed has been detected. 130 | if(contours.size()>0)motionDetected=true; 131 | else motionDetected = false; 132 | 133 | return motionDetected; 134 | 135 | } 136 | int main(){ 137 | //set recording and startNewRecording initially to false. 138 | bool recording = false; 139 | bool startNewRecording = false; 140 | int inc=0; 141 | bool firstRun = true; 142 | //if motion is detected in the video feed, we will know to start recording. 143 | bool motionDetected = false; 144 | 145 | //pause and resume code (if needed) 146 | bool pause = false; 147 | //set debug mode and trackingenabled initially to false 148 | //these can be toggled using 'd' and 't' 149 | debugMode = false; 150 | trackingEnabled = true; 151 | //set up the matrices that we will need 152 | //the two frames we will be comparing 153 | Mat frame1,frame2; 154 | //their grayscale images (needed for absdiff() function) 155 | Mat grayImage1,grayImage2; 156 | //resulting difference image 157 | Mat differenceImage; 158 | //thresholded difference image (for use in findContours() function) 159 | Mat thresholdImage; 160 | //video capture object. 161 | VideoCapture capture; 162 | capture.open(0); 163 | VideoWriter oVideoWriter;//create videoWriter object, not initialized yet 164 | double dWidth = capture.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video 165 | double dHeight = capture.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video 166 | //set framesize for use with videoWriter 167 | Size frameSize(static_cast(dWidth), static_cast(dHeight)); 168 | 169 | if(!capture.isOpened()){ 170 | cout<<"ERROR ACQUIRING VIDEO FEED\n"; 171 | getchar(); 172 | return -1; 173 | } 174 | while(1){ 175 | 176 | 177 | //read first frame 178 | capture.read(frame1); 179 | //convert frame1 to gray scale for frame differencing 180 | cv::cvtColor(frame1,grayImage1,COLOR_BGR2GRAY); 181 | //copy second frame 182 | capture.read(frame2); 183 | //convert frame2 to gray scale for frame differencing 184 | cv::cvtColor(frame2,grayImage2,COLOR_BGR2GRAY); 185 | //perform frame differencing with the sequential images. This will output an "intensity image" 186 | //do not confuse this with a threshold image, we will need to perform thresholding afterwards. 187 | cv::absdiff(grayImage1,grayImage2,differenceImage); 188 | //threshold intensity image at a given sensitivity value 189 | cv::threshold(differenceImage,thresholdImage,SENSITIVITY_VALUE,255,THRESH_BINARY); 190 | if(debugMode==true){ 191 | //show the difference image and threshold image 192 | cv::imshow("Difference Image",differenceImage); 193 | cv::imshow("Threshold Image", thresholdImage); 194 | }else{ 195 | //if not in debug mode, destroy the windows so we don't see them anymore 196 | cv::destroyWindow("Difference Image"); 197 | cv::destroyWindow("Threshold Image"); 198 | } 199 | //blur the image to get rid of the noise. This will output an intensity image 200 | cv::blur(thresholdImage,thresholdImage,cv::Size(BLUR_SIZE,BLUR_SIZE)); 201 | //threshold again to obtain binary image from blur output 202 | cv::threshold(thresholdImage,thresholdImage,SENSITIVITY_VALUE,255,THRESH_BINARY); 203 | if(debugMode==true){ 204 | //show the threshold image after it's been "blurred" 205 | 206 | imshow("Final Threshold Image",thresholdImage); 207 | 208 | } 209 | else { 210 | //if not in debug mode, destroy the windows so we don't see them anymore 211 | cv::destroyWindow("Final Threshold Image"); 212 | } 213 | 214 | //if tracking enabled, search for Motion 215 | if(trackingEnabled){ 216 | 217 | //check for motion in the video feed 218 | //the detectMotion function will return true if motion is detected, else it will return false. 219 | //set motionDetected boolean to the returned value. 220 | motionDetected = detectMotion(thresholdImage,frame1); 221 | 222 | }else{ 223 | //reset our variables if tracking is disabled 224 | motionDetected = false; 225 | 226 | } 227 | 228 | ////////////**STEP 1**////////////////////////////////////////////////////////////////////////////////////////////////////////////// 229 | //draw time stamp to video in bottom left corner. We draw it before we write so that it is written on the video file. 230 | 231 | 232 | //if we're in recording mode, write to file 233 | if(recording){ 234 | 235 | //check if it's our first time running the program so that we don't create a new video file over and over again. 236 | //we use the same boolean check to create a new recording if we want. 237 | if(firstRun == true || startNewRecording == true){ 238 | 239 | //////////**STEP 3**/////////////////////////////////////////////////////////////////////////////////////////////////////////////// 240 | //Create a unique filename for each video based on the date and time the recording has started 241 | string videoFileName = "D:/MyVideo"+intToString(inc)+".avi"; 242 | 243 | cout << "File has been opened for writing: " << videoFileName< 17 | #include 18 | 19 | using namespace std; 20 | using namespace cv; 21 | 22 | //our sensitivity value to be used in the absdiff() function 23 | const static int SENSITIVITY_VALUE = 20; 24 | //size of blur used to smooth the intensity image output from absdiff() function 25 | const static int BLUR_SIZE = 10; 26 | //we'll have just one object to search for 27 | //and keep track of its position. 28 | int theObject[2] = {0,0}; 29 | //bounding rectangle of the object, we will use the center of this as its position. 30 | Rect objectBoundingRectangle = Rect(0,0,0,0); 31 | 32 | 33 | //int to string helper function 34 | string intToString(int number){ 35 | 36 | //this function has a number input and string output 37 | std::stringstream ss; 38 | ss << number; 39 | return ss.str(); 40 | } 41 | 42 | void searchForMovement(Mat thresholdImage, Mat &cameraFeed){ 43 | //notice how we use the '&' operator for objectDetected and cameraFeed. This is because we wish 44 | //to take the values passed into the function and manipulate them, rather than just working with a copy. 45 | //eg. we draw to the cameraFeed to be displayed in the main() function. 46 | bool objectDetected = false; 47 | Mat temp; 48 | thresholdImage.copyTo(temp); 49 | //these two vectors needed for output of findContours 50 | vector< vector > contours; 51 | vector hierarchy; 52 | //find contours of filtered image using openCV findContours function 53 | //findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );// retrieves all contours 54 | findContours(temp,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE );// retrieves external contours 55 | 56 | //if contours vector is not empty, we have found some objects 57 | if(contours.size()>0)objectDetected=true; 58 | else objectDetected = false; 59 | 60 | if(objectDetected){ 61 | //the largest contour is found at the end of the contours vector 62 | //we will simply assume that the biggest contour is the object we are looking for. 63 | vector< vector > largestContourVec; 64 | largestContourVec.push_back(contours.at(contours.size()-1)); 65 | //make a bounding rectangle around the largest contour then find its centroid 66 | //this will be the object's final estimated position. 67 | objectBoundingRectangle = boundingRect(largestContourVec.at(0)); 68 | int xpos = objectBoundingRectangle.x+objectBoundingRectangle.width/2; 69 | int ypos = objectBoundingRectangle.y+objectBoundingRectangle.height/2; 70 | 71 | //update the objects positions by changing the 'theObject' array values 72 | theObject[0] = xpos , theObject[1] = ypos; 73 | } 74 | //make some temp x and y variables so we dont have to type out so much 75 | int x = theObject[0]; 76 | int y = theObject[1]; 77 | 78 | //draw some crosshairs around the object 79 | circle(cameraFeed,Point(x,y),20,Scalar(0,255,0),2); 80 | line(cameraFeed,Point(x,y),Point(x,y-25),Scalar(0,255,0),2); 81 | line(cameraFeed,Point(x,y),Point(x,y+25),Scalar(0,255,0),2); 82 | line(cameraFeed,Point(x,y),Point(x-25,y),Scalar(0,255,0),2); 83 | line(cameraFeed,Point(x,y),Point(x+25,y),Scalar(0,255,0),2); 84 | 85 | //write the position of the object to the screen 86 | putText(cameraFeed,"Tracking object at (" + intToString(x)+","+intToString(y)+")",Point(x,y),1,1,Scalar(255,0,0),2); 87 | 88 | 89 | 90 | } 91 | int main(){ 92 | 93 | //some boolean variables for added functionality 94 | bool objectDetected = false; 95 | //these two can be toggled by pressing 'd' or 't' 96 | bool debugMode = false; 97 | bool trackingEnabled = false; 98 | //pause and resume code 99 | bool pause = false; 100 | //set up the matrices that we will need 101 | //the two frames we will be comparing 102 | Mat frame1,frame2; 103 | //their grayscale images (needed for absdiff() function) 104 | Mat grayImage1,grayImage2; 105 | //resulting difference image 106 | Mat differenceImage; 107 | //thresholded difference image (for use in findContours() function) 108 | Mat thresholdImage; 109 | //video capture object. 110 | VideoCapture capture; 111 | 112 | while(1){ 113 | 114 | //we can loop the video by re-opening the capture every time the video reaches its last frame 115 | 116 | capture.open("bouncingBall.avi"); 117 | 118 | if(!capture.isOpened()){ 119 | cout<<"ERROR ACQUIRING VIDEO FEED\n"; 120 | getchar(); 121 | return -1; 122 | } 123 | 124 | //check if the video has reach its last frame. 125 | //we add '-1' because we are reading two frames from the video at a time. 126 | //if this is not included, we get a memory error! 127 | while(capture.get(CV_CAP_PROP_POS_FRAMES) 17 | #include 18 | 19 | using namespace std; 20 | using namespace cv; 21 | 22 | //our sensitivity value to be used in the threshold() function 23 | const static int SENSITIVITY_VALUE = 20; 24 | //size of blur used to smooth the image to remove possible noise and 25 | //increase the size of the object we are trying to track. (Much like dilate and erode) 26 | const static int BLUR_SIZE = 10; 27 | //we'll have just one object to search for 28 | //and keep track of its position. 29 | int theObject[2] = {0,0}; 30 | //bounding rectangle of the object, we will use the center of this as its position. 31 | Rect objectBoundingRectangle = Rect(0,0,0,0); 32 | 33 | 34 | //int to string helper function 35 | string intToString(int number){ 36 | 37 | //this function has a number input and string output 38 | std::stringstream ss; 39 | ss << number; 40 | return ss.str(); 41 | } 42 | 43 | void searchForMovement(Mat thresholdImage, Mat &cameraFeed){ 44 | //notice how we use the '&' operator for the cameraFeed. This is because we wish 45 | //to take the values passed into the function and manipulate them, rather than just working with a copy. 46 | //eg. we draw to the cameraFeed in this function which is then displayed in the main() function. 47 | bool objectDetected=false; 48 | Mat temp; 49 | thresholdImage.copyTo(temp); 50 | //these two vectors needed for output of findContours 51 | vector< vector > contours; 52 | vector hierarchy; 53 | //find contours of filtered image using openCV findContours function 54 | //findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );// retrieves all contours 55 | findContours(temp,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE );// retrieves external contours 56 | 57 | //if contours vector is not empty, we have found some objects 58 | if(contours.size()>0)objectDetected=true; 59 | else objectDetected = false; 60 | 61 | if(objectDetected){ 62 | //the largest contour is found at the end of the contours vector 63 | //we will simply assume that the biggest contour is the object we are looking for. 64 | vector< vector > largestContourVec; 65 | largestContourVec.push_back(contours.at(contours.size()-1)); 66 | //make a bounding rectangle around the largest contour then find its centroid 67 | //this will be the object's final estimated position. 68 | objectBoundingRectangle = boundingRect(largestContourVec.at(0)); 69 | int xpos = objectBoundingRectangle.x+objectBoundingRectangle.width/2; 70 | int ypos = objectBoundingRectangle.y+objectBoundingRectangle.height/2; 71 | 72 | //update the objects positions by changing the 'theObject' array values 73 | theObject[0] = xpos , theObject[1] = ypos; 74 | } 75 | //make some temp x and y variables so we dont have to type out so much 76 | int x = theObject[0]; 77 | int y = theObject[1]; 78 | //draw some crosshairs on the object 79 | circle(cameraFeed,Point(x,y),20,Scalar(0,255,0),2); 80 | line(cameraFeed,Point(x,y),Point(x,y-25),Scalar(0,255,0),2); 81 | line(cameraFeed,Point(x,y),Point(x,y+25),Scalar(0,255,0),2); 82 | line(cameraFeed,Point(x,y),Point(x-25,y),Scalar(0,255,0),2); 83 | line(cameraFeed,Point(x,y),Point(x+25,y),Scalar(0,255,0),2); 84 | putText(cameraFeed,"Tracking object at (" + intToString(x)+","+intToString(y)+")",Point(x,y),1,1,Scalar(255,0,0),2); 85 | 86 | 87 | 88 | } 89 | int main(){ 90 | 91 | //some boolean variables for added functionality 92 | bool objectDetected = false; 93 | //these two can be toggled by pressing 'd' or 't' 94 | bool debugMode = false; 95 | bool trackingEnabled = false; 96 | //pause and resume code 97 | bool pause = false; 98 | //set up the matrices that we will need 99 | //the two frames we will be comparing 100 | Mat frame1,frame2; 101 | //their grayscale images (needed for absdiff() function) 102 | Mat grayImage1,grayImage2; 103 | //resulting difference image 104 | Mat differenceImage; 105 | //thresholded difference image (for use in findContours() function) 106 | Mat thresholdImage; 107 | //video capture object. 108 | VideoCapture capture; 109 | 110 | while(1){ 111 | 112 | //we can loop the video by re-opening the capture every time the video reaches its last frame 113 | 114 | capture.open("bouncingBall.avi"); 115 | 116 | if(!capture.isOpened()){ 117 | cout<<"ERROR ACQUIRING VIDEO FEED\n"; 118 | getchar(); 119 | return -1; 120 | } 121 | 122 | //check if the video has reach its last frame. 123 | //we add '-1' because we are reading two frames from the video at a time. 124 | //if this is not included, we get a memory error! 125 | while(capture.get(CV_CAP_PROP_POS_FRAMES) 3 | using namespace std; 4 | 5 | class Fruit 6 | { 7 | public: 8 | Fruit(void); 9 | ~Fruit(void); 10 | 11 | int getXPos(); 12 | void setXPos(int x); 13 | 14 | int getYPos(); 15 | void setYPos(int y); 16 | 17 | private: 18 | 19 | int xPos, yPos; 20 | string type; 21 | 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /multiple-object-tracking-tut/part-one/multipleObjectTracking.cpp: -------------------------------------------------------------------------------- 1 | //objectTrackingTutorial.cpp 2 | 3 | //Written by Kyle Hounslow 2013 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software") 6 | //, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 14 | //IN THE SOFTWARE. 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | using namespace cv; 23 | //initial min and max HSV filter values. 24 | //these will be changed using trackbars 25 | int H_MIN = 0; 26 | int H_MAX = 256; 27 | int S_MIN = 0; 28 | int S_MAX = 256; 29 | int V_MIN = 0; 30 | int V_MAX = 256; 31 | //default capture width and height 32 | const int FRAME_WIDTH = 640; 33 | const int FRAME_HEIGHT = 480; 34 | //max number of objects to be detected in frame 35 | const int MAX_NUM_OBJECTS=50; 36 | //minimum and maximum object area 37 | const int MIN_OBJECT_AREA = 40*40; 38 | const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5; 39 | //names that will appear at the top of each window 40 | const string windowName = "Original Image"; 41 | const string windowName1 = "HSV Image"; 42 | const string windowName2 = "Thresholded Image"; 43 | const string windowName3 = "After Morphological Operations"; 44 | const string trackbarWindowName = "Trackbars"; 45 | void on_trackbar( int, void* ) 46 | {//This function gets called whenever a 47 | // trackbar position is changed 48 | 49 | 50 | 51 | 52 | 53 | } 54 | string intToString(int number){ 55 | 56 | 57 | std::stringstream ss; 58 | ss << number; 59 | return ss.str(); 60 | } 61 | void createTrackbars(){ 62 | //create window for trackbars 63 | 64 | 65 | namedWindow(trackbarWindowName,0); 66 | //create memory to store trackbar name on window 67 | char TrackbarName[50]; 68 | sprintf( TrackbarName, "H_MIN", H_MIN); 69 | sprintf( TrackbarName, "H_MAX", H_MAX); 70 | sprintf( TrackbarName, "S_MIN", S_MIN); 71 | sprintf( TrackbarName, "S_MAX", S_MAX); 72 | sprintf( TrackbarName, "V_MIN", V_MIN); 73 | sprintf( TrackbarName, "V_MAX", V_MAX); 74 | //create trackbars and insert them into window 75 | //3 parameters are: the address of the variable that is changing when the trackbar is moved(eg.H_LOW), 76 | //the max value the trackbar can move (eg. H_HIGH), 77 | //and the function that is called whenever the trackbar is moved(eg. on_trackbar) 78 | // ----> ----> ----> 79 | createTrackbar( "H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar ); 80 | createTrackbar( "H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar ); 81 | createTrackbar( "S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar ); 82 | createTrackbar( "S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar ); 83 | createTrackbar( "V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar ); 84 | createTrackbar( "V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar ); 85 | 86 | 87 | } 88 | void drawObject(int x,int y,Mat &frame){ 89 | 90 | cv::circle(frame,cv::Point(x,y),10,cv::Scalar(0,0,255)); 91 | cv::putText(frame,intToString(x)+ " , " + intToString(y),cv::Point(x,y+20),1,1,Scalar(0,255,0)); 92 | 93 | } 94 | void morphOps(Mat &thresh){ 95 | 96 | //create structuring element that will be used to "dilate" and "erode" image. 97 | //the element chosen here is a 3px by 3px rectangle 98 | 99 | Mat erodeElement = getStructuringElement( MORPH_RECT,Size(3,3)); 100 | //dilate with larger element so make sure object is nicely visible 101 | Mat dilateElement = getStructuringElement( MORPH_RECT,Size(8,8)); 102 | 103 | erode(thresh,thresh,erodeElement); 104 | erode(thresh,thresh,erodeElement); 105 | 106 | 107 | dilate(thresh,thresh,dilateElement); 108 | dilate(thresh,thresh,dilateElement); 109 | 110 | 111 | 112 | } 113 | void trackFilteredObject(Mat threshold,Mat HSV, Mat &cameraFeed){ 114 | 115 | int x,y; 116 | 117 | Mat temp; 118 | threshold.copyTo(temp); 119 | //these two vectors needed for output of findContours 120 | vector< vector > contours; 121 | vector hierarchy; 122 | //find contours of filtered image using openCV findContours function 123 | findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE ); 124 | //use moments method to find our filtered object 125 | double refArea = 0; 126 | bool objectFound = false; 127 | if (hierarchy.size() > 0) { 128 | int numObjects = hierarchy.size(); 129 | //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter 130 | if(numObjects= 0; index = hierarchy[index][0]) { 132 | 133 | Moments moment = moments((cv::Mat)contours[index]); 134 | double area = moment.m00; 135 | 136 | //if the area is less than 20 px by 20px then it is probably just noise 137 | //if the area is the same as the 3/2 of the image size, probably just a bad filter 138 | //we only want the object with the largest area so we safe a reference area each 139 | //iteration and compare it to the area in the next iteration. 140 | if(area>MIN_OBJECT_AREA){ 141 | x = moment.m10/area; 142 | y = moment.m01/area; 143 | 144 | 145 | 146 | objectFound = true; 147 | 148 | }else objectFound = false; 149 | 150 | 151 | } 152 | //let user know you found an object 153 | if(objectFound ==true){ 154 | //draw object location on screen 155 | drawObject(x,y,cameraFeed);} 156 | 157 | }else putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2); 158 | } 159 | } 160 | 161 | int main(int argc, char* argv[]) 162 | { 163 | //if we would like to calibrate our filter values, set to true. 164 | bool calibrationMode = true; 165 | 166 | //Matrix to store each frame of the webcam feed 167 | Mat cameraFeed; 168 | Mat threshold; 169 | Mat HSV; 170 | 171 | if(calibrationMode){ 172 | //create slider bars for HSV filtering 173 | createTrackbars(); 174 | } 175 | //video capture object to acquire webcam feed 176 | VideoCapture capture; 177 | //open capture object at location zero (default location for webcam) 178 | capture.open(0); 179 | //set height and width of capture frame 180 | capture.set(CV_CAP_PROP_FRAME_WIDTH,FRAME_WIDTH); 181 | capture.set(CV_CAP_PROP_FRAME_HEIGHT,FRAME_HEIGHT); 182 | //start an infinite loop where webcam feed is copied to cameraFeed matrix 183 | //all of our operations will be performed within this loop 184 | while(1){ 185 | //store image to matrix 186 | capture.read(cameraFeed); 187 | //convert frame from BGR to HSV colorspace 188 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 189 | 190 | if(calibrationMode==true){ 191 | //if in calibration mode, we track objects based on the HSV slider values. 192 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 193 | inRange(HSV,Scalar(H_MIN,S_MIN,V_MIN),Scalar(H_MAX,S_MAX,V_MAX),threshold); 194 | morphOps(threshold); 195 | imshow(windowName2,threshold); 196 | trackFilteredObject(threshold,HSV,cameraFeed); 197 | } 198 | 199 | //show frames 200 | //imshow(windowName2,threshold); 201 | 202 | imshow(windowName,cameraFeed); 203 | //imshow(windowName1,HSV); 204 | 205 | 206 | //delay 30ms so that screen can refresh. 207 | //image will not appear without this waitKey() command 208 | waitKey(30); 209 | } 210 | 211 | 212 | 213 | 214 | 215 | 216 | return 0; 217 | } 218 | 219 | -------------------------------------------------------------------------------- /multiple-object-tracking-tut/part-three/Fruit.cpp: -------------------------------------------------------------------------------- 1 | #include "Fruit.h" 2 | 3 | 4 | 5 | Fruit::Fruit() 6 | { 7 | //set values for default constructor 8 | setType("null"); 9 | setColour(Scalar(0,0,0)); 10 | 11 | } 12 | 13 | Fruit::Fruit(string name){ 14 | 15 | setType(name); 16 | 17 | if(name=="apple"){ 18 | 19 | //TODO: use "calibration mode" to find HSV min 20 | //and HSV max values 21 | 22 | setHSVmin(Scalar(0,0,0)); 23 | setHSVmax(Scalar(255,255,255)); 24 | 25 | //BGR value for Green: 26 | setColour(Scalar(0,255,0)); 27 | 28 | } 29 | if(name=="banana"){ 30 | 31 | //TODO: use "calibration mode" to find HSV min 32 | //and HSV max values 33 | 34 | setHSVmin(Scalar(0,0,0)); 35 | setHSVmax(Scalar(255,255,255)); 36 | 37 | //BGR value for Yellow: 38 | setColour(Scalar(0,255,255)); 39 | 40 | } 41 | if(name=="cherry"){ 42 | 43 | //TODO: use "calibration mode" to find HSV min 44 | //and HSV max values 45 | 46 | setHSVmin(Scalar(0,0,0)); 47 | setHSVmax(Scalar(255,255,255)); 48 | 49 | //BGR value for Red: 50 | setColour(Scalar(0,0,255)); 51 | 52 | } 53 | 54 | 55 | 56 | } 57 | 58 | Fruit::~Fruit(void) 59 | { 60 | } 61 | 62 | int Fruit::getXPos(){ 63 | 64 | return Fruit::xPos; 65 | 66 | } 67 | 68 | void Fruit::setXPos(int x){ 69 | 70 | Fruit::xPos = x; 71 | 72 | } 73 | 74 | int Fruit::getYPos(){ 75 | 76 | return Fruit::yPos; 77 | 78 | } 79 | 80 | void Fruit::setYPos(int y){ 81 | 82 | Fruit::yPos = y; 83 | 84 | } 85 | 86 | Scalar Fruit::getHSVmin(){ 87 | 88 | return Fruit::HSVmin; 89 | 90 | } 91 | Scalar Fruit::getHSVmax(){ 92 | 93 | return Fruit::HSVmax; 94 | } 95 | 96 | void Fruit::setHSVmin(Scalar min){ 97 | 98 | Fruit::HSVmin = min; 99 | } 100 | 101 | 102 | void Fruit::setHSVmax(Scalar max){ 103 | 104 | Fruit::HSVmax = max; 105 | } -------------------------------------------------------------------------------- /multiple-object-tracking-tut/part-three/Fruit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | using namespace cv; 7 | 8 | class Fruit 9 | { 10 | public: 11 | Fruit(); 12 | ~Fruit(void); 13 | 14 | Fruit(string name); 15 | 16 | int getXPos(); 17 | void setXPos(int x); 18 | 19 | int getYPos(); 20 | void setYPos(int y); 21 | 22 | Scalar getHSVmin(); 23 | Scalar getHSVmax(); 24 | 25 | void setHSVmin(Scalar min); 26 | void setHSVmax(Scalar max); 27 | 28 | string getType(){return type;} 29 | void setType(string t){type = t;} 30 | 31 | Scalar getColour(){ 32 | return Colour; 33 | } 34 | void setColour(Scalar c){ 35 | 36 | Colour = c; 37 | } 38 | 39 | private: 40 | 41 | int xPos, yPos; 42 | string type; 43 | Scalar HSVmin, HSVmax; 44 | Scalar Colour; 45 | }; -------------------------------------------------------------------------------- /multiple-object-tracking-tut/part-three/multipleObjectTracking.cpp: -------------------------------------------------------------------------------- 1 | //objectTrackingTutorial.cpp 2 | 3 | //Written by Kyle Hounslow 2013 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software") 6 | //, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 14 | //IN THE SOFTWARE. 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "Fruit.h" 22 | 23 | 24 | //initial min and max HSV filter values. 25 | //these will be changed using trackbars 26 | int H_MIN = 0; 27 | int H_MAX = 256; 28 | int S_MIN = 0; 29 | int S_MAX = 256; 30 | int V_MIN = 0; 31 | int V_MAX = 256; 32 | //default capture width and height 33 | const int FRAME_WIDTH = 640; 34 | const int FRAME_HEIGHT = 480; 35 | //max number of objects to be detected in frame 36 | const int MAX_NUM_OBJECTS=50; 37 | //minimum and maximum object area 38 | const int MIN_OBJECT_AREA = 20*20; 39 | const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5; 40 | //names that will appear at the top of each window 41 | const string windowName = "Original Image"; 42 | const string windowName1 = "HSV Image"; 43 | const string windowName2 = "Thresholded Image"; 44 | const string windowName3 = "After Morphological Operations"; 45 | const string trackbarWindowName = "Trackbars"; 46 | void on_trackbar( int, void* ) 47 | {//This function gets called whenever a 48 | // trackbar position is changed 49 | 50 | 51 | 52 | 53 | 54 | } 55 | string intToString(int number){ 56 | 57 | 58 | std::stringstream ss; 59 | ss << number; 60 | return ss.str(); 61 | } 62 | void createTrackbars(){ 63 | //create window for trackbars 64 | 65 | 66 | namedWindow(trackbarWindowName,0); 67 | //create memory to store trackbar name on window 68 | char TrackbarName[50]; 69 | sprintf( TrackbarName, "H_MIN", H_MIN); 70 | sprintf( TrackbarName, "H_MAX", H_MAX); 71 | sprintf( TrackbarName, "S_MIN", S_MIN); 72 | sprintf( TrackbarName, "S_MAX", S_MAX); 73 | sprintf( TrackbarName, "V_MIN", V_MIN); 74 | sprintf( TrackbarName, "V_MAX", V_MAX); 75 | //create trackbars and insert them into window 76 | //3 parameters are: the address of the variable that is changing when the trackbar is moved(eg.H_LOW), 77 | //the max value the trackbar can move (eg. H_HIGH), 78 | //and the function that is called whenever the trackbar is moved(eg. on_trackbar) 79 | // ----> ----> ----> 80 | createTrackbar( "H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar ); 81 | createTrackbar( "H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar ); 82 | createTrackbar( "S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar ); 83 | createTrackbar( "S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar ); 84 | createTrackbar( "V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar ); 85 | createTrackbar( "V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar ); 86 | 87 | 88 | } 89 | void drawObject(vector theFruits,Mat &frame){ 90 | 91 | for(int i =0; i apples; 121 | 122 | Mat temp; 123 | threshold.copyTo(temp); 124 | //these two vectors needed for output of findContours 125 | vector< vector > contours; 126 | vector hierarchy; 127 | //find contours of filtered image using openCV findContours function 128 | findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE ); 129 | //use moments method to find our filtered object 130 | double refArea = 0; 131 | bool objectFound = false; 132 | if (hierarchy.size() > 0) { 133 | int numObjects = hierarchy.size(); 134 | //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter 135 | if(numObjects= 0; index = hierarchy[index][0]) { 137 | 138 | Moments moment = moments((cv::Mat)contours[index]); 139 | double area = moment.m00; 140 | 141 | //if the area is less than 20 px by 20px then it is probably just noise 142 | //if the area is the same as the 3/2 of the image size, probably just a bad filter 143 | //we only want the object with the largest area so we safe a reference area each 144 | //iteration and compare it to the area in the next iteration. 145 | if(area>MIN_OBJECT_AREA){ 146 | 147 | Fruit apple; 148 | 149 | apple.setXPos(moment.m10/area); 150 | apple.setYPos(moment.m01/area); 151 | 152 | 153 | apples.push_back(apple); 154 | 155 | objectFound = true; 156 | 157 | }else objectFound = false; 158 | 159 | 160 | } 161 | //let user know you found an object 162 | if(objectFound ==true){ 163 | //draw object location on screen 164 | drawObject(apples,cameraFeed);} 165 | 166 | }else putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2); 167 | } 168 | } 169 | void trackFilteredObject(Fruit theFruit,Mat threshold,Mat HSV, Mat &cameraFeed){ 170 | 171 | 172 | vector apples; 173 | 174 | Mat temp; 175 | threshold.copyTo(temp); 176 | //these two vectors needed for output of findContours 177 | vector< vector > contours; 178 | vector hierarchy; 179 | //find contours of filtered image using openCV findContours function 180 | findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE ); 181 | //use moments method to find our filtered object 182 | double refArea = 0; 183 | bool objectFound = false; 184 | if (hierarchy.size() > 0) { 185 | int numObjects = hierarchy.size(); 186 | //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter 187 | if(numObjects= 0; index = hierarchy[index][0]) { 189 | 190 | Moments moment = moments((cv::Mat)contours[index]); 191 | double area = moment.m00; 192 | 193 | //if the area is less than 20 px by 20px then it is probably just noise 194 | //if the area is the same as the 3/2 of the image size, probably just a bad filter 195 | //we only want the object with the largest area so we safe a reference area each 196 | //iteration and compare it to the area in the next iteration. 197 | if(area>MIN_OBJECT_AREA){ 198 | 199 | Fruit apple; 200 | 201 | apple.setXPos(moment.m10/area); 202 | apple.setYPos(moment.m01/area); 203 | apple.setType(theFruit.getType()); 204 | apple.setColour(theFruit.getColour()); 205 | 206 | apples.push_back(apple); 207 | 208 | objectFound = true; 209 | 210 | }else objectFound = false; 211 | 212 | 213 | } 214 | //let user know you found an object 215 | if(objectFound ==true){ 216 | //draw object location on screen 217 | drawObject(apples,cameraFeed);} 218 | 219 | }else putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2); 220 | } 221 | } 222 | int main(int argc, char* argv[]) 223 | { 224 | //if we would like to calibrate our filter values, set to true. 225 | bool calibrationMode = true; 226 | 227 | //Matrix to store each frame of the webcam feed 228 | Mat cameraFeed; 229 | Mat threshold; 230 | Mat HSV; 231 | 232 | if(calibrationMode){ 233 | //create slider bars for HSV filtering 234 | createTrackbars(); 235 | } 236 | //video capture object to acquire webcam feed 237 | VideoCapture capture; 238 | //open capture object at location zero (default location for webcam) 239 | capture.open(0); 240 | //set height and width of capture frame 241 | capture.set(CV_CAP_PROP_FRAME_WIDTH,FRAME_WIDTH); 242 | capture.set(CV_CAP_PROP_FRAME_HEIGHT,FRAME_HEIGHT); 243 | //start an infinite loop where webcam feed is copied to cameraFeed matrix 244 | //all of our operations will be performed within this loop 245 | while(1){ 246 | //store image to matrix 247 | capture.read(cameraFeed); 248 | //convert frame from BGR to HSV colorspace 249 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 250 | 251 | if(calibrationMode==true){ 252 | //if in calibration mode, we track objects based on the HSV slider values. 253 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 254 | inRange(HSV,Scalar(H_MIN,S_MIN,V_MIN),Scalar(H_MAX,S_MAX,V_MAX),threshold); 255 | morphOps(threshold); 256 | imshow(windowName2,threshold); 257 | trackFilteredObject(threshold,HSV,cameraFeed); 258 | }else{ 259 | //create some temp fruit objects so that 260 | //we can use their member functions/information 261 | Fruit apple("apple"), banana("banana"), cherry("cherry"); 262 | 263 | 264 | //first find apples 265 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 266 | inRange(HSV,apple.getHSVmin(),apple.getHSVmax(),threshold); 267 | morphOps(threshold); 268 | trackFilteredObject(apple,threshold,HSV,cameraFeed); 269 | //then bananas 270 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 271 | inRange(HSV,banana.getHSVmin(),banana.getHSVmax(),threshold); 272 | morphOps(threshold); 273 | trackFilteredObject(banana,threshold,HSV,cameraFeed); 274 | //then cherries 275 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 276 | inRange(HSV,cherry.getHSVmin(),cherry.getHSVmax(),threshold); 277 | morphOps(threshold); 278 | trackFilteredObject(cherry,threshold,HSV,cameraFeed); 279 | 280 | 281 | 282 | } 283 | 284 | //show frames 285 | //imshow(windowName2,threshold); 286 | 287 | imshow(windowName,cameraFeed); 288 | //imshow(windowName1,HSV); 289 | 290 | 291 | //delay 30ms so that screen can refresh. 292 | //image will not appear without this waitKey() command 293 | waitKey(30); 294 | } 295 | 296 | 297 | 298 | 299 | 300 | 301 | return 0; 302 | } 303 | -------------------------------------------------------------------------------- /multiple-object-tracking-tut/part-two/multipleObjectTracking.cpp: -------------------------------------------------------------------------------- 1 | //objectTrackingTutorial.cpp 2 | 3 | //Written by Kyle Hounslow 2013 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software") 6 | //, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 14 | //IN THE SOFTWARE. 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "Fruit.h" 23 | 24 | using namespace cv; 25 | //initial min and max HSV filter values. 26 | //these will be changed using trackbars 27 | int H_MIN = 0; 28 | int H_MAX = 256; 29 | int S_MIN = 0; 30 | int S_MAX = 256; 31 | int V_MIN = 0; 32 | int V_MAX = 256; 33 | //default capture width and height 34 | const int FRAME_WIDTH = 640; 35 | const int FRAME_HEIGHT = 480; 36 | //max number of objects to be detected in frame 37 | const int MAX_NUM_OBJECTS=50; 38 | //minimum and maximum object area 39 | const int MIN_OBJECT_AREA = 40*40; 40 | const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5; 41 | //names that will appear at the top of each window 42 | const string windowName = "Original Image"; 43 | const string windowName1 = "HSV Image"; 44 | const string windowName2 = "Thresholded Image"; 45 | const string windowName3 = "After Morphological Operations"; 46 | const string trackbarWindowName = "Trackbars"; 47 | void on_trackbar( int, void* ) 48 | {//This function gets called whenever a 49 | // trackbar position is changed 50 | 51 | 52 | 53 | 54 | 55 | } 56 | string intToString(int number){ 57 | 58 | 59 | std::stringstream ss; 60 | ss << number; 61 | return ss.str(); 62 | } 63 | void createTrackbars(){ 64 | //create window for trackbars 65 | 66 | 67 | namedWindow(trackbarWindowName,0); 68 | //create memory to store trackbar name on window 69 | char TrackbarName[50]; 70 | sprintf( TrackbarName, "H_MIN", H_MIN); 71 | sprintf( TrackbarName, "H_MAX", H_MAX); 72 | sprintf( TrackbarName, "S_MIN", S_MIN); 73 | sprintf( TrackbarName, "S_MAX", S_MAX); 74 | sprintf( TrackbarName, "V_MIN", V_MIN); 75 | sprintf( TrackbarName, "V_MAX", V_MAX); 76 | //create trackbars and insert them into window 77 | //3 parameters are: the address of the variable that is changing when the trackbar is moved(eg.H_LOW), 78 | //the max value the trackbar can move (eg. H_HIGH), 79 | //and the function that is called whenever the trackbar is moved(eg. on_trackbar) 80 | // ----> ----> ----> 81 | createTrackbar( "H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar ); 82 | createTrackbar( "H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar ); 83 | createTrackbar( "S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar ); 84 | createTrackbar( "S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar ); 85 | createTrackbar( "V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar ); 86 | createTrackbar( "V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar ); 87 | 88 | 89 | } 90 | void drawObject(vector theFruits,Mat &frame){ 91 | 92 | for(int i =0; i apples; 121 | 122 | Mat temp; 123 | threshold.copyTo(temp); 124 | //these two vectors needed for output of findContours 125 | vector< vector > contours; 126 | vector hierarchy; 127 | //find contours of filtered image using openCV findContours function 128 | findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE ); 129 | //use moments method to find our filtered object 130 | double refArea = 0; 131 | bool objectFound = false; 132 | if (hierarchy.size() > 0) { 133 | int numObjects = hierarchy.size(); 134 | //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter 135 | if(numObjects= 0; index = hierarchy[index][0]) { 137 | 138 | Moments moment = moments((cv::Mat)contours[index]); 139 | double area = moment.m00; 140 | 141 | //if the area is less than 20 px by 20px then it is probably just noise 142 | //if the area is the same as the 3/2 of the image size, probably just a bad filter 143 | //we only want the object with the largest area so we safe a reference area each 144 | //iteration and compare it to the area in the next iteration. 145 | if(area>MIN_OBJECT_AREA){ 146 | 147 | Fruit apple; 148 | 149 | apple.setXPos(moment.m10/area); 150 | apple.setYPos(moment.m01/area); 151 | 152 | apples.push_back(apple); 153 | 154 | objectFound = true; 155 | 156 | }else objectFound = false; 157 | 158 | 159 | } 160 | //let user know you found an object 161 | if(objectFound ==true){ 162 | //draw object location on screen 163 | drawObject(apples,cameraFeed);} 164 | 165 | }else putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2); 166 | } 167 | } 168 | 169 | int main(int argc, char* argv[]) 170 | { 171 | //if we would like to calibrate our filter values, set to true. 172 | bool calibrationMode = true; 173 | 174 | //Matrix to store each frame of the webcam feed 175 | Mat cameraFeed; 176 | Mat threshold; 177 | Mat HSV; 178 | 179 | if(calibrationMode){ 180 | //create slider bars for HSV filtering 181 | createTrackbars(); 182 | } 183 | //video capture object to acquire webcam feed 184 | VideoCapture capture; 185 | //open capture object at location zero (default location for webcam) 186 | capture.open(0); 187 | //set height and width of capture frame 188 | capture.set(CV_CAP_PROP_FRAME_WIDTH,FRAME_WIDTH); 189 | capture.set(CV_CAP_PROP_FRAME_HEIGHT,FRAME_HEIGHT); 190 | //start an infinite loop where webcam feed is copied to cameraFeed matrix 191 | //all of our operations will be performed within this loop 192 | while(1){ 193 | //store image to matrix 194 | capture.read(cameraFeed); 195 | //convert frame from BGR to HSV colorspace 196 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 197 | 198 | if(calibrationMode==true){ 199 | //if in calibration mode, we track objects based on the HSV slider values. 200 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 201 | inRange(HSV,Scalar(H_MIN,S_MIN,V_MIN),Scalar(H_MAX,S_MAX,V_MAX),threshold); 202 | morphOps(threshold); 203 | imshow(windowName2,threshold); 204 | trackFilteredObject(threshold,HSV,cameraFeed); 205 | } 206 | 207 | //show frames 208 | //imshow(windowName2,threshold); 209 | 210 | imshow(windowName,cameraFeed); 211 | //imshow(windowName1,HSV); 212 | 213 | 214 | //delay 30ms so that screen can refresh. 215 | //image will not appear without this waitKey() command 216 | waitKey(30); 217 | } 218 | 219 | 220 | 221 | 222 | 223 | 224 | return 0; 225 | } 226 | 227 | -------------------------------------------------------------------------------- /object-tracking-tut/objectTrackingTut.cpp: -------------------------------------------------------------------------------- 1 | //objectTrackingTutorial.cpp 2 | 3 | //Written by Kyle Hounslow 2013 4 | 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software") 6 | //, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 14 | //IN THE SOFTWARE. 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | using namespace cv; 23 | //initial min and max HSV filter values. 24 | //these will be changed using trackbars 25 | int H_MIN = 0; 26 | int H_MAX = 256; 27 | int S_MIN = 0; 28 | int S_MAX = 256; 29 | int V_MIN = 0; 30 | int V_MAX = 256; 31 | //default capture width and height 32 | const int FRAME_WIDTH = 640; 33 | const int FRAME_HEIGHT = 480; 34 | //max number of objects to be detected in frame 35 | const int MAX_NUM_OBJECTS=50; 36 | //minimum and maximum object area 37 | const int MIN_OBJECT_AREA = 20*20; 38 | const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5; 39 | //names that will appear at the top of each window 40 | const string windowName = "Original Image"; 41 | const string windowName1 = "HSV Image"; 42 | const string windowName2 = "Thresholded Image"; 43 | const string windowName3 = "After Morphological Operations"; 44 | const string trackbarWindowName = "Trackbars"; 45 | void on_trackbar( int, void* ) 46 | {//This function gets called whenever a 47 | // trackbar position is changed 48 | 49 | 50 | 51 | 52 | 53 | } 54 | string intToString(int number){ 55 | 56 | 57 | std::stringstream ss; 58 | ss << number; 59 | return ss.str(); 60 | } 61 | void createTrackbars(){ 62 | //create window for trackbars 63 | 64 | 65 | namedWindow(trackbarWindowName,0); 66 | //create memory to store trackbar name on window 67 | char TrackbarName[50]; 68 | sprintf( TrackbarName, "H_MIN", H_MIN); 69 | sprintf( TrackbarName, "H_MAX", H_MAX); 70 | sprintf( TrackbarName, "S_MIN", S_MIN); 71 | sprintf( TrackbarName, "S_MAX", S_MAX); 72 | sprintf( TrackbarName, "V_MIN", V_MIN); 73 | sprintf( TrackbarName, "V_MAX", V_MAX); 74 | //create trackbars and insert them into window 75 | //3 parameters are: the address of the variable that is changing when the trackbar is moved(eg.H_LOW), 76 | //the max value the trackbar can move (eg. H_HIGH), 77 | //and the function that is called whenever the trackbar is moved(eg. on_trackbar) 78 | // ----> ----> ----> 79 | createTrackbar( "H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar ); 80 | createTrackbar( "H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar ); 81 | createTrackbar( "S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar ); 82 | createTrackbar( "S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar ); 83 | createTrackbar( "V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar ); 84 | createTrackbar( "V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar ); 85 | 86 | 87 | } 88 | void drawObject(int x, int y,Mat &frame){ 89 | 90 | //use some of the openCV drawing functions to draw crosshairs 91 | //on your tracked image! 92 | 93 | //UPDATE:JUNE 18TH, 2013 94 | //added 'if' and 'else' statements to prevent 95 | //memory errors from writing off the screen (ie. (-25,-25) is not within the window!) 96 | 97 | circle(frame,Point(x,y),20,Scalar(0,255,0),2); 98 | if(y-25>0) 99 | line(frame,Point(x,y),Point(x,y-25),Scalar(0,255,0),2); 100 | else line(frame,Point(x,y),Point(x,0),Scalar(0,255,0),2); 101 | if(y+250) 105 | line(frame,Point(x,y),Point(x-25,y),Scalar(0,255,0),2); 106 | else line(frame,Point(x,y),Point(0,y),Scalar(0,255,0),2); 107 | if(x+25 > contours; 139 | vector hierarchy; 140 | //find contours of filtered image using openCV findContours function 141 | findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE ); 142 | //use moments method to find our filtered object 143 | double refArea = 0; 144 | bool objectFound = false; 145 | if (hierarchy.size() > 0) { 146 | int numObjects = hierarchy.size(); 147 | //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter 148 | if(numObjects= 0; index = hierarchy[index][0]) { 150 | 151 | Moments moment = moments((cv::Mat)contours[index]); 152 | double area = moment.m00; 153 | 154 | //if the area is less than 20 px by 20px then it is probably just noise 155 | //if the area is the same as the 3/2 of the image size, probably just a bad filter 156 | //we only want the object with the largest area so we safe a reference area each 157 | //iteration and compare it to the area in the next iteration. 158 | if(area>MIN_OBJECT_AREA && arearefArea){ 159 | x = moment.m10/area; 160 | y = moment.m01/area; 161 | objectFound = true; 162 | refArea = area; 163 | }else objectFound = false; 164 | 165 | 166 | } 167 | //let user know you found an object 168 | if(objectFound ==true){ 169 | putText(cameraFeed,"Tracking Object",Point(0,50),2,1,Scalar(0,255,0),2); 170 | //draw object location on screen 171 | drawObject(x,y,cameraFeed);} 172 | 173 | }else putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2); 174 | } 175 | } 176 | int main(int argc, char* argv[]) 177 | { 178 | //some boolean variables for different functionality within this 179 | //program 180 | bool trackObjects = false; 181 | bool useMorphOps = false; 182 | //Matrix to store each frame of the webcam feed 183 | Mat cameraFeed; 184 | //matrix storage for HSV image 185 | Mat HSV; 186 | //matrix storage for binary threshold image 187 | Mat threshold; 188 | //x and y values for the location of the object 189 | int x=0, y=0; 190 | //create slider bars for HSV filtering 191 | createTrackbars(); 192 | //video capture object to acquire webcam feed 193 | VideoCapture capture; 194 | //open capture object at location zero (default location for webcam) 195 | capture.open(0); 196 | //set height and width of capture frame 197 | capture.set(CV_CAP_PROP_FRAME_WIDTH,FRAME_WIDTH); 198 | capture.set(CV_CAP_PROP_FRAME_HEIGHT,FRAME_HEIGHT); 199 | //start an infinite loop where webcam feed is copied to cameraFeed matrix 200 | //all of our operations will be performed within this loop 201 | while(1){ 202 | //store image to matrix 203 | capture.read(cameraFeed); 204 | //convert frame from BGR to HSV colorspace 205 | cvtColor(cameraFeed,HSV,COLOR_BGR2HSV); 206 | //filter HSV image between values and store filtered image to 207 | //threshold matrix 208 | inRange(HSV,Scalar(H_MIN,S_MIN,V_MIN),Scalar(H_MAX,S_MAX,V_MAX),threshold); 209 | //perform morphological operations on thresholded image to eliminate noise 210 | //and emphasize the filtered object(s) 211 | if(useMorphOps) 212 | morphOps(threshold); 213 | //pass in thresholded frame to our object tracking function 214 | //this function will return the x and y coordinates of the 215 | //filtered object 216 | if(trackObjects) 217 | trackFilteredObject(x,y,threshold,cameraFeed); 218 | 219 | //show frames 220 | imshow(windowName2,threshold); 221 | imshow(windowName,cameraFeed); 222 | imshow(windowName1,HSV); 223 | 224 | 225 | //delay 30ms so that screen can refresh. 226 | //image will not appear without this waitKey() command 227 | waitKey(30); 228 | } 229 | 230 | 231 | 232 | 233 | 234 | 235 | return 0; 236 | } 237 | 238 | -------------------------------------------------------------------------------- /video-writer-tut/final-code/myVideoWriter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace cv; 6 | using namespace std; 7 | 8 | string intToString(int number){ 9 | 10 | 11 | std::stringstream ss; 12 | ss << number; 13 | return ss.str(); 14 | } 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | bool recording = false; 19 | bool startNewRecording = false; 20 | int inc=0; 21 | bool firstRun = true; 22 | 23 | VideoCapture cap(0); // open the video camera no. 0 24 | VideoWriter oVideoWriter;//create videoWriter object, not initialized yet 25 | 26 | if (!cap.isOpened()) // if not success, exit program 27 | { 28 | cout << "ERROR: Cannot open the video file" << endl; 29 | return -1; 30 | } 31 | 32 | namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo" 33 | 34 | double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video 35 | double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video 36 | 37 | cout << "Frame Size = " << dWidth << "x" << dHeight << endl; 38 | 39 | //set framesize for use with videoWriter 40 | Size frameSize(static_cast(dWidth), static_cast(dHeight)); 41 | 42 | 43 | while (1) { 44 | 45 | if(startNewRecording==true){ 46 | 47 | 48 | oVideoWriter = VideoWriter("D:/MyVideo"+intToString(inc)+".avi", CV_FOURCC('D', 'I', 'V', '3'), 20, frameSize, true); //initialize the VideoWriter object 49 | //oVideoWriter = VideoWriter("D:/MyVideo"+intToString(inc)+".avi", (int)cap.get(CV_CAP_PROP_FOURCC), 20, frameSize, true); //initialize the VideoWriter object 50 | 51 | recording = true; 52 | startNewRecording = false; 53 | cout<<"New video file created D:/MyVideo"+intToString(inc)+".avi "< 2 | #include 3 | #include 4 | 5 | using namespace cv; 6 | using namespace std; 7 | 8 | string intToString(int number){ 9 | 10 | 11 | std::stringstream ss; 12 | ss << number; 13 | return ss.str(); 14 | } 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | 19 | VideoCapture cap(0); // open the video camera no. 0 20 | 21 | if (!cap.isOpened()) // if not success, exit program 22 | { 23 | cout << "ERROR INITIALIZING VIDEO CAPTURE" << endl; 24 | return -1; 25 | } 26 | 27 | char* windowName = "Webcam Feed"; 28 | namedWindow(windowName,CV_WINDOW_AUTOSIZE); //create a window to display our webcam feed 29 | 30 | 31 | while (1) { 32 | 33 | Mat frame; 34 | 35 | bool bSuccess = cap.read(frame); // read a new frame from camera feed 36 | 37 | if (!bSuccess) //test if frame successfully read 38 | { 39 | cout << "ERROR READING FRAME FROM CAMERA FEED" << endl; 40 | break; 41 | } 42 | 43 | 44 | imshow(windowName, frame); //show the frame in "MyVideo" window 45 | 46 | //listen for 10ms for a key to be pressed 47 | switch(waitKey(10)){ 48 | 49 | case 27: 50 | //'esc' has been pressed (ASCII value for 'esc' is 27) 51 | //exit program. 52 | return 0; 53 | 54 | } 55 | 56 | 57 | } 58 | 59 | return 0; 60 | 61 | } 62 | //////////////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /video-writer-tut/part-two/myVideoWriter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace cv; 6 | using namespace std; 7 | 8 | string intToString(int number){ 9 | 10 | 11 | std::stringstream ss; 12 | ss << number; 13 | return ss.str(); 14 | } 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | 19 | VideoCapture cap(0); // open the video camera no. 0 20 | 21 | cv::VideoWriter writer; 22 | 23 | 24 | if (!cap.isOpened()) // if not success, exit program 25 | { 26 | cout << "ERROR INITIALIZING VIDEO CAPTURE" << endl; 27 | return -1; 28 | } 29 | 30 | 31 | char* windowName = "Webcam Feed"; 32 | namedWindow(windowName,CV_WINDOW_AUTOSIZE); //create a window to display our webcam feed 33 | 34 | //filename string 35 | 36 | string filename = "D:\myVideo.avi"; 37 | 38 | //fourcc integer 39 | 40 | int fcc = CV_FOURCC('D','I','V','3'); 41 | 42 | //frames per sec integer 43 | 44 | int fps = 10; 45 | 46 | //frame size 47 | 48 | cv::Size frameSize(cap.get(CV_CAP_PROP_FRAME_WIDTH),cap.get(CV_CAP_PROP_FRAME_HEIGHT)); 49 | 50 | 51 | writer = VideoWriter(filename,fcc,fps,frameSize); 52 | 53 | if(!writer.isOpened()){ 54 | 55 | cout<<"ERROR OPENING FILE FOR WRITE"<