├── 0 The I don't have a notebook notebook.ipynb ├── 1 Getting started notebook.ipynb ├── 2 Fundamentals.ipynb ├── 3 Image stats and image processing.ipynb ├── 4 Features.ipynb ├── 5 detecting faces and other things.ipynb ├── 6 Moving away from the notebook.ipynb ├── LICENSE ├── README.md ├── cheat.py ├── common.py ├── common.pyc ├── edgedemo.png ├── haarcascade_frontalface_default.xml ├── noidea.jpg ├── play.py ├── start.py ├── test.jpg ├── video.py └── video.pyc /0 The I don't have a notebook notebook.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "## Running this tutorial without Jupyter\n", 11 | "\n", 12 | "If you are running on your own machine then install the whole tutorial. If you're running somewhere else... maybe in Aber Comp Sci Delph ... then you need to run standalone OpenCV. This is installed in the uni.\n", 13 | "\n", 14 | "First we need to import the relevant libraries: OpenCV itself, Numpy, and a couple of others. Common and Video are simple data handling and opening routines that you can find in the OpenCV Python Samples directory or from the github repo linked above. We'll start each notebook with the same includes - you don't need all of them every time (so this is bad form, really) but it's easier to just copy and paste. " 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 2, 20 | "metadata": { 21 | "collapsed": true, 22 | "deletable": true, 23 | "editable": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "# these imports let you use opencv\n", 28 | "import cv2 #opencv itself\n", 29 | "import common #some useful opencv functions\n", 30 | "import video # some video stuff\n", 31 | "import numpy as np # matrix manipulations" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": { 37 | "deletable": true, 38 | "editable": true 39 | }, 40 | "source": [ 41 | "The following box is useless if you're not using a notebook - they just enable the online notebook drawing stuff. " 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 3, 47 | "metadata": { 48 | "collapsed": true, 49 | "deletable": true, 50 | "editable": true 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "#the following are to do with this interactive notebook code\n", 55 | "%matplotlib inline \n", 56 | "from matplotlib import pyplot as plt # this lets you draw inline pictures in the notebooks\n", 57 | "import pylab # this allows you to control figure size \n", 58 | "pylab.rcParams['figure.figsize'] = (10.0, 8.0) # this controls figure size in the notebook" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": { 64 | "deletable": true, 65 | "editable": true 66 | }, 67 | "source": [ 68 | "## stuff about window handling\n", 69 | "\n", 70 | "It's worth noting here that we're using matplotlib to show the images, as we're using a Jupyter notebook. This means we need to think about things like \"colormaps\".\n", 71 | "\n", 72 | "When you use OpenCV outside of the notebook context, there are other things to remember - you'll need to create a window to put the image into with \n", 73 | "\n", 74 | "```\n", 75 | "cv2.namedWindow(\"windowname\")\n", 76 | "```\n", 77 | "\n", 78 | "Then to put an image in the window you've created, you can use\n", 79 | "\n", 80 | "```\n", 81 | "cv2.imshow(\"windowname\",image_variable)\n", 82 | "```\n", 83 | "\n", 84 | "This won't actually do anything until you call the waitKey function, which is the function that does most of the work when it comes to OpenCV image display. It waits for user input, storing any keypresses in the keypress variable; however it also does the window redraw. **t** is the delay in milliseconds.\n", 85 | "```\n", 86 | "keypress=cv2.waitKey(t)\n", 87 | "```\n", 88 | "\n", 89 | "This is a **gotcha** for the opencv interface: even if you have no interest in waiting for a milisecond or two for keyboard input you have to do the waitKey in order to redraw the images.\n", 90 | "\n", 91 | "## playing in opencv\n", 92 | "\n", 93 | "If at any point you want to try any of this tutorial code outside the notebook context there's a file called \"play.py\" which has the window management stuff in it- try copying some code from this page into that file." 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": { 100 | "collapsed": true, 101 | "deletable": true, 102 | "editable": true 103 | }, 104 | "outputs": [], 105 | "source": [] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": { 110 | "deletable": true, 111 | "editable": true 112 | }, 113 | "source": [ 114 | "[Next](1%20Getting%20started%20notebook.ipynb)" 115 | ] 116 | } 117 | ], 118 | "metadata": { 119 | "kernelspec": { 120 | "display_name": "Python 3", 121 | "language": "python", 122 | "name": "python3" 123 | }, 124 | "language_info": { 125 | "codemirror_mode": { 126 | "name": "ipython", 127 | "version": 3 128 | }, 129 | "file_extension": ".py", 130 | "mimetype": "text/x-python", 131 | "name": "python", 132 | "nbconvert_exporter": "python", 133 | "pygments_lexer": "ipython3", 134 | "version": "3.6.0" 135 | } 136 | }, 137 | "nbformat": 4, 138 | "nbformat_minor": 0 139 | } 140 | -------------------------------------------------------------------------------- /1 Getting started notebook.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# OpenCV from the very beginning\n", 11 | "\n", 12 | "This is a tutorial that should get you up and running with OpenCV as fast as possible. The emphasis is on practical, quick, python-based image analysis and manipulation with pointers to a lot of the gotchas. It's not on principles or theory: if you want that, read a book:-)\n", 13 | "\n", 14 | "(I recommend : [https://www.amazon.co.uk/Image-Processing-Analysis-Machine-Vision/dp/1133593607/ref=dp_ob_image_bk] for a thorough and clear image processing base as well as a computer vision intro. I also recommend [http://szeliski.org/Book/] which is clear, vision rather than image processing based, and available online)" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": { 20 | "deletable": true, 21 | "editable": true 22 | }, 23 | "source": [ 24 | "## First things first\n", 25 | "\n", 26 | "*Install*. Things to install:\n", 27 | " * Python\n", 28 | " * Install PIP which lets you install other libraries within python. Anaconda [ https://www.continuum.io/downloads ] is another option, which comes with a all the main suggestions below\n", 29 | " * numpy \n", 30 | " * scipy\n", 31 | " * There are loads of other libraries to install once you have python. If you're not already using Python for prototyping it is at least worth a look, and so you may also want to try installing these:\n", 32 | " * pandas (data analysis)\n", 33 | " * matplotlib (plotting)\n", 34 | " * jupyter (interactive notebooks: this is a jupyter notebook)\n", 35 | " \n", 36 | " * OpenCV 3.1\n", 37 | " * This has a bunch of dependencies. Here are instructions for Linux installation: http://docs.opencv.org/3.1.0/d7/d9f/tutorial_linux_install.html\n", 38 | " * Here are instructions for Mac:\n", 39 | " https://prateekvjoshi.com/2015/10/09/installing-opencv-3-with-python-on-mac-os-x/\n", 40 | " * And here for Windows: http://docs.opencv.org/3.1.0/d5/de5/tutorial_py_setup_in_windows.html\n", 41 | "\n" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": { 47 | "deletable": true, 48 | "editable": true 49 | }, 50 | "source": [ 51 | "### Testing OpenCV installation\n", 52 | "If that's worked you can go to the samples directory and run some code to test it. On linux or mac, change to the right directory (you'll find \"samples\" under opencv-3.1.0) then type ./edge.py\n", 53 | "\n", 54 | "```\n", 55 | "hannah@loganberry ~/Downloads/opencv-3.1.0/samples/python $ ./edge.py \n", 56 | "```\n", 57 | "\n", 58 | "If you get a window with some trackbars and edge-detected output of your webcam, you're good to go.\n", 59 | "To run the same test in Windows, try opening the edge.py file in your Python editor of choice (e.g. Idle) and selecting run.\n", 60 | "\n", 61 | "![Edge detection example](edgedemo.png \"Edges\")" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": { 67 | "deletable": true, 68 | "editable": true 69 | }, 70 | "source": [ 71 | "## Final setup\n", 72 | "If you've downloaded all the files from github, and you've tested the OpenCV install with edge detection and the webcam, the next step is the jupyter notebook. Get yourself a new directory for the OpenCV tutorial, and get a copy of the following github repository: \n", 73 | "\n", 74 | "[https://github.com/handee/opencv-gettingstarted]. You can do this by selecting \"download zip\" if you don't have git installed.\n", 75 | "\n", 76 | "Once you've got that, navigate to the directory that contains the tutorial material, and type \n", 77 | "```\n", 78 | "jupyter notebook\n", 79 | "```\n", 80 | "which will start a notebook server. Notebooks let you mix python code and documentation - this is a jupyter notebook, and the next few steps of the tutorial are jupyter notebooks too." 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": { 87 | "collapsed": true, 88 | "deletable": true, 89 | "editable": true 90 | }, 91 | "outputs": [], 92 | "source": [] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": { 97 | "collapsed": true, 98 | "deletable": true, 99 | "editable": true 100 | }, 101 | "source": [ 102 | "[Previous](0%20The%20I%20don't%20have%20a%20notebook%20notebook.ipynb) [Next](2%20Fundamentals.ipynb)" 103 | ] 104 | } 105 | ], 106 | "metadata": { 107 | "kernelspec": { 108 | "display_name": "Python 3", 109 | "language": "python", 110 | "name": "python3" 111 | }, 112 | "language_info": { 113 | "codemirror_mode": { 114 | "name": "ipython", 115 | "version": 3 116 | }, 117 | "file_extension": ".py", 118 | "mimetype": "text/x-python", 119 | "name": "python", 120 | "nbconvert_exporter": "python", 121 | "pygments_lexer": "ipython3", 122 | "version": "3.6.0" 123 | } 124 | }, 125 | "nbformat": 4, 126 | "nbformat_minor": 0 127 | } 128 | -------------------------------------------------------------------------------- /6 Moving away from the notebook.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# Moving away from the notebook\n", 11 | "\n", 12 | "These Jupyter notebooks provide a nice code playground for looking at Python and testing individual ideas one by one but it is time to move away from this notebook and into an \"*actual program*\". You may have already been doing this with play.py file as we go along, but if not, it's time to open up a real program. \n", 13 | "\n", 14 | "What we're going to do is video, and we're going to do it with face detection to start off with. Open up (in a text editor or code editor...) the file \n", 15 | "\n", 16 | "```\n", 17 | "start.py\n", 18 | "```\n", 19 | "\n", 20 | "This has the following code at the top of it (should look familiar...)" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 1, 26 | "metadata": { 27 | "collapsed": true, 28 | "deletable": true, 29 | "editable": true 30 | }, 31 | "outputs": [], 32 | "source": [ 33 | "# these imports let you use opencv\n", 34 | "import cv2 #opencv itself\n", 35 | "import common #some useful opencv functions\n", 36 | "import video # some video stuff\n", 37 | "import numpy as np # matrix manipulations\n" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "deletable": true, 44 | "editable": true 45 | }, 46 | "source": [ 47 | "For the purposes of the notebook (this page that you're reading now) we're going to have to do some notebook code in order to view images here" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 2, 53 | "metadata": { 54 | "collapsed": true, 55 | "deletable": true, 56 | "editable": true 57 | }, 58 | "outputs": [], 59 | "source": [ 60 | "#the following are to do with this interactive notebook code\n", 61 | "%matplotlib inline \n", 62 | "from matplotlib import pyplot as plt # this lets you draw inline pictures in the notebooks\n", 63 | "import pylab # this allows you to control figure size \n", 64 | "pylab.rcParams['figure.figsize'] = (10.0, 8.0) # this controls figure size in the notebook" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": { 70 | "deletable": true, 71 | "editable": true 72 | }, 73 | "source": [ 74 | "The other code that is in the file start.py opens the webcam (if the webcam works), then just puts the contents of the webcam in a window until someone presses escape, while counting up the frames (until someone presses escape).\n", 75 | "\n", 76 | "Test this now. You should just have a really basic webcam viewer.\n", 77 | "\n", 78 | "What we are going to do now is to edit this webcam viewer and introduce detections (from previous notebooks) and some video processing" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": { 84 | "deletable": true, 85 | "editable": true 86 | }, 87 | "source": [ 88 | "## Coding exercise 1\n", 89 | "Make your webcam image greyscale, and view that in the webcam viewer\n", 90 | "\n", 91 | "## Coding exercise 2\n", 92 | "Run a face detector on your grey webcam image, and draw the output as rectangles" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": { 98 | "deletable": true, 99 | "editable": true 100 | }, 101 | "source": [ 102 | "## Coding exercise 3: motion detection\n", 103 | "\n", 104 | "Exercise 3 is a little more challenging and involves motion detection. We're going to do this the simplest way which is to keep a moving average of the colour in each frame, and then compare that to the current frame.\n", 105 | "\n", 106 | "### 3a: setting up our constants\n", 107 | "\n", 108 | "Methods often have parameters, and these can be set outside the main video loop. The parameters we're going to set are fbuffer which is a variable for the number of frames in our buffer. We'll start with 15, this means that if something is still for 15 frames it will disappear into the background. alpha is the update rate for our background model and is a function of fbuffer. difference_thresh is the amount of difference from the background model that we're willing to accept before saying \"*actually that object is moving*\".\n", 109 | "\n", 110 | "The final thing we set up is our actual moving average model, which is a variable called \"movingaverage\" the same size as the images we're getting, initialised with the first image (img).\n", 111 | "\n", 112 | "```\n", 113 | "fbuffer=15\n", 114 | "alpha=float(1.0/fbuffer) \n", 115 | "difference_thresh=10\n", 116 | "movingaverage=np.float32(img)\n", 117 | "```\n", 118 | "\n", 119 | "\n", 120 | "Copy these into the start.py file, outside of the main video loop.\n", 121 | "\n", 122 | "### 3b: looking at the moving average model\n", 123 | "\n", 124 | "\n", 125 | "Inside the video loop, we want to take each frame and update our moving average model. This is just one line of code in OpenCV (the first of the lines below) but we also want to take a look at it so we'll convert the scale so it'll show nicely as an image, and we'll copy the result to output image. \n", 126 | "\n", 127 | "```\n", 128 | " cv2.accumulateWeighted(img,movingaverage,alpha) \n", 129 | " res=cv2.convertScaleAbs(movingaverage)\n", 130 | " # show the background model \n", 131 | " output_image=res.copy() \n", 132 | "```\n", 133 | "Add these to the file (before the facedetect section - we don't want to incorporate the face rectangles into our background model!) and take a look at the background model. \n", 134 | "\n", 135 | "Experiment with different values of fbuffer\n", 136 | "\n", 137 | "### 3c: looking at the difference image\n", 138 | "\n", 139 | "Take the absolute difference between the current image (img) and the scaled background image result (res): this is the simplest measure of motion at the pixel level. Try looking at that in the output window.\n", 140 | "\n", 141 | "```\n", 142 | " difference_img = cv2.absdiff(res, img)\n", 143 | " output_image=difference_img.copy() \n", 144 | "``` \n", 145 | "Again, experiment with different values of fbuffer to see what kinds of motion are detected.\n", 146 | "\n", 147 | "### 3d: convert the difference image to a binary (moving or not-moving) decision\n", 148 | "\n", 149 | "The difference image is in colour: first we'll convert it to greyscale in order to have it as a single channel. You know how to do this.\n", 150 | "\n", 151 | "Once we have a greyscale difference image, we need to threshold it to get a motion mask. \n", 152 | "\n", 153 | "```\n", 154 | " ret,motionmask = cv2.threshold(grey_difference_img,difference_thresh,255,cv2.THRESH_BINARY)\n", 155 | " output_image=motionmask.copy() \n", 156 | "```\n", 157 | "The threshold function takes the variable \"difference_thresh\" which we declared at the start in 3a... Experiment with different values of difference_thresh to find out what works best in this situation" 158 | ] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": { 163 | "deletable": true, 164 | "editable": true 165 | }, 166 | "source": [ 167 | "## Coding exercise 4\n", 168 | "\n", 169 | "Combine the outputs of the background subtractor and the face detector in the visualisation window: the easiest way to do this is to make the motion mask a colour image and then draw the detected faces on that. \n", 170 | "\n", 171 | "### 4a convert the colourspace of the motion mask\n", 172 | "\n", 173 | "```\n", 174 | " motionmask_visualisation= cv2.cvtColor(motionmask, cv2.COLOR_GRAY2BGR)\n", 175 | "```\n", 176 | "is a way of creating a colour version of your motion mask (which will at the current time still be black and white, obviously, as you've not drawn any colour on it yet). You want to do this just after the motion mask is created.\n", 177 | "\n", 178 | "### 4b copy the face detections from the input image to the motion mask\n", 179 | "\n", 180 | "If you look at the image fundamentals tutorial you can see how to create a little image (call it faceimage) which is a subpart of another image, and then you know how to copy that little image to a named position in a bigger image. That's basically what you need to do now. You can do this in the facedetect loop where you are currently drawing blue squares - either as well as the squares, or instead of." 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": { 186 | "deletable": true, 187 | "editable": true 188 | }, 189 | "source": [ 190 | "## Coding exercise 5\n", 191 | "\n", 192 | "There's probably some tiny foreground detections and some noise going on in your motion detection. \n", 193 | "\n", 194 | "Try smoothing (noise reduction) with a Gaussian. Remember you'll need to smooth your image before you add it to the background model, and you'll need to build the model based upon the smoothed version (otherwise you'll be calculating the difference between the input and a Gaussian smoothed input)." 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": { 200 | "deletable": true, 201 | "editable": true 202 | }, 203 | "source": [ 204 | "## Additional coding exercises\n", 205 | "\n", 206 | "1. Use connected components to find large foreground objects\n", 207 | "[ http://stackoverflow.com/questions/35854197/how-to-use-opencvs-connected-components-with-stats-in-python ] \n", 208 | "2. Take the connected components bounding box and the face bounding box and work out left-of and right-of relations\n", 209 | "3. Take a look at some of the trackers you can find in the OpenCV python samples. In particular look at Mosse tracker and Camshift tracker. You should be able to run these, although the initialisation might be an issue (you may need to click to initialise). \n" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": null, 215 | "metadata": { 216 | "collapsed": true, 217 | "deletable": true, 218 | "editable": true 219 | }, 220 | "outputs": [], 221 | "source": [] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "[Previous](5%20detecting%20faces%20and%20other%20things.ipynb)" 228 | ] 229 | } 230 | ], 231 | "metadata": { 232 | "kernelspec": { 233 | "display_name": "Python 3", 234 | "language": "python", 235 | "name": "python3" 236 | }, 237 | "language_info": { 238 | "codemirror_mode": { 239 | "name": "ipython", 240 | "version": 3 241 | }, 242 | "file_extension": ".py", 243 | "mimetype": "text/x-python", 244 | "name": "python", 245 | "nbconvert_exporter": "python", 246 | "pygments_lexer": "ipython3", 247 | "version": "3.6.0" 248 | } 249 | }, 250 | "nbformat": 4, 251 | "nbformat_minor": 0 252 | } 253 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Hannah 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opencv-gettingstarted 2 | 3 | This is a tutorial on OpenCV initially written for the HCC Summer School in 4 | Bremen: [http://hcc.uni-bremen.de/school2016/] 5 | 6 | The target audience is broad and includes 7 | 8 | * People who have done computer science (maybe to graduate level) but who have not looked at OpenCV before 9 | * People who are studying other subjects and want to play with computer vision 10 | 11 | For those with computing experience, you can view this as a set of examples and 12 | code snippets to take and modify; it probably doesn't really matter what order 13 | you do things in. 14 | 15 | For those without computing expertise, try following the notebooks 16 | sequentially. This should take you through the basics of opening images, 17 | modifying images, and doing some straightforward image operations. 18 | -------------------------------------------------------------------------------- /cheat.py: -------------------------------------------------------------------------------- 1 | 2 | # these imports let you use opencv 3 | import cv2 #opencv itself 4 | import common #some useful opencv functions 5 | import video # some video stuff 6 | import numpy as np # matrix manipulations 7 | 8 | cap = video.create_capture(0) 9 | flag, img = cap.read() 10 | n=0; #let us have a counter 11 | flag, img = cap.read() # get an initial frame 12 | cv2.namedWindow('outputwindow') # open a window for output 13 | cv2.imshow('outputwindow',img) # put the image in the output window 14 | 15 | 16 | # exercise 3a 17 | fbuffer=35 18 | alpha=float(1.0/fbuffer) 19 | difference_thresh=10 20 | movingaverage=np.float32(img) 21 | 22 | while True: 23 | 24 | #read a frame from the video capture obj 25 | flag, img = cap.read() 26 | 27 | # exercise 3b: 28 | cv2.accumulateWeighted(img,movingaverage,alpha) 29 | res=cv2.convertScaleAbs(movingaverage) 30 | # show the background model 31 | #output_image=res.copy() 32 | 33 | # exercise 3c: 34 | difference_img = cv2.absdiff(res, img) 35 | #output_image=difference_img.copy() 36 | 37 | #exercise 3d: 38 | grey_difference_img = cv2.cvtColor(difference_img, cv2.COLOR_BGR2GRAY) 39 | ret,motionmask = cv2.threshold(grey_difference_img,difference_thresh,255,cv2.THRESH_BINARY) 40 | #exercise 4a 41 | motionmask_visualisation= cv2.cvtColor(motionmask, cv2.COLOR_GRAY2BGR) 42 | output_image=motionmask_visualisation.copy() 43 | # exercise 1: make it grey 44 | 45 | grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 46 | # exercise 2: import haar cascade, detect faces 47 | face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 48 | faces = face_cascade.detectMultiScale(grey, 1.2, 2) 49 | for (x,y,w,h) in faces: 50 | print "found a face" 51 | cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) 52 | # exercise 4b 53 | cv2.rectangle(motionmask_visualisation,(x,y),(x+w,y+h),(255,0,0),2) 54 | faceregion=img[y:y+h,x:x+w] 55 | motionmask_visualisation[y:y+h,x:x+w]=faceregion 56 | # remember to change this line so you're visualising the right one 57 | output_image=motionmask_visualisation.copy() 58 | cv2.imshow('outputwindow',output_image) # put the image in the output window 59 | 60 | # wait for someone to press escape then destroy the output window 61 | if cv2.waitKey(2) & 0xff == 27: 62 | cv2.destroyAllWindows() 63 | break 64 | print "Finished frame {}".format(n) 65 | n=n+1 66 | 67 | -------------------------------------------------------------------------------- /common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | This module contais some common routines used by other samples. 5 | ''' 6 | 7 | import numpy as np 8 | import cv2 9 | import os 10 | from contextlib import contextmanager 11 | import itertools as it 12 | 13 | image_extensions = ['.bmp', '.jpg', '.jpeg', '.png', '.tif', '.tiff', '.pbm', '.pgm', '.ppm'] 14 | 15 | class Bunch(object): 16 | def __init__(self, **kw): 17 | self.__dict__.update(kw) 18 | def __str__(self): 19 | return str(self.__dict__) 20 | 21 | def splitfn(fn): 22 | path, fn = os.path.split(fn) 23 | name, ext = os.path.splitext(fn) 24 | return path, name, ext 25 | 26 | def anorm2(a): 27 | return (a*a).sum(-1) 28 | def anorm(a): 29 | return np.sqrt( anorm2(a) ) 30 | 31 | def homotrans(H, x, y): 32 | xs = H[0, 0]*x + H[0, 1]*y + H[0, 2] 33 | ys = H[1, 0]*x + H[1, 1]*y + H[1, 2] 34 | s = H[2, 0]*x + H[2, 1]*y + H[2, 2] 35 | return xs/s, ys/s 36 | 37 | def to_rect(a): 38 | a = np.ravel(a) 39 | if len(a) == 2: 40 | a = (0, 0, a[0], a[1]) 41 | return np.array(a, np.float64).reshape(2, 2) 42 | 43 | def rect2rect_mtx(src, dst): 44 | src, dst = to_rect(src), to_rect(dst) 45 | cx, cy = (dst[1] - dst[0]) / (src[1] - src[0]) 46 | tx, ty = dst[0] - src[0] * (cx, cy) 47 | M = np.float64([[ cx, 0, tx], 48 | [ 0, cy, ty], 49 | [ 0, 0, 1]]) 50 | return M 51 | 52 | 53 | def lookat(eye, target, up = (0, 0, 1)): 54 | fwd = np.asarray(target, np.float64) - eye 55 | fwd /= anorm(fwd) 56 | right = np.cross(fwd, up) 57 | right /= anorm(right) 58 | down = np.cross(fwd, right) 59 | R = np.float64([right, down, fwd]) 60 | tvec = -np.dot(R, eye) 61 | return R, tvec 62 | 63 | def mtx2rvec(R): 64 | w, u, vt = cv2.SVDecomp(R - np.eye(3)) 65 | p = vt[0] + u[:,0]*w[0] # same as np.dot(R, vt[0]) 66 | c = np.dot(vt[0], p) 67 | s = np.dot(vt[1], p) 68 | axis = np.cross(vt[0], vt[1]) 69 | return axis * np.arctan2(s, c) 70 | 71 | def draw_str(dst, (x, y), s): 72 | cv2.putText(dst, s, (x+1, y+1), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 0), thickness = 2, lineType=cv2.CV_AA) 73 | cv2.putText(dst, s, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255), lineType=cv2.CV_AA) 74 | 75 | class Sketcher: 76 | def __init__(self, windowname, dests, colors_func): 77 | self.prev_pt = None 78 | self.windowname = windowname 79 | self.dests = dests 80 | self.colors_func = colors_func 81 | self.dirty = False 82 | self.show() 83 | cv2.setMouseCallback(self.windowname, self.on_mouse) 84 | 85 | def show(self): 86 | cv2.imshow(self.windowname, self.dests[0]) 87 | 88 | def on_mouse(self, event, x, y, flags, param): 89 | pt = (x, y) 90 | if event == cv2.EVENT_LBUTTONDOWN: 91 | self.prev_pt = pt 92 | if self.prev_pt and flags & cv2.EVENT_FLAG_LBUTTON: 93 | for dst, color in zip(self.dests, self.colors_func()): 94 | cv2.line(dst, self.prev_pt, pt, color, 5) 95 | self.dirty = True 96 | self.prev_pt = pt 97 | self.show() 98 | else: 99 | self.prev_pt = None 100 | 101 | 102 | # palette data from matplotlib/_cm.py 103 | _jet_data = {'red': ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89,1, 1), 104 | (1, 0.5, 0.5)), 105 | 'green': ((0., 0, 0), (0.125,0, 0), (0.375,1, 1), (0.64,1, 1), 106 | (0.91,0,0), (1, 0, 0)), 107 | 'blue': ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65,0, 0), 108 | (1, 0, 0))} 109 | 110 | cmap_data = { 'jet' : _jet_data } 111 | 112 | def make_cmap(name, n=256): 113 | data = cmap_data[name] 114 | xs = np.linspace(0.0, 1.0, n) 115 | channels = [] 116 | eps = 1e-6 117 | for ch_name in ['blue', 'green', 'red']: 118 | ch_data = data[ch_name] 119 | xp, yp = [], [] 120 | for x, y1, y2 in ch_data: 121 | xp += [x, x+eps] 122 | yp += [y1, y2] 123 | ch = np.interp(xs, xp, yp) 124 | channels.append(ch) 125 | return np.uint8(np.array(channels).T*255) 126 | 127 | def nothing(*arg, **kw): 128 | pass 129 | 130 | def clock(): 131 | return cv2.getTickCount() / cv2.getTickFrequency() 132 | 133 | @contextmanager 134 | def Timer(msg): 135 | print msg, '...', 136 | start = clock() 137 | try: 138 | yield 139 | finally: 140 | print "%.2f ms" % ((clock()-start)*1000) 141 | 142 | class StatValue: 143 | def __init__(self, smooth_coef = 0.5): 144 | self.value = None 145 | self.smooth_coef = smooth_coef 146 | def update(self, v): 147 | if self.value is None: 148 | self.value = v 149 | else: 150 | c = self.smooth_coef 151 | self.value = c * self.value + (1.0-c) * v 152 | 153 | class RectSelector: 154 | def __init__(self, win, callback): 155 | self.win = win 156 | self.callback = callback 157 | cv2.setMouseCallback(win, self.onmouse) 158 | self.drag_start = None 159 | self.drag_rect = None 160 | self.boo=False 161 | def onmouse(self, event, x, y, flags, param): 162 | x, y = np.int16([x, y]) # BUG 163 | if (self.boo): 164 | if event == cv2.EVENT_LBUTTONDOWN: 165 | print "click2boo" 166 | print x,y 167 | print self.drag_start 168 | xo, yo = self.drag_start 169 | x0, y0 = np.minimum([xo, yo], [x, y]) 170 | x1, y1 = np.maximum([xo, yo], [x, y]) 171 | self.drag_rect = None 172 | if x1-x0 > 0 and y1-y0 > 0: 173 | self.drag_rect = (x0, y0, x1, y1) 174 | print "got a rect" 175 | rect = self.drag_rect 176 | self.drag_start = None 177 | self.drag_rect = None 178 | if rect: 179 | self.callback(rect) 180 | self.boo=False 181 | elif event == cv2.EVENT_LBUTTONDOWN: 182 | print "click1" 183 | self.drag_start = (x, y) 184 | print self.drag_start 185 | self.boo=True 186 | def draw(self, vis): 187 | if not self.drag_rect: 188 | return False 189 | x0, y0, x1, y1 = self.drag_rect 190 | cv2.rectangle(vis, (x0, y0), (x1, y1), (0, 255, 0), 2) 191 | return True 192 | @property 193 | def dragging(self): 194 | return self.drag_rect is not None 195 | 196 | 197 | def grouper(n, iterable, fillvalue=None): 198 | '''grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx''' 199 | args = [iter(iterable)] * n 200 | return it.izip_longest(fillvalue=fillvalue, *args) 201 | 202 | def mosaic(w, imgs): 203 | '''Make a grid from images. 204 | 205 | w -- number of grid columns 206 | imgs -- images (must have same size and format) 207 | ''' 208 | imgs = iter(imgs) 209 | img0 = imgs.next() 210 | pad = np.zeros_like(img0) 211 | imgs = it.chain([img0], imgs) 212 | rows = grouper(w, imgs, pad) 213 | return np.vstack(map(np.hstack, rows)) 214 | 215 | def getsize(img): 216 | h, w = img.shape[:2] 217 | return w, h 218 | 219 | def mdot(*args): 220 | return reduce(np.dot, args) 221 | 222 | def draw_keypoints(vis, keypoints, color = (0, 255, 255)): 223 | for kp in keypoints: 224 | x, y = kp.pt 225 | cv2.circle(vis, (int(x), int(y)), 2, color) 226 | -------------------------------------------------------------------------------- /common.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handee/opencv-gettingstarted/01fce491be83545a75fb0f50019a798419fc4ac8/common.pyc -------------------------------------------------------------------------------- /edgedemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handee/opencv-gettingstarted/01fce491be83545a75fb0f50019a798419fc4ac8/edgedemo.png -------------------------------------------------------------------------------- /noidea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handee/opencv-gettingstarted/01fce491be83545a75fb0f50019a798419fc4ac8/noidea.jpg -------------------------------------------------------------------------------- /play.py: -------------------------------------------------------------------------------- 1 | # these imports let you use opencv 2 | import cv2 #opencv itself 3 | import common #some useful opencv functions 4 | import video # some video stuff 5 | import numpy as np # matrix manipulations 6 | 7 | img=cv2.imread('noidea.jpg') 8 | cv2.namedWindow('outputwindow') # open a window for output 9 | 10 | # the line below just copies the input image to the output image. 11 | # try replacing it with some code from the tutorial 12 | output_image=img.copy() 13 | 14 | 15 | cv2.imshow('outputwindow',output_image) # put the image in the output window 16 | 17 | # wait for someone to press escape then destroy the output window 18 | if cv2.waitKey(0) & 0xff == 27: 19 | cv2.destroyAllWindows() 20 | 21 | -------------------------------------------------------------------------------- /start.py: -------------------------------------------------------------------------------- 1 | # these imports let you use opencv 2 | import cv2 #opencv itself 3 | import common #some useful opencv functions 4 | import video # some video stuff 5 | import numpy as np # matrix manipulations 6 | 7 | cap = video.create_capture(0) 8 | n=0; #let us have a counter 9 | flag, img = cap.read() # get an initial frame 10 | cv2.namedWindow('outputwindow') # open a window for output 11 | cv2.imshow('outputwindow',img) # put the image in the output window 12 | 13 | while True: 14 | 15 | #read a frame from the video capture obj 16 | flag, img = cap.read() 17 | 18 | # the line below just copies the input image to the output image. 19 | # try replacing it with some code from the tutorial 20 | output_image=img.copy() 21 | 22 | cv2.imshow('outputwindow',output_image) # put the image in the output window 23 | 24 | # wait for someone to press escape then destroy the output window 25 | if cv2.waitKey(2) & 0xff == 27: 26 | cv2.destroyAllWindows() 27 | break 28 | print "Finished frame {}".format(n) 29 | n=n+1 30 | 31 | -------------------------------------------------------------------------------- /test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handee/opencv-gettingstarted/01fce491be83545a75fb0f50019a798419fc4ac8/test.jpg -------------------------------------------------------------------------------- /video.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | Video capture sample. 5 | 6 | Sample shows how VideoCapture class can be used to acquire video 7 | frames from a camera of a movie file. Also the sample provides 8 | an example of procedural video generation by an object, mimicking 9 | the VideoCapture interface (see Chess class). 10 | 11 | 'create_capture' is a convinience function for capture creation, 12 | falling back to procedural video in case of error. 13 | 14 | Usage: 15 | video.py [--shotdir ] [source0] [source1] ...' 16 | 17 | sourceN is an 18 | - integer number for camera capture 19 | - name of video file 20 | - synth: for procedural video 21 | 22 | Synth examples: 23 | synth:bg=../cpp/lena.jpg:noise=0.1 24 | synth:class=chess:bg=../cpp/lena.jpg:noise=0.1:size=640x480 25 | 26 | Keys: 27 | ESC - exit 28 | SPACE - save current frame to directory 29 | 30 | ''' 31 | 32 | import numpy as np 33 | import cv2 34 | from time import clock 35 | from numpy import pi, sin, cos 36 | import common 37 | 38 | class VideoSynthBase(object): 39 | def __init__(self, size=None, noise=0.0, bg = None, **params): 40 | self.bg = None 41 | self.frame_size = (640, 480) 42 | if bg is not None: 43 | self.bg = cv2.imread(bg, 1) 44 | h, w = self.bg.shape[:2] 45 | self.frame_size = (w, h) 46 | 47 | if size is not None: 48 | w, h = map(int, size.split('x')) 49 | self.frame_size = (w, h) 50 | self.bg = cv2.resize(self.bg, self.frame_size) 51 | 52 | self.noise = float(noise) 53 | 54 | def render(self, dst): 55 | pass 56 | 57 | def read(self, dst=None): 58 | w, h = self.frame_size 59 | 60 | if self.bg is None: 61 | buf = np.zeros((h, w, 3), np.uint8) 62 | else: 63 | buf = self.bg.copy() 64 | 65 | self.render(buf) 66 | 67 | if self.noise > 0.0: 68 | noise = np.zeros((h, w, 3), np.int8) 69 | cv2.randn(noise, np.zeros(3), np.ones(3)*255*self.noise) 70 | buf = cv2.add(buf, noise, dtype=cv2.CV_8UC3) 71 | return True, buf 72 | 73 | def isOpened(self): 74 | return True 75 | 76 | class Chess(VideoSynthBase): 77 | def __init__(self, **kw): 78 | super(Chess, self).__init__(**kw) 79 | 80 | w, h = self.frame_size 81 | 82 | self.grid_size = sx, sy = 10, 7 83 | white_quads = [] 84 | black_quads = [] 85 | for i, j in np.ndindex(sy, sx): 86 | q = [[j, i, 0], [j+1, i, 0], [j+1, i+1, 0], [j, i+1, 0]] 87 | [white_quads, black_quads][(i + j) % 2].append(q) 88 | self.white_quads = np.float32(white_quads) 89 | self.black_quads = np.float32(black_quads) 90 | 91 | fx = 0.9 92 | self.K = np.float64([[fx*w, 0, 0.5*(w-1)], 93 | [0, fx*w, 0.5*(h-1)], 94 | [0.0,0.0, 1.0]]) 95 | 96 | self.dist_coef = np.float64([-0.2, 0.1, 0, 0]) 97 | self.t = 0 98 | 99 | def draw_quads(self, img, quads, color = (0, 255, 0)): 100 | img_quads = cv2.projectPoints(quads.reshape(-1, 3), self.rvec, self.tvec, self.K, self.dist_coef) [0] 101 | img_quads.shape = quads.shape[:2] + (2,) 102 | for q in img_quads: 103 | cv2.fillConvexPoly(img, np.int32(q*4), color, cv2.CV_AA, shift=2) 104 | 105 | def render(self, dst): 106 | t = self.t 107 | self.t += 1.0/30.0 108 | 109 | sx, sy = self.grid_size 110 | center = np.array([0.5*sx, 0.5*sy, 0.0]) 111 | phi = pi/3 + sin(t*3)*pi/8 112 | c, s = cos(phi), sin(phi) 113 | ofs = np.array([sin(1.2*t), cos(1.8*t), 0]) * sx * 0.2 114 | eye_pos = center + np.array([cos(t)*c, sin(t)*c, s]) * 15.0 + ofs 115 | target_pos = center + ofs 116 | 117 | R, self.tvec = common.lookat(eye_pos, target_pos) 118 | self.rvec = common.mtx2rvec(R) 119 | 120 | self.draw_quads(dst, self.white_quads, (245, 245, 245)) 121 | self.draw_quads(dst, self.black_quads, (10, 10, 10)) 122 | 123 | 124 | classes = dict(chess=Chess) 125 | 126 | presets = dict( 127 | empty = 'synth:', 128 | lena = 'synth:bg=../cpp/lena.jpg:noise=0.1', 129 | chess = 'synth:class=chess:bg=../cpp/lena.jpg:noise=0.1:size=640x480' 130 | ) 131 | 132 | 133 | def create_capture(source = 0, fallback = presets['chess']): 134 | '''source: or '||synth [:= [:...]]' 135 | ''' 136 | source = str(source).strip() 137 | chunks = source.split(':') 138 | # hanlde drive letter ('c:', ...) 139 | if len(chunks) > 1 and len(chunks[0]) == 1 and chunks[0].isalpha(): 140 | chunks[1] = chunks[0] + ':' + chunks[1] 141 | del chunks[0] 142 | 143 | source = chunks[0] 144 | try: source = int(source) 145 | except ValueError: pass 146 | params = dict( s.split('=') for s in chunks[1:] ) 147 | 148 | cap = None 149 | if source == 'synth': 150 | Class = classes.get(params.get('class', None), VideoSynthBase) 151 | try: cap = Class(**params) 152 | except: pass 153 | else: 154 | cap = cv2.VideoCapture(source) 155 | if 'size' in params: 156 | w, h = map(int, params['size'].split('x')) 157 | cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, w) 158 | cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, h) 159 | if cap is None or not cap.isOpened(): 160 | print 'Warning: unable to open video source: ', source 161 | if fallback is not None: 162 | return create_capture(fallback, None) 163 | return cap 164 | 165 | if __name__ == '__main__': 166 | import sys 167 | import getopt 168 | 169 | print __doc__ 170 | 171 | args, sources = getopt.getopt(sys.argv[1:], '', 'shotdir=') 172 | args = dict(args) 173 | shotdir = args.get('--shotdir', '.') 174 | if len(sources) == 0: 175 | sources = [ 0 ] 176 | 177 | caps = map(create_capture, sources) 178 | shot_idx = 0 179 | while True: 180 | imgs = [] 181 | for i, cap in enumerate(caps): 182 | ret, img = cap.read() 183 | imgs.append(img) 184 | cv2.imshow('capture %d' % i, img) 185 | ch = 0xFF & cv2.waitKey(1) 186 | if ch == 27: 187 | break 188 | if ch == ord(' '): 189 | for i, img in enumerate(imgs): 190 | fn = '%s/shot_%d_%03d.bmp' % (shotdir, i, shot_idx) 191 | cv2.imwrite(fn, img) 192 | print fn, 'saved' 193 | shot_idx += 1 194 | cv2.destroyAllWindows() 195 | -------------------------------------------------------------------------------- /video.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handee/opencv-gettingstarted/01fce491be83545a75fb0f50019a798419fc4ac8/video.pyc --------------------------------------------------------------------------------