Android demo: Allow DetectorActivity to gracefully degrade if no native ObjectTracker support is found. If libtensorflow_demo.so is not found in the APK, rendered boxes will simply be stationary and will be replaced whenever new results come in.

Partially addresses #6385
Change: 155159326
This commit is contained in:
Andrew Harp 2017-05-04 19:30:36 -08:00 committed by TensorFlower Gardener
parent 44cf98028b
commit efa08d80a5
3 changed files with 64 additions and 18 deletions

View File

@ -124,7 +124,7 @@ public class DetectorActivity extends CameraActivity implements OnImageAvailable
borderedText = new BorderedText(textSizePx);
borderedText.setTypeface(Typeface.MONOSPACE);
tracker = new MultiBoxTracker(getResources().getDisplayMetrics());
tracker = new MultiBoxTracker(this);
if (USE_YOLO) {
detector =

View File

@ -15,6 +15,7 @@ limitations under the License.
package org.tensorflow.demo.tracking;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
@ -24,9 +25,9 @@ import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.util.TypedValue;
import android.widget.Toast;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
@ -69,6 +70,7 @@ public class MultiBoxTracker {
private static class TrackedRecognition {
ObjectTracker.TrackedObject trackedObject;
RectF location;
float detectionConfidence;
int color;
String title;
@ -87,8 +89,10 @@ public class MultiBoxTracker {
private int frameHeight;
private int sensorOrientation;
private Context context;
public MultiBoxTracker(final DisplayMetrics metrics) {
public MultiBoxTracker(final Context context) {
this.context = context;
for (final int color : COLORS) {
availableColors.add(color);
}
@ -100,7 +104,9 @@ public class MultiBoxTracker {
boxPaint.setStrokeJoin(Join.ROUND);
boxPaint.setStrokeMiter(100);
textSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, metrics);
textSizePx =
TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, context.getResources().getDisplayMetrics());
borderedText = new BorderedText(textSizePx);
}
@ -152,10 +158,6 @@ public class MultiBoxTracker {
}
public synchronized void draw(final Canvas canvas) {
if (objectTracker == null) {
return;
}
// TODO(andrewharp): This may not work for non-90 deg rotations.
final float multiplier =
Math.min(canvas.getWidth() / (float) frameHeight, canvas.getHeight() / (float) frameWidth);
@ -168,9 +170,11 @@ public class MultiBoxTracker {
sensorOrientation,
false);
for (final TrackedRecognition recognition : trackedObjects) {
final ObjectTracker.TrackedObject trackedObject = recognition.trackedObject;
final RectF trackedPos =
(objectTracker != null)
? recognition.trackedObject.getTrackedPositionInPreviewFrame()
: new RectF(recognition.location);
final RectF trackedPos = trackedObject.getTrackedPositionInPreviewFrame();
getFrameToCanvasMatrix().mapRect(trackedPos);
boxPaint.setColor(recognition.color);
@ -185,6 +189,8 @@ public class MultiBoxTracker {
}
}
private boolean initialized = false;
public synchronized void onFrame(
final int w,
final int h,
@ -192,7 +198,7 @@ public class MultiBoxTracker {
final int sensorOrienation,
final byte[] frame,
final long timestamp) {
if (objectTracker == null) {
if (objectTracker == null && !initialized) {
ObjectTracker.clearInstance();
logger.i("Initializing ObjectTracker: %dx%d", w, h);
@ -200,6 +206,19 @@ public class MultiBoxTracker {
frameWidth = w;
frameHeight = h;
this.sensorOrientation = sensorOrienation;
initialized = true;
if (objectTracker == null) {
String message =
"Object tracking support not found. "
+ "See tensorflow/examples/android/README.md for details.";
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
logger.e(message);
}
}
if (objectTracker == null) {
return;
}
objectTracker.nextFrame(frame, null, timestamp, null, true);
@ -255,7 +274,20 @@ public class MultiBoxTracker {
}
if (objectTracker == null) {
logger.w("No ObjectTracker, can't track anything!");
trackedObjects.clear();
for (final Pair<Float, Recognition> potential : rectsToTrack) {
final TrackedRecognition trackedRecognition = new TrackedRecognition();
trackedRecognition.detectionConfidence = potential.first;
trackedRecognition.location = new RectF(potential.second.getLocation());
trackedRecognition.trackedObject = null;
trackedRecognition.title = potential.second.getTitle();
trackedRecognition.color = COLORS[trackedObjects.size()];
trackedObjects.add(trackedRecognition);
if (trackedObjects.size() >= COLORS.length) {
break;
}
}
return;
}

View File

@ -48,7 +48,18 @@ import org.tensorflow.demo.env.Size;
* ObjectTracker still exists.
*/
public class ObjectTracker {
private final Logger logger = new Logger();
private static final Logger LOGGER = new Logger();
private static boolean libraryFound = false;
static {
try {
System.loadLibrary("tensorflow_demo");
libraryFound = true;
} catch (UnsatisfiedLinkError e) {
LOGGER.e("libtensorflow_demo.so not found, tracking unavailable");
}
}
private static final boolean DRAW_TEXT = false;
@ -194,6 +205,13 @@ public class ObjectTracker {
public static synchronized ObjectTracker getInstance(
final int frameWidth, final int frameHeight, final int rowStride, final boolean alwaysTrack) {
if (!libraryFound) {
LOGGER.e(
"Native object tracking support not found. "
+ "See tensorflow/examples/android/README.md for details.");
return null;
}
if (instance == null) {
instance = new ObjectTracker(frameWidth, frameHeight, rowStride, alwaysTrack);
instance.init();
@ -519,7 +537,7 @@ public class ObjectTracker {
checkValidObject();
synchronized (ObjectTracker.this) {
if (lastExternalPositionTime > timestamp) {
logger.w("Tried to use older position time!");
LOGGER.w("Tried to use older position time!");
return;
}
final RectF externalPosition = downscaleRect(position);
@ -640,8 +658,4 @@ public class ObjectTracker {
protected static native void downsampleImageNative(
int width, int height, int rowStride, byte[] input, int factor, byte[] output);
static {
System.loadLibrary("tensorflow_demo");
}
}