├── README.md ├── android ├── .gitignore ├── .idea │ ├── .name │ ├── compiler.xml │ ├── copyright │ │ └── profiles_settings.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── libraries │ │ ├── android_0_17.xml │ │ ├── calibration_0_17.xml │ │ ├── ddogleg_0_5.xml │ │ ├── ejml_0_25.xml │ │ ├── feature_0_17.xml │ │ ├── geo_0_17.xml │ │ ├── georegression_0_6.xml │ │ ├── ip_0_17.xml │ │ ├── recognition_0_17.xml │ │ └── sfm_0_17.xml │ ├── misc.xml │ ├── modules.xml │ ├── scopes │ │ └── scope_settings.xml │ └── vcs.xml ├── android.iml ├── app │ ├── .gitignore │ ├── app.iml │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── org │ │ │ └── boofcv │ │ │ └── objecttracking │ │ │ └── ApplicationTest.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── org │ │ │ └── boofcv │ │ │ └── objecttracking │ │ │ ├── ObjectTrackerActivity.java │ │ │ └── UtilVarious.java │ │ └── res │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── layout │ │ └── objecttrack_controls.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties └── settings.gradle ├── copyright.txt └── desktop ├── build.gradle ├── desktop.iml └── src └── ExampleObjectTracking.java /README.md: -------------------------------------------------------------------------------- 1 | TutorialObjectTracking 2 | ====================== 3 | 4 | Demonstration on how to perform object tracking from live video streams on the desktop and Android devices. Object tracking is the process of tracking objects inside of video streams, often selected by the user or an automated algorithm. BoofCV (http://boofcv.org) is an open source Java based computer vision library and is used to provide the tracking algorithms. As of version 0.17 has following built in: 5 | 6 | - Circulant 7 | * Simple and robust, but can't recover tracks 8 | * http://home.isr.uc.pt/~henriques/circulant/ 9 | - Track-Learning-Detect (TLD) 10 | * Only long term tracking algorithm in BoofCV 11 | * More computationally expensive and can be finicky 12 | * http://personal.ee.surrey.ac.uk/Personal/Z.Kalal/tld.html 13 | - Sparse-Flow 14 | * Only tracker in BoofCV which can estimate rotations 15 | * KLT based tracker 16 | * Can be brittle 17 | * http://boofcv.org/javadoc/boofcv/alg/tracker/sfot/SparseFlowObjectTracker.html 18 | - Mean-Shift 19 | * Matches the histogram of a local neighborhood 20 | * Comaniciu, et. al. ,"Kernel-Based Object Tracking" 2003 21 | - Mean-Shift Likelihood 22 | * Extremely fast but only works well when a single color dominates 23 | 24 | Desktop Instructions 25 | ====================== 26 | 27 | The Desktop example should run without difficulty on Linux, Windows, and MacOS. Make sure you have webcam connect to your computer before you run. 28 | 29 | 1. Install Gradle if you don't already have it 30 | 2. Switch to desktop directory 31 | * cd TutorialObjectTracking/desktop 32 | 3. Compile and run the example: 33 | * gradle webcamRun 34 | 4. Select an object to track in the window which popped up 35 | 36 | Android Instructions 37 | ====================== 38 | 39 | Just load it into Android studio and you will be good to go. 40 | 41 | ====================== 42 | 43 | Author: Peter Abeles 44 | Date: July 15, 2014 -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | .DS_Store 5 | /build 6 | -------------------------------------------------------------------------------- /android/.idea/.name: -------------------------------------------------------------------------------- 1 | ObjectTracking -------------------------------------------------------------------------------- /android/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /android/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /android/.idea/libraries/android_0_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/calibration_0_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/ddogleg_0_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/ejml_0_25.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/feature_0_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/geo_0_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/georegression_0_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/ip_0_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/recognition_0_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/libraries/sfm_0_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /android/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 14 5 | buildToolsVersion '20.0.0' 6 | 7 | defaultConfig { 8 | applicationId "org.boofcv.objecttracking" 9 | minSdkVersion 14 10 | targetSdkVersion 19 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | runProguard false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | 25 | ['recognition','android'].each { String a -> compile group: 'org.boofcv', name: a, version: '0.17' } 26 | } 27 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android-studio/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /android/app/src/androidTest/java/org/boofcv/objecttracking/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package org.boofcv.objecttracking; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /android/app/src/main/java/org/boofcv/objecttracking/ObjectTrackerActivity.java: -------------------------------------------------------------------------------- 1 | package org.boofcv.objecttracking; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.hardware.Camera; 8 | import android.os.Bundle; 9 | import android.view.LayoutInflater; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | import android.widget.AdapterView; 13 | import android.widget.ArrayAdapter; 14 | import android.widget.FrameLayout; 15 | import android.widget.LinearLayout; 16 | import android.widget.Spinner; 17 | import android.widget.Toast; 18 | 19 | import java.util.List; 20 | 21 | import boofcv.abst.tracker.ConfigComaniciu2003; 22 | import boofcv.abst.tracker.ConfigTld; 23 | import boofcv.abst.tracker.MeanShiftLikelihoodType; 24 | import boofcv.abst.tracker.TrackerObjectQuad; 25 | import boofcv.alg.tracker.sfot.SfotConfig; 26 | import boofcv.android.ConvertBitmap; 27 | import boofcv.android.gui.VideoDisplayActivity; 28 | import boofcv.android.gui.VideoImageProcessing; 29 | import boofcv.core.image.ConvertImage; 30 | import boofcv.factory.tracker.FactoryTrackerObjectQuad; 31 | import boofcv.struct.image.ImageBase; 32 | import boofcv.struct.image.ImageType; 33 | import boofcv.struct.image.ImageUInt8; 34 | import boofcv.struct.image.MultiSpectral; 35 | import georegression.struct.point.Point2D_F64; 36 | import georegression.struct.point.Point2D_I32; 37 | import georegression.struct.shapes.Quadrilateral_F64; 38 | 39 | /** 40 | * Activity which opens a camera and lets the user select objects to track and switch between 41 | * different trackers. The user selects an object by clicking and dragging until the drawn 42 | * rectangle fills the object. To select a new object click reset. 43 | */ 44 | public class ObjectTrackerActivity extends VideoDisplayActivity 45 | implements AdapterView.OnItemSelectedListener, View.OnTouchListener 46 | { 47 | 48 | Spinner spinnerView; 49 | 50 | int mode = 0; 51 | 52 | // size of the minimum square which the user can select 53 | final static int MINIMUM_MOTION = 20; 54 | 55 | Point2D_I32 click0 = new Point2D_I32(); 56 | Point2D_I32 click1 = new Point2D_I32(); 57 | 58 | @Override 59 | public void onCreate(Bundle savedInstanceState) { 60 | super.onCreate(savedInstanceState); 61 | 62 | LayoutInflater inflater = getLayoutInflater(); 63 | LinearLayout controls = (LinearLayout)inflater.inflate(R.layout.objecttrack_controls,null); 64 | 65 | LinearLayout parent = getViewContent(); 66 | parent.addView(controls); 67 | 68 | FrameLayout iv = getViewPreview(); 69 | iv.setOnTouchListener(this); 70 | 71 | spinnerView = (Spinner)controls.findViewById(R.id.spinner_algs); 72 | ArrayAdapter adapter = ArrayAdapter.createFromResource(this, 73 | R.array.tracking_objects, android.R.layout.simple_spinner_item); 74 | adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 75 | spinnerView.setAdapter(adapter); 76 | spinnerView.setOnItemSelectedListener(this); 77 | } 78 | 79 | @Override 80 | protected void onResume() { 81 | super.onResume(); 82 | startObjectTracking(spinnerView.getSelectedItemPosition()); 83 | 84 | // uncomment the line below to visually show the FPS. 85 | // The FPS is affected by the camera speed and processing power. The camera speed 86 | // is often determined by ambient lighting conditions 87 | // setShowFPS(true); 88 | } 89 | 90 | @Override 91 | protected Camera openConfigureCamera( Camera.CameraInfo cameraInfo ) 92 | { 93 | Camera mCamera = UtilVarious.selectAndOpenCamera(cameraInfo, this); 94 | Camera.Parameters param = mCamera.getParameters(); 95 | 96 | // Select the preview size closest to 320x240 97 | // Smaller images are recommended because some computer vision operations are very expensive 98 | List sizes = param.getSupportedPreviewSizes(); 99 | Camera.Size s = sizes.get(UtilVarious.closest(sizes, 320, 240)); 100 | param.setPreviewSize(s.width,s.height); 101 | mCamera.setParameters(param); 102 | 103 | return mCamera; 104 | } 105 | 106 | @Override 107 | public void onItemSelected(AdapterView adapterView, View view, int pos, long id ) { 108 | startObjectTracking(pos); 109 | } 110 | 111 | private void startObjectTracking(int pos) { 112 | TrackerObjectQuad tracker = null; 113 | ImageType imageType = null; 114 | 115 | switch (pos) { 116 | case 0: 117 | imageType = ImageType.single(ImageUInt8.class); 118 | tracker = FactoryTrackerObjectQuad.circulant(null, ImageUInt8.class); 119 | break; 120 | 121 | case 1: 122 | imageType = ImageType.ms(3, ImageUInt8.class); 123 | tracker = FactoryTrackerObjectQuad.meanShiftComaniciu2003(new ConfigComaniciu2003(false),imageType); 124 | break; 125 | 126 | case 2: 127 | imageType = ImageType.ms(3, ImageUInt8.class); 128 | tracker = FactoryTrackerObjectQuad.meanShiftComaniciu2003(new ConfigComaniciu2003(true),imageType); 129 | break; 130 | 131 | case 3: 132 | imageType = ImageType.ms(3, ImageUInt8.class); 133 | tracker = FactoryTrackerObjectQuad.meanShiftLikelihood(30,5,256, MeanShiftLikelihoodType.HISTOGRAM,imageType); 134 | break; 135 | 136 | case 4:{ 137 | imageType = ImageType.single(ImageUInt8.class); 138 | SfotConfig config = new SfotConfig(); 139 | config.numberOfSamples = 10; 140 | config.robustMaxError = 30; 141 | tracker = FactoryTrackerObjectQuad.sparseFlow(config,ImageUInt8.class,null); 142 | }break; 143 | 144 | case 5: 145 | imageType = ImageType.single(ImageUInt8.class); 146 | tracker = FactoryTrackerObjectQuad.tld(new ConfigTld(false),ImageUInt8.class); 147 | break; 148 | 149 | default: 150 | throw new RuntimeException("Unknown tracker: "+pos); 151 | } 152 | setProcessing(new TrackingProcessing(tracker,imageType) ); 153 | } 154 | 155 | @Override 156 | public void onNothingSelected(AdapterView adapterView) {} 157 | 158 | @Override 159 | public boolean onTouch(View view, MotionEvent motionEvent) { 160 | if( mode == 0 ) { 161 | if(MotionEvent.ACTION_DOWN == motionEvent.getActionMasked()) { 162 | click0.set((int) motionEvent.getX(), (int) motionEvent.getY()); 163 | click1.set((int) motionEvent.getX(), (int) motionEvent.getY()); 164 | mode = 1; 165 | } 166 | } else if( mode == 1 ) { 167 | if(MotionEvent.ACTION_MOVE == motionEvent.getActionMasked()) { 168 | click1.set((int)motionEvent.getX(),(int)motionEvent.getY()); 169 | } else if(MotionEvent.ACTION_UP == motionEvent.getActionMasked()) { 170 | click1.set((int)motionEvent.getX(),(int)motionEvent.getY()); 171 | mode = 2; 172 | } 173 | } 174 | return true; 175 | } 176 | 177 | public void resetPressed( View view ) { 178 | mode = 0; 179 | } 180 | 181 | protected class TrackingProcessing extends VideoImageProcessing> 182 | { 183 | 184 | T input; 185 | ImageType inputType; 186 | 187 | TrackerObjectQuad tracker; 188 | boolean visible; 189 | 190 | Quadrilateral_F64 location = new Quadrilateral_F64(); 191 | 192 | Paint paintSelected = new Paint(); 193 | Paint paintLine0 = new Paint(); 194 | Paint paintLine1 = new Paint(); 195 | Paint paintLine2 = new Paint(); 196 | Paint paintLine3 = new Paint(); 197 | private Paint textPaint = new Paint(); 198 | 199 | protected TrackingProcessing(TrackerObjectQuad tracker , ImageType inputType) { 200 | super(ImageType.ms(3,ImageUInt8.class)); 201 | this.inputType = inputType; 202 | 203 | if( inputType.getFamily() == ImageType.Family.SINGLE_BAND ) { 204 | input = inputType.createImage(1,1); 205 | } 206 | 207 | mode = 0; 208 | this.tracker = tracker; 209 | 210 | paintSelected.setColor(Color.argb(0xFF / 2, 0xFF, 0, 0)); 211 | 212 | paintLine0.setColor(Color.RED); 213 | paintLine0.setStrokeWidth(3f); 214 | paintLine1.setColor(Color.MAGENTA); 215 | paintLine1.setStrokeWidth(3f); 216 | paintLine2.setColor(Color.BLUE); 217 | paintLine2.setStrokeWidth(3f); 218 | paintLine3.setColor(Color.GREEN); 219 | paintLine3.setStrokeWidth(3f); 220 | 221 | // Create out paint to use for drawing 222 | textPaint.setARGB(255, 200, 0, 0); 223 | textPaint.setTextSize(60); 224 | 225 | } 226 | 227 | @Override 228 | protected void process(MultiSpectral input, Bitmap output, byte[] storage) 229 | { 230 | updateTracker(input); 231 | visualize(input, output, storage); 232 | } 233 | 234 | private void updateTracker(MultiSpectral color) { 235 | if( inputType.getFamily() == ImageType.Family.SINGLE_BAND ) { 236 | input.reshape(color.width,color.height); 237 | ConvertImage.average(color, (ImageUInt8) input); 238 | } else { 239 | input = (T)color; 240 | } 241 | 242 | if( mode == 2 ) { 243 | imageToOutput(click0.x, click0.y, location.a); 244 | imageToOutput(click1.x, click1.y, location.c); 245 | 246 | // make sure the user selected a valid region 247 | makeInBounds(location.a); 248 | makeInBounds(location.c); 249 | 250 | if( movedSignificantly(location.a,location.c) ) { 251 | // use the selected region and start the tracker 252 | location.b.set(location.c.x, location.a.y); 253 | location.d.set( location.a.x, location.c.y ); 254 | 255 | tracker.initialize(input, location); 256 | visible = true; 257 | mode = 3; 258 | } else { 259 | // the user screw up. Let them know what they did wrong 260 | runOnUiThread(new Runnable() { 261 | @Override 262 | public void run() { 263 | Toast.makeText(ObjectTrackerActivity.this, "Drag a larger region", Toast.LENGTH_SHORT).show(); 264 | } 265 | }); 266 | mode = 0; 267 | } 268 | } else if( mode == 3 ) { 269 | visible = tracker.process(input,location); 270 | } 271 | } 272 | 273 | private void visualize(MultiSpectral color, Bitmap output, byte[] storage) { 274 | ConvertBitmap.multiToBitmap(color, output, storage); 275 | Canvas canvas = new Canvas(output); 276 | 277 | if( mode == 1 ) { 278 | Point2D_F64 a = new Point2D_F64(); 279 | Point2D_F64 b = new Point2D_F64(); 280 | 281 | imageToOutput(click0.x, click0.y, a); 282 | imageToOutput(click1.x, click1.y, b); 283 | 284 | canvas.drawRect((int)a.x,(int)a.y,(int)b.x,(int)b.y,paintSelected); 285 | } else if( mode >= 2 ) { 286 | if( visible ) { 287 | Quadrilateral_F64 q = location; 288 | 289 | drawLine(canvas,q.a,q.b,paintLine0); 290 | drawLine(canvas,q.b,q.c,paintLine1); 291 | drawLine(canvas,q.c,q.d,paintLine2); 292 | drawLine(canvas,q.d,q.a,paintLine3); 293 | } else { 294 | canvas.drawText("?",color.width/2,color.height/2,textPaint); 295 | } 296 | } 297 | } 298 | 299 | private void drawLine( Canvas canvas , Point2D_F64 a , Point2D_F64 b , Paint color ) { 300 | canvas.drawLine((int)a.x,(int)a.y,(int)b.x,(int)b.y,color); 301 | } 302 | 303 | private void makeInBounds( Point2D_F64 p ) { 304 | if( p.x < 0 ) p.x = 0; 305 | else if( p.x >= input.width ) 306 | p.x = input.width - 1; 307 | 308 | if( p.y < 0 ) p.y = 0; 309 | else if( p.y >= input.height ) 310 | p.y = input.height - 1; 311 | 312 | } 313 | 314 | private boolean movedSignificantly( Point2D_F64 a , Point2D_F64 b ) { 315 | if( Math.abs(a.x-b.x) < MINIMUM_MOTION ) 316 | return false; 317 | if( Math.abs(a.y-b.y) < MINIMUM_MOTION ) 318 | return false; 319 | 320 | return true; 321 | } 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /android/app/src/main/java/org/boofcv/objecttracking/UtilVarious.java: -------------------------------------------------------------------------------- 1 | package org.boofcv.objecttracking; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.hardware.Camera; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Various generic funtions. 12 | * 13 | * @author Peter Abeles 14 | */ 15 | public class UtilVarious { 16 | 17 | /** 18 | * Step through the camera list and select a camera. It is also possible that there is no camera. 19 | * The camera hardware requirement in AndroidManifest.xml was turned off so that devices with just 20 | * a front facing camera can be found. Newer SDK's handle this in a more sane way, but with older devices 21 | * you need this work around. 22 | */ 23 | public static Camera selectAndOpenCamera(Camera.CameraInfo info , Context context ) { 24 | int numberOfCameras = Camera.getNumberOfCameras(); 25 | 26 | int selected = -1; 27 | 28 | for (int i = 0; i < numberOfCameras; i++) { 29 | Camera.getCameraInfo(i, info); 30 | 31 | if( info.facing == Camera.CameraInfo.CAMERA_FACING_BACK ) { 32 | selected = i; 33 | break; 34 | } else { 35 | // default to a front facing camera if a back facing one can't be found 36 | selected = i; 37 | } 38 | } 39 | 40 | if( selected == -1 ) { 41 | dialogNoCamera(context); 42 | return null; // won't ever be called 43 | } else { 44 | return Camera.open(selected); 45 | } 46 | } 47 | 48 | /** 49 | * Gracefully handle the situation where a camera could not be found 50 | */ 51 | public static void dialogNoCamera( Context context ) { 52 | AlertDialog.Builder builder = new AlertDialog.Builder(context); 53 | builder.setMessage("Your device has no cameras!") 54 | .setCancelable(false) 55 | .setPositiveButton("OK", new DialogInterface.OnClickListener() { 56 | public void onClick(DialogInterface dialog, int id) { 57 | System.exit(0); 58 | } 59 | }); 60 | AlertDialog alert = builder.create(); 61 | alert.show(); 62 | } 63 | 64 | 65 | /** 66 | * From the list of image sizes, select the one which is closest to the specified size. 67 | */ 68 | public static int closest( List sizes , int width , int height ) { 69 | int best = -1; 70 | int bestScore = Integer.MAX_VALUE; 71 | 72 | for( int i = 0; i < sizes.size(); i++ ) { 73 | Camera.Size s = sizes.get(i); 74 | 75 | int dx = s.width-width; 76 | int dy = s.height-height; 77 | 78 | int score = dx*dx + dy*dy; 79 | if( score < bestScore ) { 80 | best = i; 81 | bestScore = score; 82 | } 83 | } 84 | 85 | return best; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lessthanoptimal/TutorialObjectTracking/a85b16884efa4d6782953148c06da6dd552ab0f0/android/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lessthanoptimal/TutorialObjectTracking/a85b16884efa4d6782953148c06da6dd552ab0f0/android/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lessthanoptimal/TutorialObjectTracking/a85b16884efa4d6782953148c06da6dd552ab0f0/android/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lessthanoptimal/TutorialObjectTracking/a85b16884efa4d6782953148c06da6dd552ab0f0/android/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/layout/objecttrack_controls.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 |