├── .gitignore ├── README.md ├── SIFT_filterMatches_homography ├── Makefile ├── Project.xcconfig ├── SIFT_filterMatches_homography.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── SIFT_filterMatches_homography Debug.xcscheme │ │ └── SIFT_filterMatches_homography Release.xcscheme ├── addons.make ├── bin │ └── data │ │ ├── .gitkeep │ │ ├── peeping_tom_crop1-3d.jpg │ │ ├── peeping_tom_crop1.jpg │ │ ├── peeping_tom_crop2-3d.jpg │ │ ├── peeping_tom_crop2.jpg │ │ └── peeping_tom_scene.jpg ├── config.make ├── openFrameworks-Info.plist └── src │ ├── SIFTMatcher.cpp │ ├── SIFTMatcher.hpp │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── SIFTtest ├── Makefile ├── Project.xcconfig ├── SIFTtest.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── SIFTtest Debug.xcscheme │ │ └── SIFTtest Release.xcscheme ├── addons.make ├── bin │ └── data │ │ ├── .gitkeep │ │ ├── peeping_tom_1.jpg │ │ ├── peeping_tom_1_3d.jpg │ │ └── peeping_tom_2.jpg ├── config.make ├── openFrameworks-Info.plist └── src │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── griddedHistogram ├── Makefile ├── Project.xcconfig ├── addons.make ├── bin │ └── data │ │ ├── .gitkeep │ │ ├── grid.png │ │ └── img.jpg ├── config.make ├── griddedHistogram.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── griddedHistogram Debug.xcscheme │ │ └── griddedHistogram Release.xcscheme ├── openFrameworks-Info.plist └── src │ ├── Histogrid.cpp │ ├── Histogrid.hpp │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h └── optFlowTest ├── Makefile ├── Project.xcconfig ├── addons.make ├── bin └── data │ ├── .gitkeep │ ├── rearWindow_clip_1-240p.mp4 │ └── rearWindow_clip_1.mp4 ├── config.make ├── openFrameworks-Info.plist ├── optFlowTest.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── optFlowTest Debug.xcscheme │ └── optFlowTest Release.xcscheme └── src ├── main.cpp ├── ofApp.cpp └── ofApp.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Some general ignore patterns 2 | build/ 3 | obj/ 4 | *.o 5 | Debug*/ 6 | Release*/ 7 | *.mode* 8 | *.app/ 9 | *.pyc 10 | .svn/ 11 | 12 | 13 | #XCode 14 | *.pbxuser 15 | *.perspective 16 | *.perspectivev3 17 | *.mode1v3 18 | *.mode2v3 19 | #XCode 4 20 | xcuserdata 21 | *.xcworkspace 22 | 23 | #Code::Blocks 24 | *.depend 25 | *.layout 26 | 27 | #Visual Studio 28 | *.sdf 29 | *.opensdf 30 | *.suo 31 | ipch/ 32 | 33 | #Eclipse 34 | .metadata 35 | local.properties 36 | .externalToolBuilders 37 | 38 | 39 | # OS-specific ignore patterns 40 | 41 | #Linux 42 | *~ 43 | # KDE 44 | .directory 45 | 46 | #OSX 47 | .DS_Store 48 | *.swp 49 | *~.nib 50 | # Thumbnails 51 | ._* 52 | 53 | #Windows 54 | # Windows image file caches 55 | Thumbs.db 56 | # Folder config file 57 | Desktop.ini 58 | 59 | #Android 60 | .csettings 61 | /libs/openFrameworksCompiled/project/android/paths.make 62 | 63 | # Miscellaneous 64 | .mailmap -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenCV oF Experiments 2 | 3 | Code experiments related to computer vision & cinema posts on my [blog](http://www.tylerhenry.com/category/computervision/) at [tylerhenry.com](http://tylerhenry.com). 4 | Mostly using OpenCV and openFrameworks. 5 | 6 | --- 7 | 8 | ### griddedHistogram 9 | 10 | Contains Histogrid class: uses OpenCV calcHist to generate histograms for subsections of an ofImage. 11 | Written in openFrameworks v.9.0 / XCode 7 12 | 13 | *uses addons:* [`ofxCv`](https://github.com/kylemcdonald/ofxCv/) and `ofxOpenCv` 14 | 15 | ![Hisogrid sample output](http://i1.wp.com/www.tylerhenry.com/site/wp-content/uploads/2016/03/histogrid_sample.jpg) 16 | 17 | 18 | ### SIFT_filterMatches_homography 19 | 20 | Updated, more complete SIFT implementation than SIFTtest (see below). 21 | Written in openFrameworks v.9.0 / XCode 7 22 | 23 | *uses addons:* [`ofxCv`](https://github.com/kylemcdonald/ofxCv/) and `ofxOpenCv` 24 | 25 | **Related tutorial** 26 | 27 | [SIFT Implementation in OpenFrameworks, Part 3](http://www.tylerhenry.com/sift-implementation-in-openframeworks-part-3/) 28 | 29 | Updates over SIFTtest: 30 | 31 | * SIFT implementation placed inside SIFTMatcher class 32 | * added keypoint filter to sort out good keypoint matches 33 | * added homography transformation to 34 | calculate 3D warp of query image to train img 35 | 36 | ![SIFT_filterMatches_homography sample output](http://i1.wp.com/www.tylerhenry.com/site/wp-content/uploads/2016/03/SIFT_v2_test1.jpg?resize=1024%2C501) 37 | 38 | --- 39 | 40 | ### SIFTtest 41 | First test of SIFT algorithm to match features between two images. 42 | Written in openFrameworks v.9.0 / XCode 7 43 | 44 | *uses addons:* [`ofxCv`](https://github.com/kylemcdonald/ofxCv/) and `ofxOpenCv` 45 | 46 | **Related tutorial** 47 | 48 | [SIFT Implementation in OpenFrameworks, Part 2](http://www.tylerhenry.com/sift-implementation-in-openframeworks-part-2/) 49 | 50 | **Intro tutorials** 51 | 52 | 1. [Getting Started](http://www.tylerhenry.com/getting-started/) 53 | 2. [Finding Features](http://www.tylerhenry.com/finding-features/) 54 | 3. [SIFT Implementation in OpenFrameworks, Part 1](http://www.tylerhenry.com/sift-implementation-in-openframeworks-part-1/) 55 | 56 | ![SIFTtest sample output](http://i2.wp.com/www.tylerhenry.com/site/wp-content/uploads/2016/03/SIFT_test5.jpg?resize=1024%2C490) 57 | 58 | --- 59 | 60 | ### optFlowTest 61 | Test of optical flow analysis using Farneback algorithm from OpenCV (through ofxCv) 62 | Written in openFrameworks v.9.0 / XCode 7 63 | 64 | *uses addons:* [`ofxCv`](https://github.com/kylemcdonald/ofxCv/), `ofxOpenCv` and `ofxGui` 65 | 66 | Display local motion in video as a flow field, and also: 67 | 68 | * average motion per frame (red line in video center) 69 | * average motion per clip (red line on left) 70 | * track of average motion per clip (blue dot and path) 71 | 72 | ** Related tutorial** 73 | 74 | [Optical Flow, Part 1](http://www.tylerhenry.com/optical-flow-part-1/) 75 | 76 | [![optFlowtest sample output](http://i1.wp.com/www.tylerhenry.com/site/wp-content/uploads/2016/03/optFlowtest1.jpg)](https://www.youtube.com/watch?v=09hFXvW_NMs) 77 | [YouTube sample](https://www.youtube.com/watch?v=09hFXvW_NMs) -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/Makefile: -------------------------------------------------------------------------------- 1 | # Attempt to load a config.make file. 2 | # If none is found, project defaults in config.project.make will be used. 3 | ifneq ($(wildcard config.make),) 4 | include config.make 5 | endif 6 | 7 | # make sure the the OF_ROOT location is defined 8 | ifndef OF_ROOT 9 | OF_ROOT=$(realpath ../../..) 10 | endif 11 | 12 | # call the project makefile! 13 | include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk 14 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 17 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 18 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/SIFT_filterMatches_homography.xcodeproj/xcshareddata/xcschemes/SIFT_filterMatches_homography Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/SIFT_filterMatches_homography.xcodeproj/xcshareddata/xcschemes/SIFT_filterMatches_homography Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/addons.make: -------------------------------------------------------------------------------- 1 | ofxCv 2 | ofxOpenCv 3 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/bin/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFT_filterMatches_homography/bin/data/.gitkeep -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/bin/data/peeping_tom_crop1-3d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFT_filterMatches_homography/bin/data/peeping_tom_crop1-3d.jpg -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/bin/data/peeping_tom_crop1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFT_filterMatches_homography/bin/data/peeping_tom_crop1.jpg -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/bin/data/peeping_tom_crop2-3d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFT_filterMatches_homography/bin/data/peeping_tom_crop2-3d.jpg -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/bin/data/peeping_tom_crop2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFT_filterMatches_homography/bin/data/peeping_tom_crop2.jpg -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/bin/data/peeping_tom_scene.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFT_filterMatches_homography/bin/data/peeping_tom_scene.jpg -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/config.make: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # CONFIGURE PROJECT MAKEFILE (optional) 3 | # This file is where we make project specific configurations. 4 | ################################################################################ 5 | 6 | ################################################################################ 7 | # OF ROOT 8 | # The location of your root openFrameworks installation 9 | # (default) OF_ROOT = ../../.. 10 | ################################################################################ 11 | # OF_ROOT = ../../.. 12 | 13 | ################################################################################ 14 | # PROJECT ROOT 15 | # The location of the project - a starting place for searching for files 16 | # (default) PROJECT_ROOT = . (this directory) 17 | # 18 | ################################################################################ 19 | # PROJECT_ROOT = . 20 | 21 | ################################################################################ 22 | # PROJECT SPECIFIC CHECKS 23 | # This is a project defined section to create internal makefile flags to 24 | # conditionally enable or disable the addition of various features within 25 | # this makefile. For instance, if you want to make changes based on whether 26 | # GTK is installed, one might test that here and create a variable to check. 27 | ################################################################################ 28 | # None 29 | 30 | ################################################################################ 31 | # PROJECT EXTERNAL SOURCE PATHS 32 | # These are fully qualified paths that are not within the PROJECT_ROOT folder. 33 | # Like source folders in the PROJECT_ROOT, these paths are subject to 34 | # exlclusion via the PROJECT_EXLCUSIONS list. 35 | # 36 | # (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) 37 | # 38 | # Note: Leave a leading space when adding list items with the += operator 39 | ################################################################################ 40 | # PROJECT_EXTERNAL_SOURCE_PATHS = 41 | 42 | ################################################################################ 43 | # PROJECT EXCLUSIONS 44 | # These makefiles assume that all folders in your current project directory 45 | # and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations 46 | # to look for source code. The any folders or files that match any of the 47 | # items in the PROJECT_EXCLUSIONS list below will be ignored. 48 | # 49 | # Each item in the PROJECT_EXCLUSIONS list will be treated as a complete 50 | # string unless teh user adds a wildcard (%) operator to match subdirectories. 51 | # GNU make only allows one wildcard for matching. The second wildcard (%) is 52 | # treated literally. 53 | # 54 | # (default) PROJECT_EXCLUSIONS = (blank) 55 | # 56 | # Will automatically exclude the following: 57 | # 58 | # $(PROJECT_ROOT)/bin% 59 | # $(PROJECT_ROOT)/obj% 60 | # $(PROJECT_ROOT)/%.xcodeproj 61 | # 62 | # Note: Leave a leading space when adding list items with the += operator 63 | ################################################################################ 64 | # PROJECT_EXCLUSIONS = 65 | 66 | ################################################################################ 67 | # PROJECT LINKER FLAGS 68 | # These flags will be sent to the linker when compiling the executable. 69 | # 70 | # (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs 71 | # 72 | # Note: Leave a leading space when adding list items with the += operator 73 | ################################################################################ 74 | 75 | # Currently, shared libraries that are needed are copied to the 76 | # $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to 77 | # add a runtime path to search for those shared libraries, since they aren't 78 | # incorporated directly into the final executable application binary. 79 | # TODO: should this be a default setting? 80 | # PROJECT_LDFLAGS=-Wl,-rpath=./libs 81 | 82 | ################################################################################ 83 | # PROJECT DEFINES 84 | # Create a space-delimited list of DEFINES. The list will be converted into 85 | # CFLAGS with the "-D" flag later in the makefile. 86 | # 87 | # (default) PROJECT_DEFINES = (blank) 88 | # 89 | # Note: Leave a leading space when adding list items with the += operator 90 | ################################################################################ 91 | # PROJECT_DEFINES = 92 | 93 | ################################################################################ 94 | # PROJECT CFLAGS 95 | # This is a list of fully qualified CFLAGS required when compiling for this 96 | # project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS 97 | # defined in your platform specific core configuration files. These flags are 98 | # presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. 99 | # 100 | # (default) PROJECT_CFLAGS = (blank) 101 | # 102 | # Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in 103 | # your platform specific configuration file will be applied by default and 104 | # further flags here may not be needed. 105 | # 106 | # Note: Leave a leading space when adding list items with the += operator 107 | ################################################################################ 108 | # PROJECT_CFLAGS = 109 | 110 | ################################################################################ 111 | # PROJECT OPTIMIZATION CFLAGS 112 | # These are lists of CFLAGS that are target-specific. While any flags could 113 | # be conditionally added, they are usually limited to optimization flags. 114 | # These flags are added BEFORE the PROJECT_CFLAGS. 115 | # 116 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. 117 | # 118 | # (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) 119 | # 120 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. 121 | # 122 | # (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) 123 | # 124 | # Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the 125 | # PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration 126 | # file will be applied by default and further optimization flags here may not 127 | # be needed. 128 | # 129 | # Note: Leave a leading space when adding list items with the += operator 130 | ################################################################################ 131 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE = 132 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG = 133 | 134 | ################################################################################ 135 | # PROJECT COMPILERS 136 | # Custom compilers can be set for CC and CXX 137 | # (default) PROJECT_CXX = (blank) 138 | # (default) PROJECT_CC = (blank) 139 | # Note: Leave a leading space when adding list items with the += operator 140 | ################################################################################ 141 | # PROJECT_CXX = 142 | # PROJECT_CC = 143 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | cc.openFrameworks.ofapp 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | CFBundleIconFile 20 | ${ICON} 21 | 22 | 23 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/src/SIFTMatcher.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // SIFTMatcher.cpp 3 | // SIFT_filterMatches_homography 4 | // 5 | // Created by Tyler on 3/24/16. 6 | // 7 | // 8 | 9 | #include "SIFTMatcher.hpp" 10 | 11 | 12 | //-------------------------------------------------------------- 13 | // Constructor 14 | //-------------------------------------------------------------- 15 | 16 | // default constructor - blank 17 | SIFTMatcher::SIFTMatcher(){ 18 | } 19 | 20 | 21 | // actual constructor - always use this 22 | SIFTMatcher::SIFTMatcher(ofImage& _findImg, ofImage& _fieldImg){ 23 | 24 | findImg = &_findImg; 25 | fieldImg = &_fieldImg; 26 | 27 | } 28 | 29 | //------------------------------------------------------------------------- 30 | // MATCH 31 | // runs SIFT keypoint detection and feature descriptor on findImg, fieldImg 32 | // then uses cv::BFMatcher to find matches 33 | //------------------------------------------------------------------------- 34 | 35 | void SIFTMatcher::match(){ 36 | 37 | // takes in a query image (findImg) and "train" image (fieldImg) 38 | // returns the matches vector (unfiltered) 39 | 40 | // also references findImg, fieldImg as public findImg, fieldImg 41 | // and saves resulting KeyPoints vectors as public variables 42 | 43 | 44 | uint64_t startTime = ofGetElapsedTimeMillis(); // save start time (in ms) for testing speed 45 | 46 | 47 | //---------------------// 48 | //---- LOAD IMAGES ----// 49 | //---------------------// 50 | 51 | 52 | 53 | // convert to grayscale (SIFT works in grayscale) 54 | 55 | findImg->setImageType(OF_IMAGE_GRAYSCALE); 56 | fieldImg->setImageType(OF_IMAGE_GRAYSCALE); 57 | 58 | 59 | // wrap images with Mat class for use with SIFT 60 | 61 | Mat findMat = toCv(*findImg); 62 | Mat fieldMat = toCv(*fieldImg); 63 | 64 | 65 | // print image load time 66 | // -------------- 67 | uint64_t loadTime = ofGetElapsedTimeMillis() - startTime; // calc image load time 68 | ofLogNotice("siftMatch") << "took " << loadTime << " ms to prep images" << endl; // print load time to console 69 | startTime = ofGetElapsedTimeMillis(); // reset startTime 70 | // -------------- 71 | 72 | 73 | 74 | //------------------------------------// 75 | //---- SIFT DETECTION/DESCRIPTION ----// 76 | //------------------------------------// 77 | 78 | 79 | // --------------------------------------- 80 | // 1. DETECT SIFT keypoints in both images 81 | // --------------------------------------- 82 | 83 | 84 | SiftFeatureDetector detector(2000); // SIFT detector object 85 | /* 86 | // 2000 = max number of keypoints to find 87 | // all optional constructor args, with default values: 88 | // (int nfeatures=0, int nOctaveLayers=3, double contrastThreshold=0.04, 89 | // double edgeThreshold=10, double sigma=1.6); 90 | */ 91 | 92 | 93 | // run the detector on each image 94 | 95 | detector.detect(findMat, findKeypoints); 96 | detector.detect(fieldMat, fieldKeypoints); 97 | 98 | 99 | // print results 100 | // -------------- 101 | uint64_t detectTime = ofGetElapsedTimeMillis() - startTime; // calculate detection time 102 | 103 | // print # keypoints found to console 104 | 105 | ofLogNotice("SIFTMatcher") << "took " << detectTime << " ms to find keypoints" << endl << endl 106 | << " # keypoints found" << endl 107 | << " -----------------" << endl 108 | << " findImg: " << findKeypoints.size() << endl 109 | << " fieldImg: " << fieldKeypoints.size() << endl; 110 | 111 | startTime = ofGetElapsedTimeMillis(); // reset startTime 112 | // -------------- 113 | 114 | 115 | // -------------------------------------- 116 | // 2. DESCRIBE SIFT features of keypoints 117 | // -------------------------------------- 118 | 119 | 120 | SiftDescriptorExtractor extractor; // SIFT descriptor object 121 | 122 | 123 | Mat findDescriptors, fieldDescriptors; // matrices to hold all features per keypoint in image 124 | // i.e. in each matrix, row 'i' is the list of features for keypoint 'i' 125 | 126 | // run the feature description extractor 127 | 128 | extractor.compute(findMat, findKeypoints, findDescriptors); 129 | extractor.compute(fieldMat, fieldKeypoints, fieldDescriptors); 130 | 131 | 132 | // print results 133 | // -------------- 134 | uint64_t describeTime = ofGetElapsedTimeMillis() - startTime; // calculate description time 135 | 136 | // print some statistics on the matrices 137 | 138 | cv::Size findSize = findDescriptors.size(); // size of matrix 139 | cv::Size fieldSize = fieldDescriptors.size(); 140 | 141 | ofLogNotice("SIFTMatcher") << "took " << describeTime << " ms to describe features" << endl << endl 142 | << " findImg feature matrix" << endl 143 | << " ----------------------" << endl 144 | << " height: " << findSize.height << ", width: " << findSize.width << endl 145 | << " area: " << findSize.area() << ", non-zero: " << countNonZero(findDescriptors) << endl 146 | << endl 147 | << " fieldImg feature matrix" << endl 148 | << " -----------------------" << endl 149 | << " height: " << fieldSize.height << ", width: " << fieldSize.width << endl 150 | << " area: " << fieldSize.area() << ", non-zero: " << countNonZero(fieldDescriptors) << endl; 151 | 152 | startTime = ofGetElapsedTimeMillis(); // reset startTime 153 | // -------------- 154 | 155 | 156 | 157 | //---------------------------------// 158 | //---- FIND MATCHING KEYPOINTS ----// 159 | //---------------------------------// 160 | 161 | 162 | BFMatcher matcher(NORM_L1, true); // Brute-force Matcher object 163 | /* 164 | // loops through every feature in matrix 1, comparing it to every feature in matrix 2 165 | // to find best match in matrix 2 166 | 167 | // NORM_L1 is "normType" - use NORM_L1 or NORM_L2 for SIFT. I think this determines the type of normalization done when determining "distance" (in n-dimensional space) between keypoints 168 | // true is crossCheck boolean - this means that BFMatcher will only return a match when both keypoints find each other as their closest match. This should be set to true to produce more reliable matches, but only if you have a lot of keypoints. 169 | // a good visual example of cross-checking is on StackOverflow: http://stackoverflow.com/questions/11181823/why-we-need-crosscheckmatching-for-feature 170 | // see here for BFMatcher reference: http://docs.opencv.org/3.0-last-rst/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html?highlight=bfmatcher#bfmatcher 171 | */ 172 | 173 | // run the matcher 174 | 175 | matcher.match(findDescriptors, fieldDescriptors, matches); 176 | 177 | 178 | // print results 179 | // -------------- 180 | uint64_t matchTime = ofGetElapsedTimeMillis() - startTime; // calculate match time 181 | 182 | ofLogNotice("SIFTMatcher") << "took " << matchTime << " ms to match keypoints" << endl << endl 183 | << " Found " << matches.size() << " matching keypoints" << endl; 184 | // -------------- 185 | 186 | 187 | } 188 | 189 | 190 | //-------------------------------------------------------------- 191 | // FILTER MATCHES 192 | // using distance calculations 193 | //-------------------------------------------------------------- 194 | 195 | void SIFTMatcher::filterMatches(){ 196 | 197 | // code referenced from: 198 | // http://docs.opencv.org/3.1.0/d5/d6f/tutorial_feature_flann_matcher.html 199 | // ----------------------------------------------------------------------- 200 | 201 | uint64_t startTime = ofGetElapsedTimeMillis(); // get start time for speed test 202 | 203 | 204 | // loop through matches to find min and max distances 205 | 206 | double minDist = 100, maxDist = 0; 207 | 208 | for( int i = 0; i < matches.size(); i++ ) { 209 | 210 | double dist = matches[i].distance; // calc distance in n-dim space 211 | 212 | if (dist < minDist) { minDist = dist; } 213 | if (dist > maxDist) { maxDist = dist; } 214 | } 215 | 216 | 217 | // save only "good" matches 218 | // here, threshold at 2 * minDist or 0.3 * maxDist, whichever is larger 219 | // this is fairly arbitrary 220 | 221 | if (goodMatches.size() > 0){ 222 | goodMatches.clear(); // clear the goodMatches vector if it has anything in it 223 | } 224 | 225 | double threshold = max(2 * minDist, 0.3 * maxDist); 226 | 227 | for (int i = 0; i < matches.size(); i++) { 228 | 229 | if (matches[i].distance <= threshold) { 230 | 231 | goodMatches.push_back(matches[i]); // store as good match 232 | } 233 | } 234 | 235 | 236 | // print results 237 | // -------------- 238 | uint64_t filterTime = ofGetElapsedTimeMillis() - startTime; // calculate filter time 239 | 240 | ofLogNotice("SIFTMatcher") << "took " << filterTime << " ms to filter matches" << endl << endl 241 | << " calc\'ed minDist: " << minDist << ", maxDist: " << maxDist << endl 242 | << " used treshold of: " << threshold << endl 243 | << " saved " << goodMatches.size() << " out of " << matches.size() << " total matches" << endl; 244 | // -------------- 245 | 246 | 247 | } 248 | 249 | 250 | //-------------------------------------------------------------------- 251 | // DRAW MATCHES CV 252 | // uses cv::drawMatches() to draw matches visualization into _matchImg 253 | //-------------------------------------------------------------------- 254 | 255 | void SIFTMatcher::drawMatchesCv(ofImage& _matchImg, bool bUseGoodMatches){ 256 | 257 | //----------------------// 258 | //---- DRAW RESULTS ----// 259 | //----------------------// 260 | 261 | /* 262 | // cv::drawMatches() displays the images side by side, 263 | // with colored circles at each keypoint, 264 | // and lines connecting the matched keypoints. 265 | // It draws into a Mat. 266 | */ 267 | 268 | Mat matchMat; // image-matrix to temp store the results visualization 269 | 270 | // draw results visualization into matchMat image-matrix 271 | 272 | // prep findImg and fieldImg as Mat 273 | Mat findMat, fieldMat; 274 | findMat = toCv(*findImg); 275 | fieldMat = toCv(*fieldImg); 276 | 277 | // pointer to matches vector 278 | vector* matchesPtr = &(matches); 279 | 280 | if (bUseGoodMatches){ 281 | matchesPtr = &(goodMatches); // or point to goodMatches vector 282 | } 283 | 284 | drawMatches(findMat, findKeypoints, fieldMat, fieldKeypoints, *matchesPtr, matchMat, 285 | /* and optional parameters: */ 286 | Scalar::all(-1), Scalar::all(170), vector(), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); 287 | /* 288 | // The Scalar::all(-1) through DRAW_RICH_KEYPOINTS parameters are optional. 289 | // I'm copying the default arguments for them, except: 290 | // Scalar(170) which draws the unmatched keypoints in gray 291 | // DRAW_RICH_KEYPOINTS, which draws the size/rotation of the keypoints. 292 | // The default arguments for those would be: 293 | // Scalar::all(-1) for random colors 294 | // cv::DrawMatchesFlags::DEFAULT for drawing all keypoints as little circles. 295 | // see here for drawMatches() reference: http://docs.opencv.org/3.1.0/d4/d5d/group__features2d__draw.html#gsc.tab=0 296 | */ 297 | 298 | // convert matchMat to matchImg 299 | 300 | toOf(matchMat,_matchImg); // wraps matchMat in ofImage matchImg, allocating as needed 301 | _matchImg.update(); // updates the matchImg texture on the GPU 302 | 303 | // now we can draw matchImg in ofApp::draw() 304 | } 305 | 306 | 307 | //---------------------------------------------------------------------------------- 308 | // GET HOMOGRAPHY 309 | // uses cv::findHomography to get transformation values 310 | // between findImg and fieldImg based on matched keypoints 311 | // then transforms findImg corners to match where it is in fieldImg 312 | //---------------------------------------------------------------------------------- 313 | 314 | void SIFTMatcher::getHomography(bool bUseGoodMatches){ 315 | 316 | uint64_t startTime = ofGetElapsedTimeMillis(); // save start time (in ms) for testing speed 317 | 318 | 319 | vector findPts; // Point2f is cv's ofVec2f 320 | vector fieldPts; 321 | 322 | // pointer to matches vector 323 | vector* matchesPtr = &(matches); 324 | 325 | if (bUseGoodMatches){ 326 | matchesPtr = &(goodMatches); // or point to goodMatches vector 327 | } 328 | 329 | for (int i=0; isize(); i++){ 330 | 331 | // get original keypoints based on matches 332 | 333 | int findIndex = (*matchesPtr)[i].queryIdx; // get index in findKeypoints of matched keypoint 334 | int fieldIndex = (*matchesPtr)[i].trainIdx; // get index in fieldKeypoints of matched keypoint 335 | 336 | Point2f& findPt = findKeypoints[findIndex].pt; // get 2D location of findKeypoint 337 | Point2f& fieldPt = fieldKeypoints[fieldIndex].pt; // get 2D location of fieldKeypoint 338 | 339 | // save in vectors 340 | findPts.push_back(findPt); 341 | fieldPts.push_back(fieldPt); 342 | 343 | } 344 | 345 | // calculate homography matrix using RANSAC method 346 | 347 | Mat H = findHomography(findPts, fieldPts, RANSAC); 348 | 349 | // prep findImg and fieldImg as Mats 350 | 351 | Mat findMat = toCv(*findImg); 352 | Mat fieldMat = toCv(*fieldImg); 353 | 354 | // get the image corners of findMat 355 | 356 | vector findMatCorners(4); 357 | findMatCorners[0] = cvPoint(0,0); 358 | findMatCorners[1] = cvPoint( findMat.cols, 0 ); 359 | findMatCorners[2] = cvPoint( findMat.cols, findMat.rows ); 360 | findMatCorners[3] = cvPoint( 0, findMat.rows ); 361 | 362 | // transform findMat corners to correspond with matched keypoints in fieldImg 363 | 364 | vector fieldMatCorners(4); // we'll save the transformed corners here 365 | 366 | perspectiveTransform(findMatCorners, fieldMatCorners, H); // perform transformation using homography matrix 367 | 368 | 369 | // now convert fieldMatCorners to an ofVec2f vector for use in openFrameworks 370 | 371 | fieldCorners.clear(); 372 | for (int i=0; i<4; i++){ 373 | fieldCorners.push_back(toOf(fieldMatCorners[i])); 374 | } 375 | 376 | 377 | 378 | // print results 379 | // -------------- 380 | uint64_t hTime = ofGetElapsedTimeMillis() - startTime; // calculate homography transform time 381 | 382 | ofLogNotice("SIFTMatcher") << "took " << hTime << " ms to do homography transform" << endl << endl 383 | << " x,y corners of findImg in fieldImg" << endl 384 | << " ----------------------------------" << endl 385 | << " " << fieldCorners[0].x << ", " << fieldCorners[0].y << endl 386 | << " " << fieldCorners[1].x << ", " << fieldCorners[1].y << endl 387 | << " " << fieldCorners[2].x << ", " << fieldCorners[2].y << endl 388 | << " " << fieldCorners[3].x << ", " << fieldCorners[3].y << endl; 389 | // -------------- 390 | 391 | } 392 | 393 | 394 | //---------------------------------------------------------------------------------- 395 | // DRAW HOMOGRAPHY 396 | //---------------------------------------------------------------------------------- 397 | 398 | void SIFTMatcher::drawHomography(float xOffset, float yOffset, ofColor color, float lineWidth){ 399 | 400 | ofPushStyle(); 401 | ofSetColor(color); 402 | ofSetLineWidth(lineWidth); 403 | 404 | ofPushMatrix(); 405 | ofTranslate(xOffset,yOffset); 406 | 407 | ofDrawLine(fieldCorners[0],fieldCorners[1]); 408 | ofDrawLine(fieldCorners[1],fieldCorners[2]); 409 | ofDrawLine(fieldCorners[2],fieldCorners[3]); 410 | ofDrawLine(fieldCorners[3],fieldCorners[0]); 411 | 412 | ofPopMatrix(); 413 | ofPopStyle(); 414 | 415 | } 416 | 417 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/src/SIFTMatcher.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // SIFTMatcher.hpp 3 | // SIFT_filterMatches_homography 4 | // 5 | // Created by Tyler on 3/24/16. 6 | // 7 | // 8 | 9 | #pragma once 10 | #include "ofMain.h" 11 | #include "ofxOpenCv.h" 12 | #include "ofxCv.h" 13 | 14 | // include non-free OpenCV modules 15 | #include "opencv2/nonfree/nonfree.hpp" 16 | 17 | using namespace cv; 18 | using namespace ofxCv; 19 | 20 | class SIFTMatcher { 21 | 22 | public: 23 | 24 | SIFTMatcher(); 25 | 26 | SIFTMatcher(ofImage& _findImg, ofImage& _fieldImg); 27 | 28 | void match(); 29 | // returns vector of keypoint matches between "query" image (_findImg) and "train" image (_fieldImg) 30 | 31 | void filterMatches(); 32 | // filters outliers in matches vector based on distance 33 | 34 | void drawMatchesCv(ofImage& _matchImg, bool bUseGoodMatches = false); 35 | // draws match visualization into _matchImg 36 | // bUseGoodMatches draws matches vector if false or goodMatches vector if true 37 | 38 | void getHomography(bool bUseGoodMatches = false); 39 | // calculates homography between matched keypoints 40 | // and transforms corners of findImg to match coordinates in fieldImg 41 | 42 | void drawHomography(float xOffset = 0, float yOffset = 0, ofColor color = ofColor::cyan, float lineWidth = 3); 43 | // draws warped box in fieldImg coordinates of where findImg was found 44 | // x and yOffset draw 45 | 46 | ofImage* findImg; 47 | ofImage* fieldImg; 48 | 49 | vector findKeypoints, fieldKeypoints; 50 | vector matches; 51 | vector goodMatches; 52 | 53 | vector fieldCorners; // stores corners of findImg transformed into fieldImg space 54 | 55 | 56 | }; 57 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | //======================================================================== 5 | int main( ){ 6 | ofSetupOpenGL(1700,720,OF_WINDOW); // <-------- setup the GL context 7 | 8 | // this kicks off the running of my app 9 | // can be OF_WINDOW or OF_FULLSCREEN 10 | // pass in width and height too: 11 | ofRunApp(new ofApp()); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //-------------------------------------------------------------- 4 | void ofApp::setup(){ 5 | 6 | // load the two images as ofImage 7 | 8 | findImg.load("peeping_tom_crop2-3d.jpg"); // image we're looking for (called "query" in OpenCV) 9 | // for findImg here: 10 | // I'm using an image I cropped as a trapezoid from the fieldImg, 11 | // and then warped back to be a square in Photoshop 12 | // (the original crop is "peeping_tom_crop2.jpg") 13 | 14 | fieldImg.load("peeping_tom_scene.jpg"); // image to search in (called "train" in OpenCV) 15 | 16 | // run sift matcher 17 | 18 | siftMatcher = SIFTMatcher(findImg, fieldImg); // construct SIFTMatcher object 19 | 20 | siftMatcher.match(); // find matches 21 | 22 | siftMatcher.filterMatches(); // filter matches 23 | 24 | siftMatcher.drawMatchesCv(matchImg, true); // draw good matches into matchImg 25 | 26 | siftMatcher.getHomography(true); // calculate homography between (good) matched keypoints 27 | // and calc corresponding transformation on findImg 28 | 29 | 30 | // load the pre-warped cropped image for reference in ofApp::draw() 31 | refImg.load("peeping_tom_crop2.jpg"); 32 | 33 | } 34 | 35 | //-------------------------------------------------------------- 36 | void ofApp::update(){ 37 | 38 | } 39 | 40 | //-------------------------------------------------------------- 41 | void ofApp::draw(){ 42 | 43 | ofBackground(0); 44 | 45 | // draw matchImg 46 | matchImg.draw(0,0); 47 | 48 | /* 49 | // sidenote on drawing Mats: 50 | // ------------------------- 51 | // if we had declared matchMat (from setup()) as a public variable in ofApp.h, 52 | // we could draw it in ofApp::draw() using ofxCv's drawMat(): 53 | // drawMat(matchMat,0,0); 54 | // but this is expensive since drawMat() allocates a new GPU texture every time it's called. 55 | // it's best to convert to ofImage, so the texture is just allocated once on the GPU 56 | */ 57 | 58 | // draw box around findImg inside fieldImg 59 | siftMatcher.drawHomography(findImg.getWidth()); 60 | //offset by findImg width to correspond to matchImg 61 | 62 | 63 | // draw the original crop from the image, before I warped it in photoshop 64 | refImg.draw(0,ofGetHeight()-refImg.getHeight()); 65 | string refImgLbl = "Original Crop for Reference"; 66 | ofDrawBitmapString(refImgLbl, 10, ofGetHeight()-refImg.getHeight()-20); 67 | 68 | } 69 | 70 | 71 | //-------------------------------------------------------------- 72 | void ofApp::keyPressed(int key){ 73 | 74 | } 75 | 76 | //-------------------------------------------------------------- 77 | void ofApp::keyReleased(int key){ 78 | 79 | } 80 | 81 | //-------------------------------------------------------------- 82 | void ofApp::mouseMoved(int x, int y ){ 83 | 84 | } 85 | 86 | //-------------------------------------------------------------- 87 | void ofApp::mouseDragged(int x, int y, int button){ 88 | 89 | } 90 | 91 | //-------------------------------------------------------------- 92 | void ofApp::mousePressed(int x, int y, int button){ 93 | 94 | } 95 | 96 | //-------------------------------------------------------------- 97 | void ofApp::mouseReleased(int x, int y, int button){ 98 | 99 | } 100 | 101 | //-------------------------------------------------------------- 102 | void ofApp::mouseEntered(int x, int y){ 103 | 104 | } 105 | 106 | //-------------------------------------------------------------- 107 | void ofApp::mouseExited(int x, int y){ 108 | 109 | } 110 | 111 | //-------------------------------------------------------------- 112 | void ofApp::windowResized(int w, int h){ 113 | 114 | } 115 | 116 | //-------------------------------------------------------------- 117 | void ofApp::gotMessage(ofMessage msg){ 118 | 119 | } 120 | 121 | //-------------------------------------------------------------- 122 | void ofApp::dragEvent(ofDragInfo dragInfo){ 123 | 124 | } 125 | -------------------------------------------------------------------------------- /SIFT_filterMatches_homography/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "SIFTMatcher.hpp" 5 | 6 | using namespace cv; 7 | using namespace ofxCv; 8 | 9 | class ofApp : public ofBaseApp{ 10 | 11 | public: 12 | void setup(); 13 | void update(); 14 | void draw(); 15 | 16 | void keyPressed(int key); 17 | void keyReleased(int key); 18 | void mouseMoved(int x, int y ); 19 | void mouseDragged(int x, int y, int button); 20 | void mousePressed(int x, int y, int button); 21 | void mouseReleased(int x, int y, int button); 22 | void mouseEntered(int x, int y); 23 | void mouseExited(int x, int y); 24 | void windowResized(int w, int h); 25 | void dragEvent(ofDragInfo dragInfo); 26 | void gotMessage(ofMessage msg); 27 | 28 | ofImage findImg, fieldImg, matchImg, refImg; 29 | SIFTMatcher siftMatcher; 30 | 31 | }; 32 | -------------------------------------------------------------------------------- /SIFTtest/Makefile: -------------------------------------------------------------------------------- 1 | # Attempt to load a config.make file. 2 | # If none is found, project defaults in config.project.make will be used. 3 | ifneq ($(wildcard config.make),) 4 | include config.make 5 | endif 6 | 7 | # make sure the the OF_ROOT location is defined 8 | ifndef OF_ROOT 9 | OF_ROOT=$(realpath ../../..) 10 | endif 11 | 12 | # call the project makefile! 13 | include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk 14 | -------------------------------------------------------------------------------- /SIFTtest/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 17 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 18 | -------------------------------------------------------------------------------- /SIFTtest/SIFTtest.xcodeproj/xcshareddata/xcschemes/SIFTtest Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SIFTtest/SIFTtest.xcodeproj/xcshareddata/xcschemes/SIFTtest Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SIFTtest/addons.make: -------------------------------------------------------------------------------- 1 | ofxCv 2 | ofxOpenCv 3 | -------------------------------------------------------------------------------- /SIFTtest/bin/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFTtest/bin/data/.gitkeep -------------------------------------------------------------------------------- /SIFTtest/bin/data/peeping_tom_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFTtest/bin/data/peeping_tom_1.jpg -------------------------------------------------------------------------------- /SIFTtest/bin/data/peeping_tom_1_3d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFTtest/bin/data/peeping_tom_1_3d.jpg -------------------------------------------------------------------------------- /SIFTtest/bin/data/peeping_tom_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/SIFTtest/bin/data/peeping_tom_2.jpg -------------------------------------------------------------------------------- /SIFTtest/config.make: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # CONFIGURE PROJECT MAKEFILE (optional) 3 | # This file is where we make project specific configurations. 4 | ################################################################################ 5 | 6 | ################################################################################ 7 | # OF ROOT 8 | # The location of your root openFrameworks installation 9 | # (default) OF_ROOT = ../../.. 10 | ################################################################################ 11 | # OF_ROOT = ../../.. 12 | 13 | ################################################################################ 14 | # PROJECT ROOT 15 | # The location of the project - a starting place for searching for files 16 | # (default) PROJECT_ROOT = . (this directory) 17 | # 18 | ################################################################################ 19 | # PROJECT_ROOT = . 20 | 21 | ################################################################################ 22 | # PROJECT SPECIFIC CHECKS 23 | # This is a project defined section to create internal makefile flags to 24 | # conditionally enable or disable the addition of various features within 25 | # this makefile. For instance, if you want to make changes based on whether 26 | # GTK is installed, one might test that here and create a variable to check. 27 | ################################################################################ 28 | # None 29 | 30 | ################################################################################ 31 | # PROJECT EXTERNAL SOURCE PATHS 32 | # These are fully qualified paths that are not within the PROJECT_ROOT folder. 33 | # Like source folders in the PROJECT_ROOT, these paths are subject to 34 | # exlclusion via the PROJECT_EXLCUSIONS list. 35 | # 36 | # (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) 37 | # 38 | # Note: Leave a leading space when adding list items with the += operator 39 | ################################################################################ 40 | # PROJECT_EXTERNAL_SOURCE_PATHS = 41 | 42 | ################################################################################ 43 | # PROJECT EXCLUSIONS 44 | # These makefiles assume that all folders in your current project directory 45 | # and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations 46 | # to look for source code. The any folders or files that match any of the 47 | # items in the PROJECT_EXCLUSIONS list below will be ignored. 48 | # 49 | # Each item in the PROJECT_EXCLUSIONS list will be treated as a complete 50 | # string unless teh user adds a wildcard (%) operator to match subdirectories. 51 | # GNU make only allows one wildcard for matching. The second wildcard (%) is 52 | # treated literally. 53 | # 54 | # (default) PROJECT_EXCLUSIONS = (blank) 55 | # 56 | # Will automatically exclude the following: 57 | # 58 | # $(PROJECT_ROOT)/bin% 59 | # $(PROJECT_ROOT)/obj% 60 | # $(PROJECT_ROOT)/%.xcodeproj 61 | # 62 | # Note: Leave a leading space when adding list items with the += operator 63 | ################################################################################ 64 | # PROJECT_EXCLUSIONS = 65 | 66 | ################################################################################ 67 | # PROJECT LINKER FLAGS 68 | # These flags will be sent to the linker when compiling the executable. 69 | # 70 | # (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs 71 | # 72 | # Note: Leave a leading space when adding list items with the += operator 73 | ################################################################################ 74 | 75 | # Currently, shared libraries that are needed are copied to the 76 | # $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to 77 | # add a runtime path to search for those shared libraries, since they aren't 78 | # incorporated directly into the final executable application binary. 79 | # TODO: should this be a default setting? 80 | # PROJECT_LDFLAGS=-Wl,-rpath=./libs 81 | 82 | ################################################################################ 83 | # PROJECT DEFINES 84 | # Create a space-delimited list of DEFINES. The list will be converted into 85 | # CFLAGS with the "-D" flag later in the makefile. 86 | # 87 | # (default) PROJECT_DEFINES = (blank) 88 | # 89 | # Note: Leave a leading space when adding list items with the += operator 90 | ################################################################################ 91 | # PROJECT_DEFINES = 92 | 93 | ################################################################################ 94 | # PROJECT CFLAGS 95 | # This is a list of fully qualified CFLAGS required when compiling for this 96 | # project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS 97 | # defined in your platform specific core configuration files. These flags are 98 | # presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. 99 | # 100 | # (default) PROJECT_CFLAGS = (blank) 101 | # 102 | # Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in 103 | # your platform specific configuration file will be applied by default and 104 | # further flags here may not be needed. 105 | # 106 | # Note: Leave a leading space when adding list items with the += operator 107 | ################################################################################ 108 | # PROJECT_CFLAGS = 109 | 110 | ################################################################################ 111 | # PROJECT OPTIMIZATION CFLAGS 112 | # These are lists of CFLAGS that are target-specific. While any flags could 113 | # be conditionally added, they are usually limited to optimization flags. 114 | # These flags are added BEFORE the PROJECT_CFLAGS. 115 | # 116 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. 117 | # 118 | # (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) 119 | # 120 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. 121 | # 122 | # (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) 123 | # 124 | # Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the 125 | # PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration 126 | # file will be applied by default and further optimization flags here may not 127 | # be needed. 128 | # 129 | # Note: Leave a leading space when adding list items with the += operator 130 | ################################################################################ 131 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE = 132 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG = 133 | 134 | ################################################################################ 135 | # PROJECT COMPILERS 136 | # Custom compilers can be set for CC and CXX 137 | # (default) PROJECT_CXX = (blank) 138 | # (default) PROJECT_CC = (blank) 139 | # Note: Leave a leading space when adding list items with the += operator 140 | ################################################################################ 141 | # PROJECT_CXX = 142 | # PROJECT_CC = 143 | -------------------------------------------------------------------------------- /SIFTtest/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | cc.openFrameworks.ofapp 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | CFBundleIconFile 20 | ${ICON} 21 | 22 | 23 | -------------------------------------------------------------------------------- /SIFTtest/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | //======================================================================== 5 | int main( ){ 6 | ofSetupOpenGL(1700,720,OF_WINDOW); // <-------- setup the GL context 7 | 8 | // this kicks off the running of my app 9 | // can be OF_WINDOW or OF_FULLSCREEN 10 | // pass in width and height too: 11 | ofRunApp(new ofApp()); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SIFTtest/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //-------------------------------------------------------------- 4 | void ofApp::setup(){ 5 | 6 | // save start time (in ms) for testing speed 7 | uint64_t startTime = ofGetElapsedTimeMillis(); 8 | 9 | 10 | //---------------------// 11 | //---- LOAD IMAGES ----// 12 | //---------------------// 13 | 14 | // load the two images as ofImage 15 | 16 | findImg.load("peeping_tom_1.jpg"); // image we're looking for (called "query" in OpenCV) 17 | fieldImg.load("peeping_tom_2.jpg"); // image to search in (called "train" in OpenCV) 18 | 19 | // convert to grayscale (SIFT works in grayscale) 20 | 21 | findImg.setImageType(OF_IMAGE_GRAYSCALE); 22 | fieldImg.setImageType(OF_IMAGE_GRAYSCALE); 23 | 24 | 25 | 26 | // wrap images with Mat class for use with SIFT 27 | 28 | Mat findMat = toCv(findImg); 29 | Mat fieldMat = toCv(fieldImg); 30 | 31 | 32 | 33 | uint64_t loadTime = ofGetElapsedTimeMillis() - startTime; // calc image load time 34 | ofLogNotice("Image Load") << "took " << loadTime << " ms" << endl; // print load time to console 35 | startTime = ofGetElapsedTimeMillis(); // reset startTime 36 | 37 | 38 | 39 | //------------------------------------// 40 | //---- SIFT DETECTION/DESCRIPTION ----// 41 | //------------------------------------// 42 | 43 | 44 | // --------------------------------------- 45 | // 1. DETECT SIFT keypoints in both images 46 | // --------------------------------------- 47 | 48 | 49 | SiftFeatureDetector detector(2000); // SIFT detector object 50 | 51 | // 400 = max number of keypoints to find 52 | // all optional constructor args, with default values: 53 | // (int nfeatures=0, int nOctaveLayers=3, double contrastThreshold=0.04, 54 | // double edgeThreshold=10, double sigma=1.6); 55 | 56 | 57 | vector findKeypoints, fieldKeypoints; // KeyPoint vectors to store keypoints detected per image 58 | 59 | // run the detector on each image 60 | 61 | detector.detect(findMat, findKeypoints); 62 | detector.detect(fieldMat, fieldKeypoints); 63 | 64 | 65 | // print results 66 | // -------------- 67 | uint64_t detectTime = ofGetElapsedTimeMillis() - startTime; // calculate detection time 68 | 69 | // print # keypoints found to console 70 | 71 | ofLogNotice("SIFT Detector") << "took " << detectTime << " ms" << endl << endl 72 | << "# keypoints found" << endl 73 | << "-----------------" << endl 74 | << " findImg: " << findKeypoints.size() << endl 75 | << " fieldImg: " << fieldKeypoints.size() << endl; 76 | 77 | startTime = ofGetElapsedTimeMillis(); // reset startTime 78 | // -------------- 79 | 80 | 81 | // -------------------------------------- 82 | // 2. DESCRIBE SIFT features of keypoints 83 | // -------------------------------------- 84 | 85 | 86 | SiftDescriptorExtractor extractor; // SIFT descriptor object 87 | 88 | 89 | Mat findDescriptors, fieldDescriptors; // matrices to hold all features per keypoint in image 90 | // i.e. in each matrix, row 'i' is the list of features for keypoint 'i' 91 | 92 | // run the feature description extractor 93 | 94 | extractor.compute(findMat, findKeypoints, findDescriptors); 95 | extractor.compute(fieldMat, fieldKeypoints, fieldDescriptors); 96 | 97 | 98 | // print results 99 | // -------------- 100 | uint64_t describeTime = ofGetElapsedTimeMillis() - startTime; // calculate description time 101 | 102 | // print some statistics on the matrices 103 | 104 | cv::Size findSize = findDescriptors.size(); // size of matrix 105 | cv::Size fieldSize = fieldDescriptors.size(); 106 | 107 | ofLogNotice("SIFT Descriptor") << "took " << describeTime << " ms" << endl << endl 108 | << "findImg feature matrix" << endl 109 | << "--------------------" << endl 110 | << " height: " << findSize.height << ", width: " << findSize.width << endl 111 | << " area: " << findSize.area() << ", non-zero: " << countNonZero(findDescriptors) << endl 112 | << endl 113 | << "fieldImg feature matrix" << endl 114 | << "--------------------" << endl 115 | << " height: " << fieldSize.height << ", width: " << fieldSize.width << endl 116 | << " area: " << fieldSize.area() << ", non-zero: " << countNonZero(fieldDescriptors) << endl; 117 | 118 | startTime = ofGetElapsedTimeMillis(); // reset startTime 119 | // -------------- 120 | 121 | 122 | 123 | //---------------------------------// 124 | //---- FIND MATCHING KEYPOINTS ----// 125 | //---------------------------------// 126 | 127 | 128 | BFMatcher matcher(NORM_L1, true); // Brute-force Matcher object 129 | // loops through every feature in matrix 1, comparing it to every feature in matrix 2 130 | // to find best match in matrix 2 131 | 132 | // NORM_L1 is "normType" - use NORM_L1 or NORM_L2 for SIFT. I think this determines the type of normalization done when determining "distance" (in n-dimensional space) between keypoints 133 | // true is crossCheck boolean - this means that BFMatcher will only return a match when both keypoints find each other as their closest match. This should be set to true to produce more reliable matches, but only if you have a lot of keypoints. 134 | // a good visual example of cross-checking is on StackOverflow: http://stackoverflow.com/questions/11181823/why-we-need-crosscheckmatching-for-feature 135 | // see here for BFMatcher reference: http://docs.opencv.org/3.0-last-rst/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html?highlight=bfmatcher#bfmatcher 136 | 137 | vector matches; // vector to store matches 138 | 139 | // run the matcher 140 | 141 | matcher.match(findDescriptors, fieldDescriptors, matches); 142 | 143 | 144 | // print results 145 | // -------------- 146 | 147 | uint64_t matchTime = ofGetElapsedTimeMillis() - startTime; // calculate match time 148 | 149 | ofLogNotice("Matcher") << "took " << matchTime << " ms" << endl 150 | << "Found " << matches.size() << " matching keypoints" << endl; 151 | // -------------- 152 | 153 | 154 | //----------------------// 155 | //---- DRAW RESULTS ----// 156 | //----------------------// 157 | 158 | 159 | // cv::drawMatches() displays the images side by side, 160 | // with colored circles at each keypoint, 161 | // and lines connecting the matched keypoints. 162 | // It draws into a Mat. 163 | 164 | Mat matchMat; // image-matrix to temp store the results visualization 165 | 166 | // draw results visualization into matchMat image-matrix 167 | 168 | drawMatches(findMat, findKeypoints, fieldMat, fieldKeypoints, matches, matchMat, 169 | /* and optional parameters: */ 170 | Scalar::all(-1), Scalar::all(170), vector(), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); 171 | 172 | // The Scalar::all(-1) through DRAW_RICH_KEYPOINTS parameters are optional. 173 | // I'm copying the default arguments for them, except: 174 | // Scalar(170) which draws the unmatched keypoints in gray 175 | // DRAW_RICH_KEYPOINTS, which draws the size/rotation of the keypoints. 176 | // The default arguments for those would be: 177 | // Scalar::all(-1) for random colors 178 | // cv::DrawMatchesFlags::DEFAULT for drawing all keypoints as little circles. 179 | // see here for drawMatches() reference: http://docs.opencv.org/3.1.0/d4/d5d/group__features2d__draw.html#gsc.tab=0 180 | 181 | // convert matchMat to matchImg 182 | 183 | toOf(matchMat,matchImg); // wraps matchMat in ofImage matchImg, allocating as needed 184 | matchImg.update(); // updates the matchImg texture on the GPU 185 | 186 | // now we can draw matchImg in ofApp::draw() 187 | 188 | 189 | } 190 | 191 | //-------------------------------------------------------------- 192 | void ofApp::update(){ 193 | 194 | } 195 | 196 | //-------------------------------------------------------------- 197 | void ofApp::draw(){ 198 | 199 | ofBackground(0); 200 | 201 | // draw matchImg 202 | matchImg.draw(0,0); 203 | 204 | 205 | // sidenote on drawing Mats: 206 | // ------------------------- 207 | // if we had declared matchMat (from setup()) as a public variable in ofApp.h, 208 | // we could draw it in ofApp::draw() using ofxCv's drawMat(): 209 | // drawMat(matchMat,0,0); 210 | // but this is expensive since drawMat() allocates a new GPU texture every time it's called. 211 | // it's best to convert to ofImage, so the texture is just allocated once on the GPU 212 | 213 | } 214 | 215 | //-------------------------------------------------------------- 216 | void ofApp::keyPressed(int key){ 217 | 218 | } 219 | 220 | //-------------------------------------------------------------- 221 | void ofApp::keyReleased(int key){ 222 | 223 | } 224 | 225 | //-------------------------------------------------------------- 226 | void ofApp::mouseMoved(int x, int y ){ 227 | 228 | } 229 | 230 | //-------------------------------------------------------------- 231 | void ofApp::mouseDragged(int x, int y, int button){ 232 | 233 | } 234 | 235 | //-------------------------------------------------------------- 236 | void ofApp::mousePressed(int x, int y, int button){ 237 | 238 | } 239 | 240 | //-------------------------------------------------------------- 241 | void ofApp::mouseReleased(int x, int y, int button){ 242 | 243 | } 244 | 245 | //-------------------------------------------------------------- 246 | void ofApp::mouseEntered(int x, int y){ 247 | 248 | } 249 | 250 | //-------------------------------------------------------------- 251 | void ofApp::mouseExited(int x, int y){ 252 | 253 | } 254 | 255 | //-------------------------------------------------------------- 256 | void ofApp::windowResized(int w, int h){ 257 | 258 | } 259 | 260 | //-------------------------------------------------------------- 261 | void ofApp::gotMessage(ofMessage msg){ 262 | 263 | } 264 | 265 | //-------------------------------------------------------------- 266 | void ofApp::dragEvent(ofDragInfo dragInfo){ 267 | 268 | } 269 | -------------------------------------------------------------------------------- /SIFTtest/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "ofxOpenCv.h" 5 | #include "ofxCv.h" 6 | 7 | // include non-free OpenCV modules 8 | #include "opencv2/nonfree/nonfree.hpp" 9 | 10 | using namespace cv; 11 | using namespace ofxCv; 12 | 13 | class ofApp : public ofBaseApp{ 14 | 15 | public: 16 | void setup(); 17 | void update(); 18 | void draw(); 19 | 20 | void keyPressed(int key); 21 | void keyReleased(int key); 22 | void mouseMoved(int x, int y ); 23 | void mouseDragged(int x, int y, int button); 24 | void mousePressed(int x, int y, int button); 25 | void mouseReleased(int x, int y, int button); 26 | void mouseEntered(int x, int y); 27 | void mouseExited(int x, int y); 28 | void windowResized(int w, int h); 29 | void dragEvent(ofDragInfo dragInfo); 30 | void gotMessage(ofMessage msg); 31 | 32 | ofImage findImg, fieldImg, matchImg; 33 | 34 | 35 | }; 36 | -------------------------------------------------------------------------------- /griddedHistogram/Makefile: -------------------------------------------------------------------------------- 1 | # Attempt to load a config.make file. 2 | # If none is found, project defaults in config.project.make will be used. 3 | ifneq ($(wildcard config.make),) 4 | include config.make 5 | endif 6 | 7 | # make sure the the OF_ROOT location is defined 8 | ifndef OF_ROOT 9 | OF_ROOT=$(realpath ../../..) 10 | endif 11 | 12 | # call the project makefile! 13 | include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk 14 | -------------------------------------------------------------------------------- /griddedHistogram/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 17 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 18 | -------------------------------------------------------------------------------- /griddedHistogram/addons.make: -------------------------------------------------------------------------------- 1 | ofxCcv 2 | ofxCv 3 | ofxGui 4 | ofxOpenCv 5 | -------------------------------------------------------------------------------- /griddedHistogram/bin/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/griddedHistogram/bin/data/.gitkeep -------------------------------------------------------------------------------- /griddedHistogram/bin/data/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/griddedHistogram/bin/data/grid.png -------------------------------------------------------------------------------- /griddedHistogram/bin/data/img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/griddedHistogram/bin/data/img.jpg -------------------------------------------------------------------------------- /griddedHistogram/config.make: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # CONFIGURE PROJECT MAKEFILE (optional) 3 | # This file is where we make project specific configurations. 4 | ################################################################################ 5 | 6 | ################################################################################ 7 | # OF ROOT 8 | # The location of your root openFrameworks installation 9 | # (default) OF_ROOT = ../../.. 10 | ################################################################################ 11 | # OF_ROOT = ../../.. 12 | 13 | ################################################################################ 14 | # PROJECT ROOT 15 | # The location of the project - a starting place for searching for files 16 | # (default) PROJECT_ROOT = . (this directory) 17 | # 18 | ################################################################################ 19 | # PROJECT_ROOT = . 20 | 21 | ################################################################################ 22 | # PROJECT SPECIFIC CHECKS 23 | # This is a project defined section to create internal makefile flags to 24 | # conditionally enable or disable the addition of various features within 25 | # this makefile. For instance, if you want to make changes based on whether 26 | # GTK is installed, one might test that here and create a variable to check. 27 | ################################################################################ 28 | # None 29 | 30 | ################################################################################ 31 | # PROJECT EXTERNAL SOURCE PATHS 32 | # These are fully qualified paths that are not within the PROJECT_ROOT folder. 33 | # Like source folders in the PROJECT_ROOT, these paths are subject to 34 | # exlclusion via the PROJECT_EXLCUSIONS list. 35 | # 36 | # (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) 37 | # 38 | # Note: Leave a leading space when adding list items with the += operator 39 | ################################################################################ 40 | # PROJECT_EXTERNAL_SOURCE_PATHS = 41 | 42 | ################################################################################ 43 | # PROJECT EXCLUSIONS 44 | # These makefiles assume that all folders in your current project directory 45 | # and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations 46 | # to look for source code. The any folders or files that match any of the 47 | # items in the PROJECT_EXCLUSIONS list below will be ignored. 48 | # 49 | # Each item in the PROJECT_EXCLUSIONS list will be treated as a complete 50 | # string unless teh user adds a wildcard (%) operator to match subdirectories. 51 | # GNU make only allows one wildcard for matching. The second wildcard (%) is 52 | # treated literally. 53 | # 54 | # (default) PROJECT_EXCLUSIONS = (blank) 55 | # 56 | # Will automatically exclude the following: 57 | # 58 | # $(PROJECT_ROOT)/bin% 59 | # $(PROJECT_ROOT)/obj% 60 | # $(PROJECT_ROOT)/%.xcodeproj 61 | # 62 | # Note: Leave a leading space when adding list items with the += operator 63 | ################################################################################ 64 | # PROJECT_EXCLUSIONS = 65 | 66 | ################################################################################ 67 | # PROJECT LINKER FLAGS 68 | # These flags will be sent to the linker when compiling the executable. 69 | # 70 | # (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs 71 | # 72 | # Note: Leave a leading space when adding list items with the += operator 73 | ################################################################################ 74 | 75 | # Currently, shared libraries that are needed are copied to the 76 | # $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to 77 | # add a runtime path to search for those shared libraries, since they aren't 78 | # incorporated directly into the final executable application binary. 79 | # TODO: should this be a default setting? 80 | # PROJECT_LDFLAGS=-Wl,-rpath=./libs 81 | 82 | ################################################################################ 83 | # PROJECT DEFINES 84 | # Create a space-delimited list of DEFINES. The list will be converted into 85 | # CFLAGS with the "-D" flag later in the makefile. 86 | # 87 | # (default) PROJECT_DEFINES = (blank) 88 | # 89 | # Note: Leave a leading space when adding list items with the += operator 90 | ################################################################################ 91 | # PROJECT_DEFINES = 92 | 93 | ################################################################################ 94 | # PROJECT CFLAGS 95 | # This is a list of fully qualified CFLAGS required when compiling for this 96 | # project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS 97 | # defined in your platform specific core configuration files. These flags are 98 | # presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. 99 | # 100 | # (default) PROJECT_CFLAGS = (blank) 101 | # 102 | # Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in 103 | # your platform specific configuration file will be applied by default and 104 | # further flags here may not be needed. 105 | # 106 | # Note: Leave a leading space when adding list items with the += operator 107 | ################################################################################ 108 | # PROJECT_CFLAGS = 109 | 110 | ################################################################################ 111 | # PROJECT OPTIMIZATION CFLAGS 112 | # These are lists of CFLAGS that are target-specific. While any flags could 113 | # be conditionally added, they are usually limited to optimization flags. 114 | # These flags are added BEFORE the PROJECT_CFLAGS. 115 | # 116 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. 117 | # 118 | # (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) 119 | # 120 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. 121 | # 122 | # (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) 123 | # 124 | # Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the 125 | # PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration 126 | # file will be applied by default and further optimization flags here may not 127 | # be needed. 128 | # 129 | # Note: Leave a leading space when adding list items with the += operator 130 | ################################################################################ 131 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE = 132 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG = 133 | 134 | ################################################################################ 135 | # PROJECT COMPILERS 136 | # Custom compilers can be set for CC and CXX 137 | # (default) PROJECT_CXX = (blank) 138 | # (default) PROJECT_CC = (blank) 139 | # Note: Leave a leading space when adding list items with the += operator 140 | ################################################################################ 141 | # PROJECT_CXX = 142 | # PROJECT_CC = 143 | -------------------------------------------------------------------------------- /griddedHistogram/griddedHistogram.xcodeproj/xcshareddata/xcschemes/griddedHistogram Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /griddedHistogram/griddedHistogram.xcodeproj/xcshareddata/xcschemes/griddedHistogram Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /griddedHistogram/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | cc.openFrameworks.ofapp 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | CFBundleIconFile 20 | ${ICON} 21 | 22 | 23 | -------------------------------------------------------------------------------- /griddedHistogram/src/Histogrid.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Histogrid.cpp 3 | // griddedHistogram 4 | // 5 | // Created by Tyler on 3/31/16. 6 | // 7 | // 8 | 9 | #include "Histogrid.hpp" 10 | 11 | 12 | Histogrid::Histogrid(){ 13 | 14 | } 15 | 16 | 17 | Histogrid::Histogrid(ofImage& _img, int _nDivsX, int _nDivsY, int _nBins){ 18 | 19 | img = &_img; 20 | 21 | nDivsX = _nDivsX; 22 | nDivsY = _nDivsY; 23 | nBins = _nBins; 24 | 25 | imgMat = toCv(*img); 26 | cvtColor(imgMat,imgMat, CV_BGR2GRAY); 27 | // convert to grayscale for intensity 28 | 29 | } 30 | 31 | 32 | void Histogrid::run(){ 33 | 34 | // calculate histograms 35 | 36 | histograms.clear(); 37 | rects.clear(); 38 | 39 | Mat hist; 40 | float range[] = { 0, 256 }; // histogram range, upper bound exclusive 41 | const float* histRange = { range }; // another range? cv weirdness 42 | 43 | for (int r=0; r tmpHist; 70 | for (int i=0; i(i)); 73 | 74 | } 75 | // save to histogram vector of histograms 76 | histograms.push_back(tmpHist); 77 | } 78 | } 79 | 80 | 81 | 82 | } 83 | 84 | void Histogrid::draw(int n, ofColor color){ 85 | draw(n,0,0,img->getWidth(),img->getHeight(), color); 86 | // draw at (0,0) and image size 87 | } 88 | 89 | void Histogrid::draw(int n, float x, float y, float w, float h, ofColor color){ 90 | 91 | ofPushMatrix(); 92 | ofTranslate(x,y); 93 | 94 | ofPushStyle(); 95 | ofSetLineWidth(1); 96 | ofFill(); 97 | ofSetColor(color); 98 | 99 | for (int i=0; i>& Histogrid::getHistograms() const{ 120 | 121 | return histograms; // return all histograms 122 | } 123 | 124 | const vector& Histogrid::getHistogram(int n) const{ 125 | 126 | return histograms[n]; // return specific histogram 127 | } 128 | 129 | int Histogrid::getNDivsX(){ 130 | 131 | return nDivsX; 132 | } 133 | 134 | int Histogrid::getNDivsY(){ 135 | 136 | return nDivsY; 137 | } 138 | 139 | int Histogrid::getNBins(){ 140 | 141 | return nBins; 142 | } 143 | 144 | const vector& Histogrid::getRectangles() const{ 145 | return rects; 146 | } -------------------------------------------------------------------------------- /griddedHistogram/src/Histogrid.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Histogrid.hpp 3 | // griddedHistogram 4 | // 5 | // Created by Tyler on 3/31/16. 6 | // 7 | // 8 | 9 | #pragma once 10 | #include "ofMain.h" 11 | 12 | #include "ofxOpenCv.h" 13 | #include "ofxCv.h" 14 | 15 | using namespace cv; 16 | using namespace ofxCv; 17 | 18 | class Histogrid { 19 | 20 | public: 21 | 22 | Histogrid(); 23 | Histogrid(ofImage& _img, int _nDivsX = 10, int _nDivsY = 10, int _nBins = 256); 24 | 25 | void run(); 26 | void draw(int n, ofColor color = ofColor::white); 27 | void draw(int n, float x, float y, float w, float h, ofColor color = ofColor::white); 28 | void drawMat(); 29 | 30 | const vector>& getHistograms() const; 31 | const vector& getHistogram(int n) const; 32 | int getNDivsX(); 33 | int getNDivsY(); 34 | int getNBins(); 35 | const vector& getRectangles() const; 36 | 37 | private: 38 | 39 | int nDivsX, nDivsY, nBins; 40 | ofImage* img; 41 | Mat imgMat; 42 | 43 | vector> histograms; 44 | vector rects; 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /griddedHistogram/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | //======================================================================== 5 | int main( ){ 6 | ofSetupOpenGL(1280,480,OF_WINDOW); // <-------- setup the GL context 7 | 8 | // this kicks off the running of my app 9 | // can be OF_WINDOW or OF_FULLSCREEN 10 | // pass in width and height too: 11 | ofRunApp(new ofApp()); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /griddedHistogram/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //-------------------------------------------------------------- 4 | void ofApp::setup(){ 5 | ofBackground(0); 6 | 7 | img.load("img.jpg"); 8 | 9 | imgXY = ofVec2f(0,0); // placement of image for draw 10 | imgWH = ofVec2f(640,480); // scale of image for draw 11 | 12 | nDivsX = 2; // # of grid divisions on x-axis 13 | nDivsY = 2; // # of divs on y-axis 14 | 15 | hist = Histogrid(img,nDivsX,nDivsY,256); //img, nDivs x,y, nBins 16 | 17 | hist.run(); // calculate the histogram 18 | 19 | rects = hist.getRectangles(); // get the grid as a vector of rectangles 20 | 21 | drawGrid = ofRectangle(0,0,0,0); // rectangle overlay for selected subsection 22 | 23 | } 24 | 25 | //-------------------------------------------------------------- 26 | void ofApp::update(){ 27 | 28 | } 29 | 30 | //-------------------------------------------------------------- 31 | void ofApp::draw(){ 32 | 33 | img.draw(imgXY.x,imgXY.y, imgWH.x,imgWH.y); // draw image 34 | 35 | hist.draw(gridNum, imgWH.x,imgXY.y, imgWH.x,imgWH.y); // draw histogram 36 | // gridNum = which section to draw histogram for 37 | // other options: x,y, w,h for draw (here, draw next to image) 38 | 39 | 40 | // draw selected grid chunk 41 | 42 | ofPushMatrix(); 43 | ofTranslate(imgXY); 44 | ofScale(imgWH.x/img.getWidth(),imgWH.y/img.getHeight()); 45 | ofPushStyle(); 46 | ofFill(); 47 | ofSetColor(255,255,0,100); 48 | ofDrawRectangle(drawGrid); // draw selected rect 49 | ofPopStyle(); 50 | ofPopMatrix(); 51 | 52 | } 53 | 54 | //-------------------------------------------------------------- 55 | void ofApp::keyPressed(int key){ 56 | 57 | } 58 | 59 | //-------------------------------------------------------------- 60 | void ofApp::keyReleased(int key){ 61 | 62 | } 63 | 64 | //-------------------------------------------------------------- 65 | void ofApp::mouseMoved(int x, int y ){ 66 | 67 | // if mouse is over image 68 | ofRectangle rect(imgXY,imgWH); 69 | 70 | if (rect.inside(ofVec2f(x,y))){ 71 | 72 | // figure out which rectangle the mouse is in 73 | 74 | float mX = ofMap(x, imgXY.x, imgWH.x, 0, img.getWidth()); 75 | float mY = ofMap(y, imgXY.y, imgWH.y, 0, img.getHeight()); 76 | 77 | for (int i=0; i rects; 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /optFlowTest/Makefile: -------------------------------------------------------------------------------- 1 | # Attempt to load a config.make file. 2 | # If none is found, project defaults in config.project.make will be used. 3 | ifneq ($(wildcard config.make),) 4 | include config.make 5 | endif 6 | 7 | # make sure the the OF_ROOT location is defined 8 | ifndef OF_ROOT 9 | OF_ROOT=$(realpath ../../..) 10 | endif 11 | 12 | # call the project makefile! 13 | include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk 14 | -------------------------------------------------------------------------------- /optFlowTest/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 17 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 18 | -------------------------------------------------------------------------------- /optFlowTest/addons.make: -------------------------------------------------------------------------------- 1 | ofxCv 2 | ofxOpenCv 3 | -------------------------------------------------------------------------------- /optFlowTest/bin/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/optFlowTest/bin/data/.gitkeep -------------------------------------------------------------------------------- /optFlowTest/bin/data/rearWindow_clip_1-240p.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/optFlowTest/bin/data/rearWindow_clip_1-240p.mp4 -------------------------------------------------------------------------------- /optFlowTest/bin/data/rearWindow_clip_1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyhenry/opencv-oF-experiments/9564b74604e37f2a5941219cc95b5612d19721c9/optFlowTest/bin/data/rearWindow_clip_1.mp4 -------------------------------------------------------------------------------- /optFlowTest/config.make: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # CONFIGURE PROJECT MAKEFILE (optional) 3 | # This file is where we make project specific configurations. 4 | ################################################################################ 5 | 6 | ################################################################################ 7 | # OF ROOT 8 | # The location of your root openFrameworks installation 9 | # (default) OF_ROOT = ../../.. 10 | ################################################################################ 11 | # OF_ROOT = ../../.. 12 | 13 | ################################################################################ 14 | # PROJECT ROOT 15 | # The location of the project - a starting place for searching for files 16 | # (default) PROJECT_ROOT = . (this directory) 17 | # 18 | ################################################################################ 19 | # PROJECT_ROOT = . 20 | 21 | ################################################################################ 22 | # PROJECT SPECIFIC CHECKS 23 | # This is a project defined section to create internal makefile flags to 24 | # conditionally enable or disable the addition of various features within 25 | # this makefile. For instance, if you want to make changes based on whether 26 | # GTK is installed, one might test that here and create a variable to check. 27 | ################################################################################ 28 | # None 29 | 30 | ################################################################################ 31 | # PROJECT EXTERNAL SOURCE PATHS 32 | # These are fully qualified paths that are not within the PROJECT_ROOT folder. 33 | # Like source folders in the PROJECT_ROOT, these paths are subject to 34 | # exlclusion via the PROJECT_EXLCUSIONS list. 35 | # 36 | # (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) 37 | # 38 | # Note: Leave a leading space when adding list items with the += operator 39 | ################################################################################ 40 | # PROJECT_EXTERNAL_SOURCE_PATHS = 41 | 42 | ################################################################################ 43 | # PROJECT EXCLUSIONS 44 | # These makefiles assume that all folders in your current project directory 45 | # and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations 46 | # to look for source code. The any folders or files that match any of the 47 | # items in the PROJECT_EXCLUSIONS list below will be ignored. 48 | # 49 | # Each item in the PROJECT_EXCLUSIONS list will be treated as a complete 50 | # string unless teh user adds a wildcard (%) operator to match subdirectories. 51 | # GNU make only allows one wildcard for matching. The second wildcard (%) is 52 | # treated literally. 53 | # 54 | # (default) PROJECT_EXCLUSIONS = (blank) 55 | # 56 | # Will automatically exclude the following: 57 | # 58 | # $(PROJECT_ROOT)/bin% 59 | # $(PROJECT_ROOT)/obj% 60 | # $(PROJECT_ROOT)/%.xcodeproj 61 | # 62 | # Note: Leave a leading space when adding list items with the += operator 63 | ################################################################################ 64 | # PROJECT_EXCLUSIONS = 65 | 66 | ################################################################################ 67 | # PROJECT LINKER FLAGS 68 | # These flags will be sent to the linker when compiling the executable. 69 | # 70 | # (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs 71 | # 72 | # Note: Leave a leading space when adding list items with the += operator 73 | ################################################################################ 74 | 75 | # Currently, shared libraries that are needed are copied to the 76 | # $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to 77 | # add a runtime path to search for those shared libraries, since they aren't 78 | # incorporated directly into the final executable application binary. 79 | # TODO: should this be a default setting? 80 | # PROJECT_LDFLAGS=-Wl,-rpath=./libs 81 | 82 | ################################################################################ 83 | # PROJECT DEFINES 84 | # Create a space-delimited list of DEFINES. The list will be converted into 85 | # CFLAGS with the "-D" flag later in the makefile. 86 | # 87 | # (default) PROJECT_DEFINES = (blank) 88 | # 89 | # Note: Leave a leading space when adding list items with the += operator 90 | ################################################################################ 91 | # PROJECT_DEFINES = 92 | 93 | ################################################################################ 94 | # PROJECT CFLAGS 95 | # This is a list of fully qualified CFLAGS required when compiling for this 96 | # project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS 97 | # defined in your platform specific core configuration files. These flags are 98 | # presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. 99 | # 100 | # (default) PROJECT_CFLAGS = (blank) 101 | # 102 | # Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in 103 | # your platform specific configuration file will be applied by default and 104 | # further flags here may not be needed. 105 | # 106 | # Note: Leave a leading space when adding list items with the += operator 107 | ################################################################################ 108 | # PROJECT_CFLAGS = 109 | 110 | ################################################################################ 111 | # PROJECT OPTIMIZATION CFLAGS 112 | # These are lists of CFLAGS that are target-specific. While any flags could 113 | # be conditionally added, they are usually limited to optimization flags. 114 | # These flags are added BEFORE the PROJECT_CFLAGS. 115 | # 116 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. 117 | # 118 | # (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) 119 | # 120 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. 121 | # 122 | # (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) 123 | # 124 | # Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the 125 | # PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration 126 | # file will be applied by default and further optimization flags here may not 127 | # be needed. 128 | # 129 | # Note: Leave a leading space when adding list items with the += operator 130 | ################################################################################ 131 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE = 132 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG = 133 | 134 | ################################################################################ 135 | # PROJECT COMPILERS 136 | # Custom compilers can be set for CC and CXX 137 | # (default) PROJECT_CXX = (blank) 138 | # (default) PROJECT_CC = (blank) 139 | # Note: Leave a leading space when adding list items with the += operator 140 | ################################################################################ 141 | # PROJECT_CXX = 142 | # PROJECT_CC = 143 | -------------------------------------------------------------------------------- /optFlowTest/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | cc.openFrameworks.ofapp 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | CFBundleIconFile 20 | ${ICON} 21 | 22 | 23 | -------------------------------------------------------------------------------- /optFlowTest/optFlowTest.xcodeproj/xcshareddata/xcschemes/optFlowTest Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /optFlowTest/optFlowTest.xcodeproj/xcshareddata/xcschemes/optFlowTest Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /optFlowTest/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | //======================================================================== 5 | int main( ){ 6 | ofSetupOpenGL(1280,720,OF_WINDOW); // <-------- setup the GL context 7 | 8 | // this kicks off the running of my app 9 | // can be OF_WINDOW or OF_FULLSCREEN 10 | // pass in width and height too: 11 | ofRunApp(new ofApp()); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /optFlowTest/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //-------------------------------------------------------------- 4 | void ofApp::setup(){ 5 | ofBackground(0); 6 | ofSetFrameRate(60); 7 | ofFill(); 8 | 9 | vid.load("rearWindow_clip_1-240p.mp4"); // a single shot from Rear Window 10 | vidW = vid.getWidth(); 11 | vidH = vid.getHeight(); 12 | 13 | // setup gui 14 | gui.setup(); 15 | gui.add(flowPyrScale.set("Pyramid Scale", .5, 0, .99)); 16 | gui.add(flowLevels.set("Pyramid Levels", 4, 1, 8)); 17 | gui.add(flowIterations.set("Iterations", 2, 1, 8)); 18 | gui.add(flowPolyN.set("Polynomial size", 7, 5, 10)); 19 | gui.add(flowPolySigma.set("PolySigma", 1.5, 1.1, 2)); 20 | gui.add(flowUseGaussian.set("Use Gaussian", true)); 21 | gui.add(flowWinSize.set("Window size", 32, 4, 64)); 22 | gui.add(loopVid.set("Loop video", false)); 23 | gui.add(vidScale.set("Scale video", 2, 1, 3)); 24 | gui.add(lineWidth.set("Draw line width", 4, 1, 10)); 25 | 26 | // start video 27 | vid.play(); 28 | } 29 | 30 | //-------------------------------------------------------------- 31 | void ofApp::update(){ 32 | 33 | if (vid.getCurrentFrame() == 0) { 34 | reset(); 35 | // will only do full reset if video is at beginning 36 | // doubles as an initialization 37 | } 38 | 39 | vid.update(); 40 | 41 | if (loopVid){ 42 | vid.setLoopState(OF_LOOP_NORMAL); 43 | 44 | if (!vid.isPlaying()){ 45 | vid.play(); // restart vid if it ended 46 | } 47 | 48 | 49 | } else { 50 | vid.setLoopState(OF_LOOP_NONE); 51 | 52 | if (vid.getIsMovieDone()){ 53 | flow.resetFlow(); // reset flow cache in ofxCv to clear flow draw 54 | } 55 | } 56 | 57 | 58 | if (vid.isFrameNew()){ 59 | 60 | // Farneback flow parameters 61 | // more info at: http://docs.opencv.org/3.0-beta/modules/video/doc/motion_analysis_and_object_tracking.html#calcopticalflowfarneback 62 | 63 | flow.setPyramidScale(flowPyrScale); 64 | // 0.5 is classical image pyramid (scales image * 0.5 each layer) 65 | 66 | flow.setNumLevels(flowLevels); // number of levels of scaling pyramid 67 | // 1 means only original image is analyzed, no pyramid 68 | 69 | flow.setWindowSize(flowWinSize); // average window size 70 | // larger means robust to noise + better fast motion, but more blurred motion 71 | 72 | flow.setNumIterations(flowIterations); // # iterations of algorithm at each pyramid level 73 | 74 | flow.setPolyN(flowPolyN); 75 | // size of pixel neighborhood used for per-pixel polynomial expansion 76 | // larger means image will be approximated at smooth surfaces, more robust algorithm, more blurred motion 77 | 78 | flow.setPolySigma(flowPolySigma); 79 | // standard deviation of gaussian used to smooth derivates for polynomial expansion 80 | // for PolyN of 5, use PolySigma 1.1 81 | // for PolyN of 7, use PolySigma 1.5 82 | 83 | flow.setUseGaussian(flowUseGaussian); 84 | // use gaussian filter instead of box filter: slower but more accurate 85 | // normally use a larger window with this option 86 | 87 | 88 | 89 | // calculate flow 90 | 91 | flow.calcOpticalFlow(vid); 92 | 93 | 94 | 95 | // save average flows per frame + per vid 96 | 97 | frameFlows.push_back(flow.getAverageFlow()); 98 | 99 | vidFlowTotal += frameFlows.back(); 100 | vidFlowAvg = vidFlowTotal / frameFlows.size(); 101 | 102 | // calculate dot position to show average movement 103 | 104 | dotPos += frameFlows.back(); 105 | dotPath.addVertex(dotPos); 106 | 107 | } 108 | 109 | } 110 | 111 | //-------------------------------------------------------------- 112 | void ofApp::draw(){ 113 | 114 | // draw video and flow field 115 | 116 | ofSetColor(255); 117 | 118 | ofPushMatrix(); 119 | ofTranslate(250,0); // make room for gui at left 120 | ofScale(vidScale, vidScale); // scale to vidScale gui choice 121 | 122 | 123 | vid.draw(0,0, vidW, vidH); // draw video at scale 124 | 125 | ofSetLineWidth(1); // draw thin flow field 126 | // (i.e. don't change flow field's line width with gui lineWidth choice) 127 | 128 | flow.draw(0,0, vidW, vidH); // draw flow field at scale 129 | 130 | ofSetLineWidth(lineWidth); // draw other lines based on gui lineWidth 131 | 132 | 133 | // draw dot to track average flow 134 | 135 | ofSetColor(0,255,255); 136 | 137 | ofDrawCircle(dotPos, lineWidth*0.75); // draw dot 138 | 139 | dotPath.draw(); // draw dot's path 140 | 141 | if (frameFlows.size() > 0){ 142 | // draw average magnitude and direction of this frame, if we have it 143 | 144 | ofSetColor(255,0,0); 145 | 146 | ofDrawLine(vidW*0.5, vidH*0.5, vidW*0.5+ frameFlows.back().x * 50, vidH*0.5+ frameFlows.back().y * 50); 147 | // scale motion average * 50 for visibility 148 | } 149 | 150 | 151 | ofPopMatrix(); 152 | 153 | // draw framerate at bottom of video 154 | ofDrawBitmapStringHighlight(ofToString((int) ofGetFrameRate()) + "fps", 250, vidH*vidScale); 155 | 156 | 157 | 158 | // draw gui 159 | gui.draw(); 160 | 161 | 162 | 163 | 164 | // draw average flow per frame and per video as lines 165 | 166 | if (frameFlows.size() > 0){ // only draw if there's been some flow 167 | 168 | ofPushMatrix(); 169 | ofTranslate(125,300); // move below gui 170 | 171 | // draw avg magnitude + direction 172 | 173 | ofSetColor(255,0,0); 174 | ofDrawLine(0, 0, vidFlowAvg.x * 50, vidFlowAvg.y * 50); // scale up * 50 for visibility 175 | 176 | ofSetColor(0,255,0); 177 | 178 | // draw normalized direction for magnitude reference 179 | 180 | ofDrawCircle(vidFlowAvg.getNormalized().x * 50, vidFlowAvg.getNormalized().y * 50, lineWidth); 181 | 182 | ofDrawBitmapStringHighlight("Avg magnitude + direction\nnorm'd to 50px",-115,-50); 183 | 184 | 185 | ofPopMatrix(); 186 | 187 | } 188 | 189 | 190 | } 191 | 192 | //-------------------------------------------------------------- 193 | void ofApp::reset(){ 194 | 195 | flow.resetFlow(); // clear ofxCv's flow cache 196 | 197 | // reset frameFlow tracking 198 | frameFlows.clear(); 199 | vidFlowTotal.set(0,0); 200 | 201 | // moving dot 202 | dotPos = ofVec2f(vidW*0.5, vidH*0.5); // center of drawn video 203 | 204 | // polyline that tracks dot movement 205 | dotPath.clear(); 206 | dotPath.addVertex(dotPos); 207 | } 208 | 209 | //-------------------------------------------------------------- 210 | void ofApp::keyPressed(int key){ 211 | 212 | } 213 | 214 | //-------------------------------------------------------------- 215 | void ofApp::keyReleased(int key){ 216 | 217 | } 218 | 219 | //-------------------------------------------------------------- 220 | void ofApp::mouseMoved(int x, int y ){ 221 | 222 | } 223 | 224 | //-------------------------------------------------------------- 225 | void ofApp::mouseDragged(int x, int y, int button){ 226 | 227 | } 228 | 229 | //-------------------------------------------------------------- 230 | void ofApp::mousePressed(int x, int y, int button){ 231 | 232 | } 233 | 234 | //-------------------------------------------------------------- 235 | void ofApp::mouseReleased(int x, int y, int button){ 236 | 237 | } 238 | 239 | //-------------------------------------------------------------- 240 | void ofApp::mouseEntered(int x, int y){ 241 | 242 | } 243 | 244 | //-------------------------------------------------------------- 245 | void ofApp::mouseExited(int x, int y){ 246 | 247 | } 248 | 249 | //-------------------------------------------------------------- 250 | void ofApp::windowResized(int w, int h){ 251 | 252 | } 253 | 254 | //-------------------------------------------------------------- 255 | void ofApp::gotMessage(ofMessage msg){ 256 | 257 | } 258 | 259 | //-------------------------------------------------------------- 260 | void ofApp::dragEvent(ofDragInfo dragInfo){ 261 | 262 | } 263 | -------------------------------------------------------------------------------- /optFlowTest/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | #include "ofxOpenCv.h" 6 | #include "ofxCv.h" 7 | 8 | #include "ofxGui.h" 9 | 10 | using namespace cv; 11 | using namespace ofxCv; 12 | 13 | class ofApp : public ofBaseApp{ 14 | 15 | public: 16 | void setup(); 17 | void update(); 18 | void draw(); 19 | 20 | void reset(); 21 | 22 | void keyPressed(int key); 23 | void keyReleased(int key); 24 | void mouseMoved(int x, int y ); 25 | void mouseDragged(int x, int y, int button); 26 | void mousePressed(int x, int y, int button); 27 | void mouseReleased(int x, int y, int button); 28 | void mouseEntered(int x, int y); 29 | void mouseExited(int x, int y); 30 | void windowResized(int w, int h); 31 | void dragEvent(ofDragInfo dragInfo); 32 | void gotMessage(ofMessage msg); 33 | 34 | ofVideoPlayer vid; 35 | float vidW, vidH; 36 | 37 | FlowFarneback flow; // ofxCv's dense optical flow analyzer (for whole image) 38 | // alternative would be FlowPyrLK which detects/analyzes a sparse feature set 39 | 40 | vector frameFlows; // store average flow frame-by-frame 41 | ofVec2f vidFlowTotal = ofVec2f(0,0), vidFlowAvg = ofVec2f(0,0); // store average flow of video 42 | 43 | // moving dot 44 | ofVec2f dotPos; 45 | ofPolyline dotPath; // polyline tracks dot movement 46 | 47 | 48 | // gui options - stolen from ofxCv example-flow 49 | ofxPanel gui; 50 | ofParameter flowPyrScale, flowPolySigma, vidScale, lineWidth; 51 | ofParameter flowLevels, flowIterations, flowPolyN, flowWinSize; 52 | ofParameter flowUseGaussian, loopVid; 53 | 54 | }; 55 | --------------------------------------------------------------------------------