Commit 2756155a by wanglei

format

1 parent e08d779b
Showing with 266 additions and 878 deletions
...@@ -14,11 +14,9 @@ ...@@ -14,11 +14,9 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@drawable/ic_launcher"
android:label="@string/tfe_od_app_name" android:label="@string/tfe_od_app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.ObjectDetection"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:installLocation="internalOnly"> android:installLocation="internalOnly">
......
...@@ -22,51 +22,52 @@ import android.view.TextureView; ...@@ -22,51 +22,52 @@ import android.view.TextureView;
/** A {@link TextureView} that can be adjusted to a specified aspect ratio. */ /** A {@link TextureView} that can be adjusted to a specified aspect ratio. */
public class AutoFitTextureView extends TextureView { public class AutoFitTextureView extends TextureView {
private int ratioWidth = 0; private int ratioWidth = 0;
private int ratioHeight = 0; private int ratioHeight = 0;
public AutoFitTextureView(final Context context) { public AutoFitTextureView(final Context context) {
this(context, null); this(context, null);
} }
public AutoFitTextureView(final Context context, final AttributeSet attrs) { public AutoFitTextureView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0); this(context, attrs, 0);
} }
public AutoFitTextureView(final Context context, final AttributeSet attrs, final int defStyle) { public AutoFitTextureView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
} }
/** /**
* Sets the aspect ratio for this view. The size of the view will be measured based on the ratio * Sets the aspect ratio for this view. The size of the view will be measured
* calculated from the parameters. Note that the actual sizes of parameters don't matter, that is, * based on the ratio calculated from the parameters. Note that the actual sizes
* calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. * of parameters don't matter, that is, calling setAspectRatio(2, 3) and
* * setAspectRatio(4, 6) make the same result.
* @param width Relative horizontal size *
* @param height Relative vertical size * @param width Relative horizontal size
*/ * @param height Relative vertical size
public void setAspectRatio(final int width, final int height) { */
if (width < 0 || height < 0) { public void setAspectRatio(final int width, final int height) {
throw new IllegalArgumentException("Size cannot be negative."); if (width < 0 || height < 0) {
} throw new IllegalArgumentException("Size cannot be negative.");
ratioWidth = width; }
ratioHeight = height; ratioWidth = width;
requestLayout(); ratioHeight = height;
} requestLayout();
}
@Override @Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int width = MeasureSpec.getSize(widthMeasureSpec); final int width = MeasureSpec.getSize(widthMeasureSpec);
final int height = MeasureSpec.getSize(heightMeasureSpec); final int height = MeasureSpec.getSize(heightMeasureSpec);
if (0 == ratioWidth || 0 == ratioHeight) { if (0 == ratioWidth || 0 == ratioHeight) {
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
} else { } else {
if (width < height * ratioWidth / ratioHeight) { if (width < height * ratioWidth / ratioHeight) {
setMeasuredDimension(width, width * ratioHeight / ratioWidth); setMeasuredDimension(width, width * ratioHeight / ratioWidth);
} else { } else {
setMeasuredDimension(height * ratioWidth / ratioHeight, height); setMeasuredDimension(height * ratioWidth / ratioHeight, height);
} }
} }
} }
} }
...@@ -24,25 +24,25 @@ import java.util.List; ...@@ -24,25 +24,25 @@ import java.util.List;
/** A simple View providing a render callback to other classes. */ /** A simple View providing a render callback to other classes. */
public class OverlayView extends View { public class OverlayView extends View {
private final List<DrawCallback> callbacks = new LinkedList<DrawCallback>(); private final List<DrawCallback> callbacks = new LinkedList<DrawCallback>();
public OverlayView(final Context context, final AttributeSet attrs) { public OverlayView(final Context context, final AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
public void addCallback(final DrawCallback callback) { public void addCallback(final DrawCallback callback) {
callbacks.add(callback); callbacks.add(callback);
} }
@Override @Override
public synchronized void draw(final Canvas canvas) { public synchronized void draw(final Canvas canvas) {
for (final DrawCallback callback : callbacks) { for (final DrawCallback callback : callbacks) {
callback.drawCallback(canvas); callback.drawCallback(canvas);
} }
} }
/** Interface defining the callback for client classes. */ /** Interface defining the callback for client classes. */
public interface DrawCallback { public interface DrawCallback {
public void drawCallback(final Canvas canvas); public void drawCallback(final Canvas canvas);
} }
} }
...@@ -18,111 +18,71 @@ package com.agenew.detection.env; ...@@ -18,111 +18,71 @@ package com.agenew.detection.env;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Typeface; import android.graphics.Typeface;
import java.util.Vector;
/** A class that encapsulates the tedious bits of rendering legible, bordered text onto a canvas. */ /**
* A class that encapsulates the tedious bits of rendering legible, bordered
* text onto a canvas.
*/
public class BorderedText { public class BorderedText {
private final Paint interiorPaint; private final Paint interiorPaint;
private final Paint exteriorPaint; private final Paint exteriorPaint;
private final float textSize; /**
* Creates a left-aligned bordered text object with a white interior, and a
/** * black exterior with the specified text size.
* Creates a left-aligned bordered text object with a white interior, and a black exterior with *
* the specified text size. * @param textSize text size in pixels
* */
* @param textSize text size in pixels public BorderedText(final float textSize) {
*/ this(Color.WHITE, Color.BLACK, textSize);
public BorderedText(final float textSize) { }
this(Color.WHITE, Color.BLACK, textSize);
} /**
* Create a bordered text object with the specified interior and exterior
/** * colors, text size and alignment.
* Create a bordered text object with the specified interior and exterior colors, text size and *
* alignment. * @param interiorColor the interior text color
* * @param exteriorColor the exterior text color
* @param interiorColor the interior text color * @param textSize text size in pixels
* @param exteriorColor the exterior text color */
* @param textSize text size in pixels public BorderedText(final int interiorColor, final int exteriorColor, final float textSize) {
*/ interiorPaint = new Paint();
public BorderedText(final int interiorColor, final int exteriorColor, final float textSize) { interiorPaint.setTextSize(textSize);
interiorPaint = new Paint(); interiorPaint.setColor(interiorColor);
interiorPaint.setTextSize(textSize); interiorPaint.setStyle(Style.FILL);
interiorPaint.setColor(interiorColor); interiorPaint.setAntiAlias(false);
interiorPaint.setStyle(Style.FILL); interiorPaint.setAlpha(255);
interiorPaint.setAntiAlias(false);
interiorPaint.setAlpha(255); exteriorPaint = new Paint();
exteriorPaint.setTextSize(textSize);
exteriorPaint = new Paint(); exteriorPaint.setColor(exteriorColor);
exteriorPaint.setTextSize(textSize); exteriorPaint.setStyle(Style.FILL_AND_STROKE);
exteriorPaint.setColor(exteriorColor); exteriorPaint.setStrokeWidth(textSize / 8);
exteriorPaint.setStyle(Style.FILL_AND_STROKE); exteriorPaint.setAntiAlias(false);
exteriorPaint.setStrokeWidth(textSize / 8); exteriorPaint.setAlpha(255);
exteriorPaint.setAntiAlias(false); }
exteriorPaint.setAlpha(255);
public void setTypeface(Typeface typeface) {
this.textSize = textSize; interiorPaint.setTypeface(typeface);
} exteriorPaint.setTypeface(typeface);
}
public void setTypeface(Typeface typeface) {
interiorPaint.setTypeface(typeface); public void drawText(final Canvas canvas, final float posX, final float posY, final String text) {
exteriorPaint.setTypeface(typeface); canvas.drawText(text, posX, posY, exteriorPaint);
} canvas.drawText(text, posX, posY, interiorPaint);
}
public void drawText(final Canvas canvas, final float posX, final float posY, final String text) {
canvas.drawText(text, posX, posY, exteriorPaint); public void drawText(final Canvas canvas, final float posX, final float posY, final String text, Paint bgPaint) {
canvas.drawText(text, posX, posY, interiorPaint);
} float width = exteriorPaint.measureText(text);
float textSize = exteriorPaint.getTextSize();
public void drawText( Paint paint = new Paint(bgPaint);
final Canvas canvas, final float posX, final float posY, final String text, Paint bgPaint) { paint.setStyle(Paint.Style.FILL);
paint.setAlpha(160);
float width = exteriorPaint.measureText(text); canvas.drawRect(posX, (posY + (int) (textSize)), (posX + (int) (width)), posY, paint);
float textSize = exteriorPaint.getTextSize();
Paint paint = new Paint(bgPaint); canvas.drawText(text, posX, (posY + textSize), interiorPaint);
paint.setStyle(Paint.Style.FILL); }
paint.setAlpha(160);
canvas.drawRect(posX, (posY + (int) (textSize)), (posX + (int) (width)), posY, paint);
canvas.drawText(text, posX, (posY + textSize), interiorPaint);
}
public void drawLines(Canvas canvas, final float posX, final float posY, Vector<String> lines) {
int lineNum = 0;
for (final String line : lines) {
drawText(canvas, posX, posY - getTextSize() * (lines.size() - lineNum - 1), line);
++lineNum;
}
}
public void setInteriorColor(final int color) {
interiorPaint.setColor(color);
}
public void setExteriorColor(final int color) {
exteriorPaint.setColor(color);
}
public float getTextSize() {
return textSize;
}
public void setAlpha(final int alpha) {
interiorPaint.setAlpha(alpha);
exteriorPaint.setAlpha(alpha);
}
public void getTextBounds(
final String line, final int index, final int count, final Rect lineBounds) {
interiorPaint.getTextBounds(line, index, count, lineBounds);
}
public void setTextAlign(final Align align) {
interiorPaint.setTextAlign(align);
exteriorPaint.setTextAlign(align);
}
} }
...@@ -19,168 +19,131 @@ import android.util.Log; ...@@ -19,168 +19,131 @@ import android.util.Log;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
/** Wrapper for the platform log function, allows convenient message prefixing and log disabling. */ /**
* Wrapper for the platform log function, allows convenient message prefixing
* and log disabling.
*/
public final class Logger { public final class Logger {
private static final String DEFAULT_TAG = "tensorflow"; private static final String DEFAULT_TAG = "tensorflow";
private static final int DEFAULT_MIN_LOG_LEVEL = Log.DEBUG; private static final int DEFAULT_MIN_LOG_LEVEL = Log.DEBUG;
// Classes to be ignored when examining the stack trace // Classes to be ignored when examining the stack trace
private static final Set<String> IGNORED_CLASS_NAMES; private static final Set<String> IGNORED_CLASS_NAMES;
static { static {
IGNORED_CLASS_NAMES = new HashSet<String>(3); IGNORED_CLASS_NAMES = new HashSet<String>(3);
IGNORED_CLASS_NAMES.add("dalvik.system.VMStack"); IGNORED_CLASS_NAMES.add("dalvik.system.VMStack");
IGNORED_CLASS_NAMES.add("java.lang.Thread"); IGNORED_CLASS_NAMES.add("java.lang.Thread");
IGNORED_CLASS_NAMES.add(Logger.class.getCanonicalName()); IGNORED_CLASS_NAMES.add(Logger.class.getCanonicalName());
} }
private final String tag; private final String tag;
private final String messagePrefix; private final String messagePrefix;
private int minLogLevel = DEFAULT_MIN_LOG_LEVEL; private int minLogLevel = DEFAULT_MIN_LOG_LEVEL;
/** /**
* Creates a Logger using the class name as the message prefix. * Creates a Logger with a custom tag and a custom message prefix. If the
* * message prefix is set to
* @param clazz the simple name of this class is used as the message prefix. *
*/ * <pre>
public Logger(final Class<?> clazz) { * null
this(clazz.getSimpleName()); * </pre>
} *
* , the caller's class name is used as the prefix.
/** *
* Creates a Logger using the specified message prefix. * @param tag identifies the source of a log message.
* * @param messagePrefix prepended to every message if non-null. If null, the
* @param messagePrefix is prepended to the text of every message. * name of the caller is being used
*/ */
public Logger(final String messagePrefix) { public Logger(final String tag, final String messagePrefix) {
this(DEFAULT_TAG, messagePrefix); this.tag = tag;
} final String prefix = messagePrefix == null ? getCallerSimpleName() : messagePrefix;
this.messagePrefix = (prefix.length() > 0) ? prefix + ": " : prefix;
/** }
* Creates a Logger with a custom tag and a custom message prefix. If the message prefix is set to
* /** Creates a Logger using the caller's class name as the message prefix. */
* <pre>null</pre> public Logger() {
* this(DEFAULT_TAG, null);
* , the caller's class name is used as the prefix. }
*
* @param tag identifies the source of a log message. /**
* @param messagePrefix prepended to every message if non-null. If null, the name of the caller is * Return caller's simple name.
* being used *
*/ * <p>
public Logger(final String tag, final String messagePrefix) { * Android getStackTrace() returns an array that looks like this: stackTrace[0]:
this.tag = tag; * dalvik.system.VMStack stackTrace[1]: java.lang.Thread stackTrace[2]:
final String prefix = messagePrefix == null ? getCallerSimpleName() : messagePrefix; * com.google.android.apps.unveil.env.UnveilLogger stackTrace[3]:
this.messagePrefix = (prefix.length() > 0) ? prefix + ": " : prefix; * com.google.android.apps.unveil.BaseApplication
} *
* <p>
/** Creates a Logger using the caller's class name as the message prefix. */ * This function returns the simple version of the first non-filtered name.
public Logger() { *
this(DEFAULT_TAG, null); * @return caller's simple name
} */
private static String getCallerSimpleName() {
/** Creates a Logger using the caller's class name as the message prefix. */ // Get the current callstack so we can pull the class of the caller off of it.
public Logger(final int minLogLevel) { final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
this(DEFAULT_TAG, null);
this.minLogLevel = minLogLevel; for (final StackTraceElement elem : stackTrace) {
} final String className = elem.getClassName();
if (!IGNORED_CLASS_NAMES.contains(className)) {
/** // We're only interested in the simple name of the class, not the complete
* Return caller's simple name. // package.
* final String[] classParts = className.split("\\.");
* <p>Android getStackTrace() returns an array that looks like this: stackTrace[0]: return classParts[classParts.length - 1];
* dalvik.system.VMStack stackTrace[1]: java.lang.Thread stackTrace[2]: }
* com.google.android.apps.unveil.env.UnveilLogger stackTrace[3]: }
* com.google.android.apps.unveil.BaseApplication
* return Logger.class.getSimpleName();
* <p>This function returns the simple version of the first non-filtered name. }
*
* @return caller's simple name public boolean isLoggable(final int logLevel) {
*/ return logLevel >= minLogLevel || Log.isLoggable(tag, logLevel);
private static String getCallerSimpleName() { }
// Get the current callstack so we can pull the class of the caller off of it.
final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); private String toMessage(final String format, final Object... args) {
return messagePrefix + (args.length > 0 ? String.format(format, args) : format);
for (final StackTraceElement elem : stackTrace) { }
final String className = elem.getClassName();
if (!IGNORED_CLASS_NAMES.contains(className)) { public void v(final String format, final Object... args) {
// We're only interested in the simple name of the class, not the complete package. if (isLoggable(Log.VERBOSE)) {
final String[] classParts = className.split("\\."); Log.v(tag, toMessage(format, args));
return classParts[classParts.length - 1]; }
} }
}
public void d(final String format, final Object... args) {
return Logger.class.getSimpleName(); if (isLoggable(Log.DEBUG)) {
} Log.d(tag, toMessage(format, args));
}
public void setMinLogLevel(final int minLogLevel) { }
this.minLogLevel = minLogLevel;
} public void i(final String format, final Object... args) {
if (isLoggable(Log.INFO)) {
public boolean isLoggable(final int logLevel) { Log.i(tag, toMessage(format, args));
return logLevel >= minLogLevel || Log.isLoggable(tag, logLevel); }
} }
private String toMessage(final String format, final Object... args) { public void i(final Throwable t, final String format, final Object... args) {
return messagePrefix + (args.length > 0 ? String.format(format, args) : format); if (isLoggable(Log.INFO)) {
} Log.i(tag, toMessage(format, args), t);
}
public void v(final String format, final Object... args) { }
if (isLoggable(Log.VERBOSE)) {
Log.v(tag, toMessage(format, args)); public void w(final String format, final Object... args) {
} if (isLoggable(Log.WARN)) {
} Log.w(tag, toMessage(format, args));
}
public void v(final Throwable t, final String format, final Object... args) { }
if (isLoggable(Log.VERBOSE)) {
Log.v(tag, toMessage(format, args), t); public void e(final String format, final Object... args) {
} if (isLoggable(Log.ERROR)) {
} Log.e(tag, toMessage(format, args));
}
public void d(final String format, final Object... args) { }
if (isLoggable(Log.DEBUG)) {
Log.d(tag, toMessage(format, args)); public void e(final Throwable t, final String format, final Object... args) {
} if (isLoggable(Log.ERROR)) {
} Log.e(tag, toMessage(format, args), t);
}
public void d(final Throwable t, final String format, final Object... args) { }
if (isLoggable(Log.DEBUG)) {
Log.d(tag, toMessage(format, args), t);
}
}
public void i(final String format, final Object... args) {
if (isLoggable(Log.INFO)) {
Log.i(tag, toMessage(format, args));
}
}
public void i(final Throwable t, final String format, final Object... args) {
if (isLoggable(Log.INFO)) {
Log.i(tag, toMessage(format, args), t);
}
}
public void w(final String format, final Object... args) {
if (isLoggable(Log.WARN)) {
Log.w(tag, toMessage(format, args));
}
}
public void w(final Throwable t, final String format, final Object... args) {
if (isLoggable(Log.WARN)) {
Log.w(tag, toMessage(format, args), t);
}
}
public void e(final String format, final Object... args) {
if (isLoggable(Log.ERROR)) {
Log.e(tag, toMessage(format, args));
}
}
public void e(final Throwable t, final String format, final Object... args) {
if (isLoggable(Log.ERROR)) {
Log.e(tag, toMessage(format, args), t);
}
}
} }
/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
package com.agenew.detection.env;
import android.graphics.Bitmap;
import android.text.TextUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/** Size class independent of a Camera object. */
public class Size implements Comparable<Size>, Serializable {
// 1.4 went out with this UID so we'll need to maintain it to preserve pending queries when
// upgrading.
public static final long serialVersionUID = 7689808733290872361L;
public final int width;
public final int height;
public Size(final int width, final int height) {
this.width = width;
this.height = height;
}
public Size(final Bitmap bmp) {
this.width = bmp.getWidth();
this.height = bmp.getHeight();
}
/**
* Rotate a size by the given number of degrees.
*
* @param size Size to rotate.
* @param rotation Degrees {0, 90, 180, 270} to rotate the size.
* @return Rotated size.
*/
public static Size getRotatedSize(final Size size, final int rotation) {
if (rotation % 180 != 0) {
// The phone is portrait, therefore the camera is sideways and frame should be rotated.
return new Size(size.height, size.width);
}
return size;
}
public static Size parseFromString(String sizeString) {
if (TextUtils.isEmpty(sizeString)) {
return null;
}
sizeString = sizeString.trim();
// The expected format is "<width>x<height>".
final String[] components = sizeString.split("x");
if (components.length == 2) {
try {
final int width = Integer.parseInt(components[0]);
final int height = Integer.parseInt(components[1]);
return new Size(width, height);
} catch (final NumberFormatException e) {
return null;
}
} else {
return null;
}
}
public static List<Size> sizeStringToList(final String sizes) {
final List<Size> sizeList = new ArrayList<Size>();
if (sizes != null) {
final String[] pairs = sizes.split(",");
for (final String pair : pairs) {
final Size size = Size.parseFromString(pair);
if (size != null) {
sizeList.add(size);
}
}
}
return sizeList;
}
public static String sizeListToString(final List<Size> sizes) {
String sizesString = "";
if (sizes != null && sizes.size() > 0) {
sizesString = sizes.get(0).toString();
for (int i = 1; i < sizes.size(); i++) {
sizesString += "," + sizes.get(i).toString();
}
}
return sizesString;
}
public static final String dimensionsAsString(final int width, final int height) {
return width + "x" + height;
}
public final float aspectRatio() {
return (float) width / (float) height;
}
@Override
public int compareTo(final Size other) {
return width * height - other.width * other.height;
}
@Override
public boolean equals(final Object other) {
if (other == null) {
return false;
}
if (!(other instanceof Size)) {
return false;
}
final Size otherSize = (Size) other;
return (width == otherSize.width && height == otherSize.height);
}
@Override
public int hashCode() {
return width * 32713 + height;
}
@Override
public String toString() {
return dimensionsAsString(width, height);
}
}
package com.agenew.detection.env; package com.agenew.detection.env;
import android.content.Context;
import android.content.res.AssetFileDescriptor; import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.os.Environment;
import android.util.Log; import android.util.Log;
import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.MappedByteBuffer; import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
...@@ -63,149 +54,4 @@ public class Utils { ...@@ -63,149 +54,4 @@ public class Utils {
return result; return result;
} }
public static void softmax(final float[] vals) {
float max = Float.NEGATIVE_INFINITY;
for (final float val : vals) {
max = Math.max(max, val);
}
float sum = 0.0f;
for (int i = 0; i < vals.length; ++i) {
vals[i] = (float) Math.exp(vals[i] - max);
sum += vals[i];
}
for (int i = 0; i < vals.length; ++i) {
vals[i] = vals[i] / sum;
}
}
public static float expit(final float x) {
return (float) (1. / (1. + Math.exp(-x)));
}
// public static Bitmap scale(Context context, String filePath) {
// AssetManager assetManager = context.getAssets();
//
// InputStream istr;
// Bitmap bitmap = null;
// try {
// istr = assetManager.open(filePath);
// bitmap = BitmapFactory.decodeStream(istr);
// bitmap = Bitmap.createScaledBitmap(bitmap, MainActivity.TF_OD_API_INPUT_SIZE, MainActivity.TF_OD_API_INPUT_SIZE, false);
// } catch (IOException e) {
// // handle exception
// Log.e("getBitmapFromAsset", "getBitmapFromAsset: " + e.getMessage());
// }
//
// return bitmap;
// }
public static Bitmap getBitmapFromAsset(Context context, String filePath) {
AssetManager assetManager = context.getAssets();
InputStream istr;
Bitmap bitmap = null;
try {
istr = assetManager.open(filePath);
bitmap = BitmapFactory.decodeStream(istr);
// return bitmap.copy(Bitmap.Config.ARGB_8888,true);
} catch (IOException e) {
// handle exception
Log.e("getBitmapFromAsset", "getBitmapFromAsset: " + e.getMessage());
}
return bitmap;
}
/**
* Returns a transformation matrix from one reference frame into another.
* Handles cropping (if maintaining aspect ratio is desired) and rotation.
*
* @param srcWidth Width of source frame.
* @param srcHeight Height of source frame.
* @param dstWidth Width of destination frame.
* @param dstHeight Height of destination frame.
* @param applyRotation Amount of rotation to apply from one frame to
* another. Must be a multiple of 90.
* @param maintainAspectRatio If true, will ensure that scaling in x and y
* remains constant, cropping the image if necessary.
* @return The transformation fulfilling the desired requirements.
*/
public static Matrix getTransformationMatrix(final int srcWidth, final int srcHeight, final int dstWidth,
final int dstHeight, final int applyRotation, final boolean maintainAspectRatio) {
final Matrix matrix = new Matrix();
if (applyRotation != 0) {
// Translate so center of image is at origin.
matrix.postTranslate(-srcWidth / 2.0f, -srcHeight / 2.0f);
// Rotate around origin.
matrix.postRotate(applyRotation);
}
// Account for the already applied rotation, if any, and then determine how
// much scaling is needed for each axis.
final boolean transpose = (Math.abs(applyRotation) + 90) % 180 == 0;
final int inWidth = transpose ? srcHeight : srcWidth;
final int inHeight = transpose ? srcWidth : srcHeight;
// Apply scaling if necessary.
if (inWidth != dstWidth || inHeight != dstHeight) {
final float scaleFactorX = dstWidth / (float) inWidth;
final float scaleFactorY = dstHeight / (float) inHeight;
if (maintainAspectRatio) {
// Scale by minimum factor so that dst is filled completely while
// maintaining the aspect ratio. Some image may fall off the edge.
final float scaleFactor = Math.max(scaleFactorX, scaleFactorY);
matrix.postScale(scaleFactor, scaleFactor);
} else {
// Scale exactly to fill dst from src.
matrix.postScale(scaleFactorX, scaleFactorY);
}
}
if (applyRotation != 0) {
// Translate back from origin centered reference to destination frame.
matrix.postTranslate(dstWidth / 2.0f, dstHeight / 2.0f);
}
return matrix;
}
public static Bitmap processBitmap(Bitmap source, int size) {
int image_height = source.getHeight();
int image_width = source.getWidth();
Bitmap croppedBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Matrix frameToCropTransformations = getTransformationMatrix(image_width, image_height, size, size, 0, false);
Matrix cropToFrameTransformations = new Matrix();
frameToCropTransformations.invert(cropToFrameTransformations);
final Canvas canvas = new Canvas(croppedBitmap);
canvas.drawBitmap(source, frameToCropTransformations, null);
return croppedBitmap;
}
public static void writeToFile(String data, Context context) {
try {
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "myFile.txt";
File file = new File(baseDir + File.separator + fileName);
FileOutputStream stream = new FileOutputStream(file);
try {
stream.write(data.getBytes());
} finally {
stream.close();
}
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
} }
...@@ -34,8 +34,6 @@ public interface Classifier { ...@@ -34,8 +34,6 @@ public interface Classifier {
void setNumThreads(int num_threads); void setNumThreads(int num_threads);
void setUseNNAPI(boolean isChecked);
abstract float getObjThresh(); abstract float getObjThresh();
/** /**
......
...@@ -5,30 +5,19 @@ import android.content.res.AssetManager; ...@@ -5,30 +5,19 @@ import android.content.res.AssetManager;
import java.io.IOException; import java.io.IOException;
public class DetectorFactory { public class DetectorFactory {
public static YoloV5Classifier getDetector( public static YoloV5Classifier getDetector(final AssetManager assetManager, final String modelFilename)
final AssetManager assetManager, throws IOException {
final String modelFilename) String labelFilename = null;
throws IOException { boolean isQuantized = false;
String labelFilename = null; int inputSize = 0;
boolean isQuantized = false;
int inputSize = 0;
int[] output_width = new int[]{0};
int[][] masks = new int[][]{{0}};
int[] anchors = new int[]{0};
if (modelFilename.endsWith(".tflite")) { if (modelFilename.endsWith(".tflite")) {
labelFilename = "file:///android_asset/class.txt"; labelFilename = "file:///android_asset/class.txt";
isQuantized = modelFilename.endsWith("-int8.tflite"); isQuantized = modelFilename.endsWith("-int8.tflite");
inputSize = 640; inputSize = 640;
output_width = new int[]{80, 40, 20}; }
masks = new int[][]{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
anchors = new int[]{
10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
};
}
return YoloV5Classifier.create(assetManager, modelFilename, labelFilename, isQuantized, return YoloV5Classifier.create(assetManager, modelFilename, labelFilename, isQuantized, inputSize);
inputSize); }
}
} }
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0"/>
<item
android:color="#00000000"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@android:color/white"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@android:color/white"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
<resources>
<!-- Base application theme. -->
<style name="AppTheme.ObjectDetection" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/tfe_color_primary</item>
<item name="colorPrimaryDark">@color/tfe_color_primary_dark</item>
<item name="colorAccent">@color/tfe_color_accent</item>
</style>
</resources>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!