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:
parent
44cf98028b
commit
efa08d80a5
@ -124,7 +124,7 @@ public class DetectorActivity extends CameraActivity implements OnImageAvailable
|
|||||||
borderedText = new BorderedText(textSizePx);
|
borderedText = new BorderedText(textSizePx);
|
||||||
borderedText.setTypeface(Typeface.MONOSPACE);
|
borderedText.setTypeface(Typeface.MONOSPACE);
|
||||||
|
|
||||||
tracker = new MultiBoxTracker(getResources().getDisplayMetrics());
|
tracker = new MultiBoxTracker(this);
|
||||||
|
|
||||||
if (USE_YOLO) {
|
if (USE_YOLO) {
|
||||||
detector =
|
detector =
|
||||||
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||||||
|
|
||||||
package org.tensorflow.demo.tracking;
|
package org.tensorflow.demo.tracking;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
@ -24,9 +25,9 @@ import android.graphics.Paint.Join;
|
|||||||
import android.graphics.Paint.Style;
|
import android.graphics.Paint.Style;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
import android.widget.Toast;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
@ -69,6 +70,7 @@ public class MultiBoxTracker {
|
|||||||
|
|
||||||
private static class TrackedRecognition {
|
private static class TrackedRecognition {
|
||||||
ObjectTracker.TrackedObject trackedObject;
|
ObjectTracker.TrackedObject trackedObject;
|
||||||
|
RectF location;
|
||||||
float detectionConfidence;
|
float detectionConfidence;
|
||||||
int color;
|
int color;
|
||||||
String title;
|
String title;
|
||||||
@ -87,8 +89,10 @@ public class MultiBoxTracker {
|
|||||||
private int frameHeight;
|
private int frameHeight;
|
||||||
|
|
||||||
private int sensorOrientation;
|
private int sensorOrientation;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
public MultiBoxTracker(final DisplayMetrics metrics) {
|
public MultiBoxTracker(final Context context) {
|
||||||
|
this.context = context;
|
||||||
for (final int color : COLORS) {
|
for (final int color : COLORS) {
|
||||||
availableColors.add(color);
|
availableColors.add(color);
|
||||||
}
|
}
|
||||||
@ -100,7 +104,9 @@ public class MultiBoxTracker {
|
|||||||
boxPaint.setStrokeJoin(Join.ROUND);
|
boxPaint.setStrokeJoin(Join.ROUND);
|
||||||
boxPaint.setStrokeMiter(100);
|
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);
|
borderedText = new BorderedText(textSizePx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,10 +158,6 @@ public class MultiBoxTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void draw(final Canvas canvas) {
|
public synchronized void draw(final Canvas canvas) {
|
||||||
if (objectTracker == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(andrewharp): This may not work for non-90 deg rotations.
|
// TODO(andrewharp): This may not work for non-90 deg rotations.
|
||||||
final float multiplier =
|
final float multiplier =
|
||||||
Math.min(canvas.getWidth() / (float) frameHeight, canvas.getHeight() / (float) frameWidth);
|
Math.min(canvas.getWidth() / (float) frameHeight, canvas.getHeight() / (float) frameWidth);
|
||||||
@ -168,9 +170,11 @@ public class MultiBoxTracker {
|
|||||||
sensorOrientation,
|
sensorOrientation,
|
||||||
false);
|
false);
|
||||||
for (final TrackedRecognition recognition : trackedObjects) {
|
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);
|
getFrameToCanvasMatrix().mapRect(trackedPos);
|
||||||
boxPaint.setColor(recognition.color);
|
boxPaint.setColor(recognition.color);
|
||||||
|
|
||||||
@ -185,6 +189,8 @@ public class MultiBoxTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean initialized = false;
|
||||||
|
|
||||||
public synchronized void onFrame(
|
public synchronized void onFrame(
|
||||||
final int w,
|
final int w,
|
||||||
final int h,
|
final int h,
|
||||||
@ -192,7 +198,7 @@ public class MultiBoxTracker {
|
|||||||
final int sensorOrienation,
|
final int sensorOrienation,
|
||||||
final byte[] frame,
|
final byte[] frame,
|
||||||
final long timestamp) {
|
final long timestamp) {
|
||||||
if (objectTracker == null) {
|
if (objectTracker == null && !initialized) {
|
||||||
ObjectTracker.clearInstance();
|
ObjectTracker.clearInstance();
|
||||||
|
|
||||||
logger.i("Initializing ObjectTracker: %dx%d", w, h);
|
logger.i("Initializing ObjectTracker: %dx%d", w, h);
|
||||||
@ -200,6 +206,19 @@ public class MultiBoxTracker {
|
|||||||
frameWidth = w;
|
frameWidth = w;
|
||||||
frameHeight = h;
|
frameHeight = h;
|
||||||
this.sensorOrientation = sensorOrienation;
|
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);
|
objectTracker.nextFrame(frame, null, timestamp, null, true);
|
||||||
@ -255,7 +274,20 @@ public class MultiBoxTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (objectTracker == null) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,18 @@ import org.tensorflow.demo.env.Size;
|
|||||||
* ObjectTracker still exists.
|
* ObjectTracker still exists.
|
||||||
*/
|
*/
|
||||||
public class ObjectTracker {
|
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;
|
private static final boolean DRAW_TEXT = false;
|
||||||
|
|
||||||
@ -194,6 +205,13 @@ public class ObjectTracker {
|
|||||||
|
|
||||||
public static synchronized ObjectTracker getInstance(
|
public static synchronized ObjectTracker getInstance(
|
||||||
final int frameWidth, final int frameHeight, final int rowStride, final boolean alwaysTrack) {
|
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) {
|
if (instance == null) {
|
||||||
instance = new ObjectTracker(frameWidth, frameHeight, rowStride, alwaysTrack);
|
instance = new ObjectTracker(frameWidth, frameHeight, rowStride, alwaysTrack);
|
||||||
instance.init();
|
instance.init();
|
||||||
@ -519,7 +537,7 @@ public class ObjectTracker {
|
|||||||
checkValidObject();
|
checkValidObject();
|
||||||
synchronized (ObjectTracker.this) {
|
synchronized (ObjectTracker.this) {
|
||||||
if (lastExternalPositionTime > timestamp) {
|
if (lastExternalPositionTime > timestamp) {
|
||||||
logger.w("Tried to use older position time!");
|
LOGGER.w("Tried to use older position time!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final RectF externalPosition = downscaleRect(position);
|
final RectF externalPosition = downscaleRect(position);
|
||||||
@ -640,8 +658,4 @@ public class ObjectTracker {
|
|||||||
|
|
||||||
protected static native void downsampleImageNative(
|
protected static native void downsampleImageNative(
|
||||||
int width, int height, int rowStride, byte[] input, int factor, byte[] output);
|
int width, int height, int rowStride, byte[] input, int factor, byte[] output);
|
||||||
|
|
||||||
static {
|
|
||||||
System.loadLibrary("tensorflow_demo");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user