(*labelEnv);
+
+ labelNet->ReleaseNets();
+
+ return (jboolean) true;
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/cpp/MindSporeNetnative.h b/model_zoo/official/lite/car_classification/app/src/main/cpp/MindSporeNetnative.h
new file mode 100644
index 0000000000..92707373fe
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/cpp/MindSporeNetnative.h
@@ -0,0 +1,21 @@
+/**
+ * Copyright 2021 Huawei Technologies Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
+#define MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
+
+
+#endif // MINDSPORE_JNI_HMS_DEBUG_MINDSPORENETNATIVE_H
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/BitmapUtils.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/BitmapUtils.java
new file mode 100644
index 0000000000..5cdc7e6179
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/BitmapUtils.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright 2020 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.gallery.classify;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.media.ExifInterface;
+import android.net.Uri;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BitmapUtils {
+ private static final String TAG = "BitmapUtils";
+
+ public static void recycleBitmap(Bitmap... bitmaps) {
+ for (Bitmap bitmap : bitmaps) {
+ if (bitmap != null && !bitmap.isRecycled()) {
+ bitmap.recycle();
+ bitmap = null;
+ }
+ }
+ }
+
+ public static Bitmap getBitmapFormUri(Activity ac, Uri uri) {
+ Bitmap bitmap = null;
+ try {
+ InputStream input = ac.getContentResolver().openInputStream(uri);
+ BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
+ onlyBoundsOptions.inJustDecodeBounds = true;
+ onlyBoundsOptions.inDither = true;//optional
+ onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
+ BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
+ input.close();
+ int originalWidth = onlyBoundsOptions.outWidth;
+ int originalHeight = onlyBoundsOptions.outHeight;
+ if ((originalWidth == -1) || (originalHeight == -1))
+ return null;
+ float hh = 1920f;
+ float ww = 1080f;
+ int be = 1;
+ if (originalWidth > originalHeight && originalWidth > ww) {
+ be = (int) (originalWidth / ww);
+ } else if (originalWidth < originalHeight && originalHeight > hh) {
+ be = (int) (originalHeight / hh);
+ }
+ if (be <= 0) {
+ be = 1;
+ }
+ BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
+ bitmapOptions.inSampleSize = be;
+ bitmapOptions.inDither = true;//optional
+ bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
+ input = ac.getContentResolver().openInputStream(uri);
+ bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
+ input.close();
+
+
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return compressImage(bitmap);
+ }
+
+
+ public static Bitmap compressImage(Bitmap image) {
+ if (image != null) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
+ int options = 100;
+ while (baos.toByteArray().length / 1024 > 100) {
+ baos.reset();
+ image.compress(Bitmap.CompressFormat.JPEG, options, baos);
+ options -= 10;
+ }
+ ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
+ Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
+ return bitmap;
+ }else {
+ return null;
+ }
+ }
+
+ public static File getFileFromMediaUri(Context ac, Uri uri) {
+ if (uri.getScheme().toString().compareTo("content") == 0) {
+ ContentResolver cr = ac.getContentResolver();
+ Cursor cursor = cr.query(uri, null, null, null, null);
+ if (cursor != null) {
+ cursor.moveToFirst();
+ String filePath = cursor.getString(cursor.getColumnIndex("_data"));
+ cursor.close();
+ if (filePath != null) {
+ return new File(filePath);
+ }
+ }
+ } else if (uri.getScheme().toString().compareTo("file") == 0) {
+ return new File(uri.toString().replace("file://", ""));
+ }
+ return null;
+ }
+
+ public static int getBitmapDegree(String path) {
+ int degree = 0;
+ try {
+ ExifInterface exifInterface = new ExifInterface(path);
+ int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
+ ExifInterface.ORIENTATION_NORMAL);
+ switch (orientation) {
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ degree = 90;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ degree = 180;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ degree = 270;
+ break;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return degree;
+ }
+
+ public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
+ Bitmap returnBm = null;
+ Matrix matrix = new Matrix();
+ matrix.postRotate(degree);
+ try {
+ returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
+ } catch (OutOfMemoryError e) {
+ }
+ if (returnBm == null) {
+ returnBm = bm;
+ }
+ if (bm != returnBm) {
+ bm.recycle();
+ }
+ return returnBm;
+ }
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/CompareSizesByArea.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/CompareSizesByArea.java
new file mode 100644
index 0000000000..3a187fb842
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/CompareSizesByArea.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright 2021 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.gallery.classify;
+
+import android.util.Size;
+import java.util.Comparator;
+
+/**
+ * Data comparator.
+ */
+
+public class CompareSizesByArea implements Comparator {
+
+ @Override
+ public int compare(Size lhs, Size rhs) {
+ // We cast here to ensure the multiplications won't overflow
+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
+ }
+
+}
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/ImageTrackingMobile.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/ImageTrackingMobile.java
new file mode 100644
index 0000000000..ac951e8a1f
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/ImageTrackingMobile.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2020 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.gallery.classify;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * Call the MindSpore interface API in the Java layer.
+ */
+public class ImageTrackingMobile {
+ private final static String TAG = "ImageTrackingMobile";
+
+ static {
+ try {
+ System.loadLibrary("mlkit-label-MS");
+ Log.i(TAG, "load libiMindSpore.so successfully.");
+ } catch (UnsatisfiedLinkError e) {
+ Log.e(TAG, "UnsatisfiedLinkError >>>>>>" + e.getMessage());
+ }
+ }
+
+ // The address of the running inference environment.
+ private long netEnv = 0;
+
+ private final Context mActivity;
+
+ public ImageTrackingMobile(Context activity) {
+ this.mActivity = activity;
+ }
+
+ /**
+ * JNI load model and also create model inference environment.
+ *
+ * @param modelBuffer Model buffer.
+ * @param numThread The num of thread.
+ * @return MindSpore Inference environment address.
+ */
+ public native long loadModel(ByteBuffer modelBuffer, int numThread);
+
+ /**
+ * Running model.
+ *
+ * @param netEnv Inference environment address.
+ * @param img A picture to be inferred.
+ * @return Inference result
+ */
+ public native String runNet(long netEnv, Bitmap img);
+
+ /**
+ * Unbind model data.
+ *
+ * @param netEnv Inference environment address.
+ * @return Unbound state.
+ */
+ public native boolean unloadModel(long netEnv);
+
+ /**
+ * The C++ side is encapsulated into a method of the MSNetWorks class
+ *
+ * @param modelPath Model file location
+ * @return Load model file status
+ */
+ public boolean loadModelFromBuf(String modelPath) {
+ ByteBuffer buffer = loadModelFile(modelPath);
+ netEnv = loadModel(buffer, 2); //numThread's default setting is 2.
+ if (netEnv == 0) { // Loading model failed.
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Run MindSpore inference.
+ */
+ public String MindSpore_runnet(Bitmap img) {
+ String ret_str = runNet(netEnv, img);
+ return ret_str;
+ }
+
+ /**
+ * Unload model.
+ *
+ * @return true
+ */
+ public boolean unloadModel() {
+ unloadModel(netEnv);
+ return true;
+ }
+
+ /**
+ * Load model file stream.
+ *
+ * @param modelPath Model file path.
+ * @return Model ByteBuffer.
+ */
+ public ByteBuffer loadModelFile(String modelPath) {
+ InputStream is = null;
+ try {
+ is = mActivity.getAssets().open(modelPath);
+ byte[] bytes = new byte[is.available()];
+ is.read(bytes);
+ return ByteBuffer.allocateDirect(bytes.length).put(bytes);
+ } catch (Exception e) {
+ Log.d("loadModelFile", " Exception occur. ");
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ return null;
+ }
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/RecognitionImageBean.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/RecognitionImageBean.java
new file mode 100644
index 0000000000..4fb7c6e6f9
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/RecognitionImageBean.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright 2020 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.gallery.classify;
+
+public class RecognitionImageBean {
+
+ private String name;
+ private float score;
+
+ public RecognitionImageBean(String name, float score) {
+ this.name = name;
+ this.score = score;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public float getScore() {
+ return score;
+ }
+
+ public void setScore(float score) {
+ this.score = score;
+ }
+
+
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/TrackingMobile.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/TrackingMobile.java
new file mode 100644
index 0000000000..bcc96730fe
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/gallery/classify/TrackingMobile.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2021 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.gallery.classify;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * Call the MindSpore interface API in the Java layer.
+ */
+public class TrackingMobile {
+ private final static String TAG = "TrackingMobile";
+
+ static {
+ try {
+ System.loadLibrary("mlkit-label-MS");
+ Log.i(TAG, "load libiMindSpore.so successfully.");
+ } catch (UnsatisfiedLinkError e) {
+ Log.e(TAG, "UnsatisfiedLinkError " + e.getMessage());
+ }
+ }
+
+ // The address of the running inference environment.
+ private long netEnv = 0;
+
+ private final Context mActivity;
+
+ public TrackingMobile(Context activity) {
+ this.mActivity = activity;
+ }
+
+ /**
+ * JNI load model and also create model inference environment.
+ *
+ * @param modelBuffer Model buffer.
+ * @param numThread The num of thread.
+ * @return MindSpore Inference environment address.
+ */
+ public native long loadModel(ByteBuffer modelBuffer, int numThread);
+
+ /**
+ * Running model.
+ *
+ * @param netEnv Inference environment address.
+ * @param img A picture to be inferred.
+ * @return Inference result
+ */
+ public native String runNet(long netEnv, Bitmap img);
+
+ /**
+ * Unbind model data.
+ *
+ * @param netEnv Inference environment address.
+ * @return Unbound state.
+ */
+ public native boolean unloadModel(long netEnv);
+
+ /**
+ * The C++ side is encapsulated into a method of the MSNetWorks class
+ *
+ * @param modelPath Model file location
+ * @return Load model file status
+ */
+ public boolean loadModelFromBuf(String modelPath) {
+ ByteBuffer buffer = loadModelFile(modelPath);
+ netEnv = loadModel(buffer, 2); //numThread's default setting is 2.
+ if (netEnv == 0){ // Loading model failed.
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Run MindSpore inference.
+ */
+ public String MindSpore_runnet(Bitmap img) {
+ String ret_str = runNet(netEnv, img);
+ return ret_str;
+ }
+
+ /**
+ * Unload model.
+ * @return true
+ */
+ public boolean unloadModel() {
+ unloadModel(netEnv);
+ return true;
+ }
+
+ /**
+ * Load model file stream.
+ * @param modelPath Model file path.
+ * @return Model ByteBuffer.
+ */
+ public ByteBuffer loadModelFile(String modelPath) {
+ InputStream is = null;
+ try {
+ is = new FileInputStream(modelPath);
+// is = mActivity.getAssets().open(modelPath);
+ byte[] bytes = new byte[is.available()];
+ is.read(bytes);
+ return ByteBuffer.allocateDirect(bytes.length).put(bytes);
+ } catch (Exception e) {
+ Log.d("loadModelFile", " Exception occur. ");
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ return null;
+ }
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/AutoFitTextureView.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/AutoFitTextureView.java
new file mode 100644
index 0000000000..f2123c6ebe
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/AutoFitTextureView.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2021 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.TextureView;
+
+public class AutoFitTextureView extends TextureView {
+
+ private int mRatioWidth = 0;
+ private int mRatioHeight = 0;
+
+ public AutoFitTextureView(Context context) {
+ this(context, null);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
+ * calculated from the parameters. Note that the actual sizes 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
+ */
+ public void setAspectRatio(int width, int height) {
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Size cannot be negative.");
+ }
+ mRatioWidth = width;
+ mRatioHeight = height;
+ requestLayout();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (0 == mRatioWidth || 0 == mRatioHeight) {
+ setMeasuredDimension(width, height);
+ } else {
+ if (width > height * mRatioWidth / mRatioHeight) {
+ setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
+ } else {
+ setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
+ }
+ }
+ }
+
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/CameraActivity.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/CameraActivity.java
new file mode 100644
index 0000000000..f68ba3606c
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/CameraActivity.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright 2021 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.widget;
+
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.mindspore.classificationforcar.R;
+import com.mindspore.classificationforcar.gallery.classify.ImageTrackingMobile;
+import com.mindspore.classificationforcar.gallery.classify.RecognitionImageBean;
+import com.mindspore.classificationforcar.gallery.classify.TrackingMobile;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * The main interface of camera preview.
+ * Using Camera 2 API.
+ */
+public class CameraActivity extends AppCompatActivity {
+ private static final String TAG = "CameraActivity";
+ private static final String IMAGE_SCENE_MS = "model/mobilenetv2.ms";
+
+ private String filePath;
+ private boolean isCarModel;
+ private TrackingMobile trackingMobile;
+ private ImageTrackingMobile imageTrackingMobile;
+
+ private TextView resultText;
+ private List recognitionObjectBeanList;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(TAG, "onCreate");
+ setContentView(R.layout.activity_camera);
+
+ filePath = getIntent().getStringExtra("FILEPATH");
+ isCarModel = getIntent().getBooleanExtra("ISHASCARMODELFILE", false);
+ resultText = findViewById(R.id.textResult);
+
+ if (isCarModel) {
+ trackingMobile = new TrackingMobile(this);
+ boolean ret = trackingMobile.loadModelFromBuf(filePath);
+ if (!ret) {
+ Log.e(TAG, "Load model error.");
+ return;
+ }
+ } else {
+ imageTrackingMobile = new ImageTrackingMobile(this);
+ boolean ret = imageTrackingMobile.loadModelFromBuf(IMAGE_SCENE_MS);
+ if (!ret) {
+ Log.e(TAG, "Load model error.");
+ return;
+ }
+ }
+ addCameraFragment();
+ }
+
+ protected void addCameraFragment() {
+ CameraFragment cameraFragment = CameraFragment.newInstance(bitmap -> {
+ runOnUiThread(() -> initMindspore(bitmap));
+ });
+
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.container, cameraFragment)
+ .commitAllowingStateLoss();
+ }
+
+
+ private void initMindspore(Bitmap bitmap) {
+ // run net.
+ if (isCarModel) {
+ long startTime = System.currentTimeMillis();
+ String result = trackingMobile.MindSpore_runnet(bitmap);
+ long endTime = System.currentTimeMillis();
+ resultText.setText(TextUtils.isEmpty(result) ? "正在识别..." : result);
+ Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
+ Log.d(TAG, "result:" + result);
+ } else {
+ if (recognitionObjectBeanList != null) {
+ recognitionObjectBeanList.clear();
+ } else {
+ recognitionObjectBeanList = new ArrayList<>();
+ }
+
+ long startTime = System.currentTimeMillis();
+ String result = imageTrackingMobile.MindSpore_runnet(bitmap);
+ long endTime = System.currentTimeMillis();
+ Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
+ Log.d(TAG, "result:" + result);
+ if (!TextUtils.isEmpty(result)) {
+ String[] resultArray = result.split(";");
+ for (String singleRecognitionResult : resultArray) {
+ String[] singleResult = singleRecognitionResult.split(":");
+ float score = Float.parseFloat(singleResult[1]);
+ if (score > 0.5) {
+ recognitionObjectBeanList.add(new RecognitionImageBean(singleResult[0], score));
+ }
+ }
+ Collections.sort(recognitionObjectBeanList, (t1, t2) -> Float.compare(t2.getScore(), t1.getScore()));
+ showResultsInBottomSheet(recognitionObjectBeanList, (endTime - startTime) + "ms");
+ }
+ }
+ }
+
+
+ @UiThread
+ protected void showResultsInBottomSheet(List list, String time) {
+ if (list == null || list.size() < 1) {
+ return;
+ }
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < list.size(); i++) {
+ RecognitionImageBean bean = list.get(i);
+ stringBuilder.append(bean.getName()).append("\r:\r").append(String.format("%.2f", (100 * bean.getScore())) + "%").append("\r\n");
+ if (i > 3) { // set maximum display is 3.
+ break;
+ }
+ }
+ resultText.setText(stringBuilder);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (trackingMobile != null) {
+ trackingMobile.unloadModel();
+ }
+ if (imageTrackingMobile != null) {
+ imageTrackingMobile.unloadModel();
+ }
+ }
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/CameraFragment.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/CameraFragment.java
new file mode 100644
index 0000000000..cc598441c0
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/CameraFragment.java
@@ -0,0 +1,782 @@
+/**
+ * Copyright 2021 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.widget;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.Log;
+import android.util.Size;
+import android.util.SparseIntArray;
+import android.view.LayoutInflater;
+import android.view.Surface;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.mindspore.classificationforcar.R;
+import com.mindspore.classificationforcar.gallery.classify.CompareSizesByArea;
+import com.mindspore.classificationforcar.gallery.classify.TrackingMobile;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class CameraFragment extends Fragment {
+
+ private static final String TAG = "CameraFragment";
+
+ private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
+
+ static {
+ ORIENTATIONS.append(Surface.ROTATION_0, 90);
+ ORIENTATIONS.append(Surface.ROTATION_90, 0);
+ ORIENTATIONS.append(Surface.ROTATION_180, 270);
+ ORIENTATIONS.append(Surface.ROTATION_270, 180);
+ }
+
+ private static final int MAX_PREVIEW_WIDTH = 1920;
+
+ private static final int MAX_PREVIEW_HEIGHT = 1280;
+
+ private Semaphore mCameraOpenCloseLock = new Semaphore(1);
+
+ private int mState = STATE_PREVIEW;
+
+ private static final int STATE_PREVIEW = 0;
+
+ private static final int STATE_WAITING_LOCK = 1;
+
+ private static final int STATE_WAITING_PRECAPTURE = 2;
+
+ private static final int STATE_WAITING_NON_PRECAPTURE = 3;
+
+ private static final int STATE_PICTURE_TAKEN = 4;
+
+ /**
+ * Data interface returned after identification.
+ */
+ private RecognitionDataCallBack recognitionDataCallBack;
+
+ private AutoFitTextureView mTextureView;
+
+ private boolean mFlashSupported;
+
+ private boolean isPreBackgroundThreadPause;
+
+
+ /**
+ * HandlerThread and Handler of camera and algorithm.
+ */
+ private HandlerThread mCameraHandlerThread, mMindsporeHandlerThread;
+
+ private Handler mCameraHandler, mMindsporeHandler;
+
+ private CameraManager mCameraManager;
+
+ private CameraCaptureSession mCaptureSession;
+
+ private CameraDevice mCameraDevice;
+
+ private String mCameraId;
+
+ private ImageReader mImageReader;
+
+ private CaptureRequest.Builder mPreviewRequestBuilder;
+
+ private CaptureRequest mPreviewRequest;
+
+ private File mFile;
+
+ private Size mPreviewSize;
+
+ private int mSensorOrientation;
+
+ private CameraDevice.StateCallback mCameraDeviceStateCallback;
+
+
+ private CameraFragment(RecognitionDataCallBack recognitionDataCallBack) {
+ this.recognitionDataCallBack = recognitionDataCallBack;
+ }
+
+ /**
+ * Singleton.
+ *
+ * @param recognitionDataCallBack Identify data return interface.
+ * @return Construction method.
+ */
+ public static CameraFragment newInstance(RecognitionDataCallBack recognitionDataCallBack) {
+ return new CameraFragment(recognitionDataCallBack);
+ }
+
+ /**
+ * Data interface returned after identification.
+ */
+ public interface RecognitionDataCallBack {
+
+ void onRecognitionDataCallBack(Bitmap bitmap);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_camera, container, false);
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ initChildThread();
+ initCameraManager();
+ initSelectCamera();
+ initHandlerMatchingSize();
+ initImageReader();
+ initTextureViewListener();
+ }
+
+ @Override
+ public void onPause() {
+ closeCamera();
+ stopBackgroundThread();
+ super.onPause();
+ }
+
+ private void initChildThread() {
+ mCameraHandlerThread = new HandlerThread("CAMERA2");
+ mCameraHandlerThread.start();
+ mCameraHandler = new Handler(mCameraHandlerThread.getLooper());
+
+ mMindsporeHandlerThread = new HandlerThread("MINDSPORE");
+ mMindsporeHandlerThread.start();
+ mMindsporeHandler = new Handler(mMindsporeHandlerThread.getLooper());
+ mMindsporeHandler.postDelayed(classifyRunnable, 500);
+ }
+
+
+ /**
+ * Detect time-consuming threads
+ */
+ private Runnable classifyRunnable = new Runnable() {
+ public void run() {
+ synchronized (CameraFragment.this) {
+ Bitmap bitmap = mTextureView.getBitmap();
+ if (bitmap != null) {
+ if (recognitionDataCallBack != null) {
+ // Interface returns data。
+ recognitionDataCallBack.onRecognitionDataCallBack(bitmap);
+ }
+ }
+ if (mMindsporeHandler != null && !isPreBackgroundThreadPause) {
+ mMindsporeHandler.postDelayed(classifyRunnable, 500);
+ }
+ }
+ }
+ };
+
+ private void initCameraManager() {
+ mCameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
+ }
+
+ private void initSelectCamera() {
+ try {
+ String[] cameraIdArray = mCameraManager.getCameraIdList();
+ for (String itemId : cameraIdArray) {
+ CameraCharacteristics itemCharacteristics = mCameraManager.getCameraCharacteristics(itemId);
+ Integer facing = itemCharacteristics.get(CameraCharacteristics.LENS_FACING);
+ if (facing == CameraCharacteristics.LENS_FACING_BACK) {
+ mCameraId = itemId;
+ break;
+ }
+
+ }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ if (mCameraId == null) {
+ Toast.makeText(getActivity(), getString(R.string.camera_error), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ private StreamConfigurationMap streamConfigurationMap;
+ private Size largest;
+
+ /**
+ * Calculate the camera resolution suitable for the current screen resolution.
+ */
+ private void initHandlerMatchingSize() {
+ try {
+ CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
+ streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ Size[] sizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);
+ largest = Collections.max(Arrays.asList(sizes), new CompareSizesByArea());
+
+ Boolean available = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+ mFlashSupported = available == null ? false : available;
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Initialize the picture.
+ */
+ private void initImageReader() {
+ final int W = 640;
+ final int H = 480;
+
+ mImageReader = ImageReader.newInstance(W, H, ImageFormat.JPEG, 30);
+ mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ mFile = new File(getActivity().getExternalFilesDir(null), System.currentTimeMillis() + ".jpg");
+ // Get the data frame and start the algorithm processing.
+ try {
+ // Get the next image from the ImageReader queue.
+ Image image = reader.acquireNextImage();
+ image.close();
+ } catch (Exception e) {
+ Log.e(TAG, "onImageAvailable: " + e.toString());
+ }
+ }
+ }, mCameraHandler);
+ }
+
+ /**
+ * TextureView.SurfaceTextureListener
+ */
+ private void initTextureViewListener() {
+ if (mTextureView.isAvailable()) {
+ openCamera(mTextureView.getMeasuredWidth(), mTextureView.getMeasuredHeight());
+ Log.d(TAG, "isAvailable: " + mTextureView.getWidth() + "--" + mTextureView.getHeight());
+ } else {
+ mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
+ openCamera(width, height);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
+ configureTransform(width, height);
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surfaceTexture) {
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) {
+
+ }
+ });
+ }
+ }
+
+
+ @SuppressLint("MissingPermission")
+ private void openCamera(int width, int height) {
+ setPreviewSize(width, height, streamConfigurationMap, largest);
+ configureTransform(width, height);
+
+ mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
+ @Override
+ public void onOpened(@NonNull CameraDevice cameraDevice) {
+ if (cameraDevice != null) {
+ mCameraOpenCloseLock.release();
+ mCameraDevice = cameraDevice;
+ createCameraPreviewSession();
+ }
+ }
+
+ @Override
+ public void onDisconnected(@NonNull CameraDevice cameraDevice) {
+ if (cameraDevice != null) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ }
+ }
+
+ @Override
+ public void onError(@NonNull CameraDevice cameraDevice, int i) {
+ if (cameraDevice != null) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ if (null != getActivity()) {
+ getActivity().finish();
+ }
+ }
+ }
+ };
+
+
+ try {
+ if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Time out waiting to lock ic_launcher opening.");
+ }
+ mCameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock ic_launcher opening.", e);
+ }
+
+
+ }
+
+
+ /**
+ * Open camera preview.
+ */
+ private void createCameraPreviewSession() {
+ try {
+ SurfaceTexture texture = mTextureView.getSurfaceTexture();
+ // Set preview size.
+ texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+ // This is the output Surface we need to start preview.
+ Surface surface = new Surface(texture);
+
+ mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ mPreviewRequestBuilder.addTarget(surface);
+ // Here, we create a CameraCaptureSession for ic_launcher preview.
+ mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
+ new CameraCaptureSession.StateCallback() {
+
+ @Override
+ public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
+ // The ic_launcher is already closed
+ if (null == mCameraDevice) {
+ return;
+ }
+
+ // When the session is ready, we start displaying the preview.
+ mCaptureSession = cameraCaptureSession;
+ try {
+ // Auto focus should be continuous for ic_launcher preview.
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ // Flash is automatically enabled when necessary.
+ setAutoFlash(mPreviewRequestBuilder);
+ // Finally, we start displaying the ic_launcher preview.
+ mPreviewRequest = mPreviewRequestBuilder.build();
+ mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
+ Toast.makeText(getActivity(), "Failed", Toast.LENGTH_LONG).show();
+ }
+ }, null);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
+
+ private void process(CaptureResult result) {
+ switch (mState) {
+ case STATE_PREVIEW: {
+ // We have nothing to do when the ic_launcher preview is working normally.
+ break;
+ }
+ case STATE_WAITING_LOCK: {
+ Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
+ if (afState == null) {
+ captureStillPicture();
+ } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState
+ || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
+ // CONTROL_AE_STATE can be null on some devices
+ Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
+ mState = STATE_PICTURE_TAKEN;
+ captureStillPicture();
+ } else {
+ runPrecaptureSequence();
+ }
+ }
+ break;
+ }
+ case STATE_WAITING_PRECAPTURE: {
+ // CONTROL_AE_STATE can be null on some devices
+ Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE
+ || aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
+ mState = STATE_WAITING_NON_PRECAPTURE;
+ }
+ break;
+ }
+ case STATE_WAITING_NON_PRECAPTURE: {
+ // CONTROL_AE_STATE can be null on some devices
+ Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
+ mState = STATE_PICTURE_TAKEN;
+ captureStillPicture();
+ }
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request,
+ @NonNull CaptureResult partialResult) {
+ process(partialResult);
+ }
+
+ @Override
+ public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request,
+ @NonNull TotalCaptureResult result) {
+ process(result);
+ }
+ };
+
+
+ /**
+ * Run the precapture sequence for capturing a still image. This method should be called when
+ * we get a response in.
+ */
+ private void runPrecaptureSequence() {
+ try {
+ // This is how to tell the ic_launcher to trigger.
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
+ // Tell #mCaptureCallback to wait for the precapture sequence to be set.
+ mState = STATE_WAITING_PRECAPTURE;
+ mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Capture a still picture. This method should be called when we get a response in
+ * {@link #mCaptureCallback} from both
+ */
+ private void captureStillPicture() {
+ try {
+ final Activity activity = getActivity();
+ if (null == activity || null == mCameraDevice) {
+ return;
+ }
+ // This is the CaptureRequest.Builder that we use to take a picture.
+ final CaptureRequest.Builder captureBuilder =
+ mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ captureBuilder.addTarget(mImageReader.getSurface());
+
+ // Use the same AE and AF modes as the preview.
+ captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ setAutoFlash(captureBuilder);
+
+ // Orientation
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
+
+ CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {
+
+ @Override
+ public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request,
+ @NonNull TotalCaptureResult result) {
+ showToast("Saved: " + mFile);
+ Log.d(TAG, mFile.toString());
+ unlockFocus();
+ }
+ };
+
+ mCaptureSession.stopRepeating();
+ mCaptureSession.abortCaptures();
+ mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Retrieves the JPEG orientation from the specified screen rotation.
+ *
+ * @param rotation The screen rotation.
+ * @return The JPEG orientation (one of 0, 90, 270, and 360)
+ */
+ private int getOrientation(int rotation) {
+ return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;
+ }
+
+ /**
+ * Unlock the focus. This method should be called when still image capture sequence is
+ * finished.
+ */
+ private void unlockFocus() {
+ try {
+ // Reset the auto-focus trigger
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
+ setAutoFlash(mPreviewRequestBuilder);
+ mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mCameraHandler);
+ // After this, the ic_launcher will go back to the normal state of preview.
+ mState = STATE_PREVIEW;
+ mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
+ if (mFlashSupported) {
+ requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+ }
+ }
+
+ protected void showToast(final String text) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }
+
+ /**
+ * Configures the necessary {@link Matrix} transformation to `mTextureView`.
+ * This method should be called after the ic_launcher preview size is determined in
+ * setUpCameraOutputs and also the size of `mTextureView` is fixed.
+ *
+ * @param viewWidth The width of `mTextureView`
+ * @param viewHeight The height of `mTextureView`
+ */
+ protected void configureTransform(int viewWidth, int viewHeight) {
+ Activity activity = getActivity();
+ if (null == mTextureView || null == mPreviewSize || null == activity) {
+ return;
+ }
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ Matrix matrix = new Matrix();
+ RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
+ RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ float centerX = viewRect.centerX();
+ float centerY = viewRect.centerY();
+ if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
+ matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
+ float scale =
+ Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
+ matrix.postScale(scale, scale, centerX, centerY);
+ matrix.postRotate(90 * (rotation - 2), centerX, centerY);
+ } else if (Surface.ROTATION_180 == rotation) {
+ matrix.postRotate(180, centerX, centerY);
+ }
+ mTextureView.setTransform(matrix);
+ }
+
+
+ /**
+ * Set preview image size and positioning.
+ *
+ * @param width
+ * @param height
+ * @param map StreamConfigurationMap, the manager of all output formats and sizes supported by the camera.
+ * @param largest The max size
+ */
+ private void setPreviewSize(int width, int height, StreamConfigurationMap map, Size largest) {
+ // Find out if we need to swap dimension to get the preview size relative to sensor coordinate.
+ int displayRotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
+ Log.d(TAG, "displayRotation: " + displayRotation);
+
+ boolean swappedDimensions = false;
+ if (Surface.ROTATION_0 == displayRotation || Surface.ROTATION_180 == displayRotation) {
+ if (mSensorOrientation == 90 || mSensorOrientation == 270) {
+ swappedDimensions = true;
+ }
+ } else if (Surface.ROTATION_90 == displayRotation || Surface.ROTATION_270 == displayRotation) {
+ if (mSensorOrientation == 0 || mSensorOrientation == 180) {
+ swappedDimensions = true;
+ }
+ }
+
+ Point displaySize = new Point();
+ getActivity().getWindowManager().getDefaultDisplay().getSize(displaySize);
+ int rotatedPreviewWidth = width;
+ int rotatedPreviewHeight = height;
+ int maxPreviewWidth = displaySize.x;
+ int maxPreviewHeight = displaySize.y;
+
+ if (swappedDimensions) {
+ rotatedPreviewWidth = height;
+ rotatedPreviewHeight = width;
+ maxPreviewWidth = displaySize.y;
+ maxPreviewHeight = displaySize.x;
+ }
+
+ if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
+ maxPreviewWidth = MAX_PREVIEW_WIDTH;
+ }
+
+ if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
+ maxPreviewHeight = MAX_PREVIEW_HEIGHT;
+ }
+
+ // Danger, W.R.! Attempting to use too large a preview size could exceed the ic_launcher
+ // bus' bandwidth limitation, resulting in gorgeous previews but the storage of
+ // garbage capture data.
+ mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedPreviewWidth,
+ rotatedPreviewHeight, maxPreviewWidth, maxPreviewHeight, largest);
+
+ // We fit the aspect ratio of TextureView to the size of preview we picked.
+ int orientation = getResources().getConfiguration().orientation;// manifest中方向已经写死
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+ } else {
+ mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ }
+ }
+
+ /**
+ * Given {@code choices} of {@code Size}s supported by a ic_launcher, choose the smallest one that
+ * is at least as large as the respective texture view size, and that is at most as large as the
+ * respective max size, and whose aspect ratio matches with the specified value. If such size
+ * doesn't exist, choose the largest one that is at most as large as the respective max size,
+ * and whose aspect ratio matches with the specified value.
+ *
+ * @param choices The list of sizes that the ic_launcher supports for the intended output
+ * class
+ * @param textureViewWidth The width of the texture view relative to sensor coordinate
+ * @param textureViewHeight The height of the texture view relative to sensor coordinate
+ * @param maxWidth The maximum width that can be chosen
+ * @param maxHeight The maximum height that can be chosen
+ * @param aspectRatio The aspect ratio
+ * @return The optimal {@code Size}, or an arbitrary one if none were big enough
+ */
+ protected Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight, int maxWidth,
+ int maxHeight, Size aspectRatio) {
+
+ // Collect the supported resolutions that are at least as big as the preview Surface
+ List bigEnough = new ArrayList<>();
+ // Collect the supported resolutions that are smaller than the preview Surface
+ List notBigEnough = new ArrayList<>();
+ int w = aspectRatio.getWidth();
+ int h = aspectRatio.getHeight();
+ for (Size option : choices) {
+ if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight
+ && option.getHeight() == option.getWidth() * h / w) {
+ // if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight) {
+ if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
+ bigEnough.add(option);
+ } else {
+ notBigEnough.add(option);
+ }
+ }
+ }
+
+ if (bigEnough.size() > 0) {
+ return Collections.min(bigEnough, new CompareSizesByArea());
+ } else if (notBigEnough.size() > 0) {
+ return Collections.max(notBigEnough, new CompareSizesByArea());
+ } else {
+ Log.e(TAG, "Couldn't find any suitable preview size");
+ return choices[0];
+ }
+ }
+
+
+ /**
+ * Closes the current {@link CameraDevice}.
+ */
+ private void closeCamera() {
+ try {
+ mCameraOpenCloseLock.acquire();
+ if (null != mCaptureSession) {
+ mCaptureSession.close();
+ mCaptureSession = null;
+ }
+ if (null != mCameraDevice) {
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ if (null != mImageReader) {
+ mImageReader.close();
+ mImageReader = null;
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock ic_launcher closing.", e);
+ } finally {
+ mCameraOpenCloseLock.release();
+ }
+ }
+
+ private void stopBackgroundThread() {
+ isPreBackgroundThreadPause = true;
+ mCameraHandlerThread.quitSafely();
+ mMindsporeHandlerThread.quitSafely();
+ try {
+ mCameraHandlerThread.join();
+ mCameraHandlerThread = null;
+ mCameraHandler.removeCallbacksAndMessages(null);
+ mCameraHandler = null;
+
+ mMindsporeHandlerThread.join();
+ mMindsporeHandlerThread = null;
+ mMindsporeHandler.removeCallbacksAndMessages(null);
+ mMindsporeHandler = null;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/MainActivity.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/MainActivity.java
new file mode 100644
index 0000000000..fd986c8386
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/MainActivity.java
@@ -0,0 +1,341 @@
+package com.mindspore.classificationforcar.widget;
+
+import android.Manifest;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.core.content.FileProvider;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.mindspore.classificationforcar.R;
+import com.mindspore.classificationforcar.gallery.classify.BitmapUtils;
+import com.mindspore.classificationforcar.gallery.classify.ImageTrackingMobile;
+import com.mindspore.classificationforcar.gallery.classify.RecognitionImageBean;
+import com.mindspore.classificationforcar.gallery.classify.TrackingMobile;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MainActivity extends AppCompatActivity implements OnBackgroundImageListener {
+
+ private static final String TAG = "MainActivity";
+
+ private static final String[] PERMISSIONS = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA};
+ private static final int REQUEST_PERMISSION = 0;
+
+ private static final int[] IMAGES = {R.drawable.style0, R.drawable.style1, R.drawable.style2, R.drawable.style3, R.drawable.style4,
+ R.drawable.style5, R.drawable.style6, R.drawable.style7, R.drawable.style8, R.drawable.style9,
+ R.drawable.style10, R.drawable.style11, R.drawable.style12, R.drawable.style13, R.drawable.style14,
+ R.drawable.style15, R.drawable.style16, R.drawable.style17, R.drawable.style18, R.drawable.style19};
+
+ private static final int RC_CHOOSE_PHOTO = 1;
+ private static final int RC_CHOOSE_CAMERA = 2;
+ private static final String IMAGE_SCENE_MS = "model/mobilenetv2.ms";
+
+ private boolean isAllGranted;
+ private static final String CAR_MS = "car.ms";
+ private File ROOT_FILE = new File(Environment.getExternalStorageDirectory().getAbsoluteFile(), "CarClassification");
+ private File DIR_FILE = new File(ROOT_FILE, CAR_MS);
+
+ private ImageView imgPreview;
+ private Uri imageUri;
+ private TextView textResult;
+ private ProgressBar progressBar;
+ private RecyclerView recyclerView;
+ private TrackingMobile trackingMobile;
+ private ImageTrackingMobile imageTrackingMobile;
+ private List recognitionObjectBeanList;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ init();
+ requestPermissions();
+ }
+
+ private void init() {
+ imgPreview = findViewById(R.id.img_origin);
+ textResult = findViewById(R.id.tv_image);
+ progressBar = findViewById(R.id.progress);
+ recyclerView = findViewById(R.id.recyclerview);
+ recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
+ recyclerView.setAdapter(new RecyclerViewAdapter(this, IMAGES, this));
+ trackingMobile = new TrackingMobile(this);
+ imageTrackingMobile = new ImageTrackingMobile(this);
+ }
+
+ private void requestPermissions() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ isAllGranted = checkPermissionAllGranted(PERMISSIONS);
+ if (!isAllGranted) {
+ ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION);
+ }
+ } else {
+ isAllGranted = true;
+ }
+ }
+
+ private boolean checkPermissionAllGranted(String[] permissions) {
+ for (String permission : permissions) {
+ if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Authority application result callback
+ */
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (REQUEST_PERMISSION == requestCode) {
+ isAllGranted = true;
+ for (int grant : grantResults) {
+ if (grant != PackageManager.PERMISSION_GRANTED) {
+ isAllGranted = false;
+ break;
+ }
+ }
+ if (!isAllGranted) {
+ openAppDetails();
+ }
+ }
+ }
+
+ private void openAppDetails() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage("HiMindSpore需要访问 “相机” 和 “外部存储器”,请到 “应用信息 -> 权限” 中授予!");
+ builder.setPositiveButton("去手动授权", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.setData(Uri.parse("package:" + getPackageName()));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ startActivity(intent);
+ }
+ });
+ builder.setNegativeButton("取消", null);
+ builder.show();
+ }
+
+ public boolean isHasCarModelFile() {
+ if (DIR_FILE.exists()) {
+ return true;
+ } else {
+ if (!ROOT_FILE.exists()) {
+ ROOT_FILE.mkdirs();
+ }
+ return false;
+ }
+ }
+
+ public void onClickPhoto(View view) {
+ if (isAllGranted) {
+ openGallay();
+ } else {
+ requestPermissions();
+ }
+ }
+
+ public void onClickCamera(View view) {
+ if (isAllGranted) {
+ openCamera();
+ } else {
+ requestPermissions();
+ }
+ }
+
+ public void onClickScene(View view) {
+ Intent intent = new Intent(MainActivity.this, CameraActivity.class);
+ intent.putExtra("FILEPATH", DIR_FILE.getPath());
+ intent.putExtra("ISHASCARMODELFILE", isHasCarModelFile());
+ startActivity(intent);
+ }
+
+ @Override
+ public void onBackImageSelected(int position) {
+ imgPreview.setImageResource(IMAGES[position]);
+ initMindspore(BitmapFactory.decodeResource(getResources(), IMAGES[position]));
+ }
+
+ private void openGallay() {
+ Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
+ intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
+ startActivityForResult(intentToPickPic, RC_CHOOSE_PHOTO);
+ }
+
+ private void openCamera() {
+ Intent intentToTakePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ String mTempPhotoPath = Environment.getExternalStorageDirectory() + File.separator + "photo22.jpeg";
+ imageUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".fileprovider", new File(mTempPhotoPath));
+ intentToTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
+ startActivityForResult(intentToTakePhoto, RC_CHOOSE_CAMERA);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode == RESULT_OK) {
+ if (RC_CHOOSE_PHOTO == requestCode) {
+ if (null != data && null != data.getData()) {
+ this.imageUri = data.getData();
+ showOriginImage();
+ } else {
+ finish();
+ }
+ } else if (RC_CHOOSE_CAMERA == requestCode) {
+ showOriginCamera();
+ }
+ }
+ }
+
+ private void showOriginImage() {
+ File file = BitmapUtils.getFileFromMediaUri(this, imageUri);
+ Bitmap photoBmp = BitmapUtils.getBitmapFormUri(this, Uri.fromFile(file));
+ int degree = BitmapUtils.getBitmapDegree(file.getAbsolutePath());
+ Bitmap originBitmap = BitmapUtils.rotateBitmapByDegree(photoBmp, degree);
+ if (originBitmap != null) {
+ imgPreview.setImageBitmap(originBitmap);
+ initMindspore(originBitmap.copy(Bitmap.Config.ARGB_8888, true));
+ } else {
+ Toast.makeText(this, R.string.image_invalid, Toast.LENGTH_LONG).show();
+ }
+ }
+
+ private void showOriginCamera() {
+ try {
+ Bitmap originBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
+ if (originBitmap != null) {
+ imgPreview.setImageBitmap(originBitmap);
+ initMindspore(originBitmap.copy(Bitmap.Config.ARGB_8888, true));
+ } else {
+ Toast.makeText(this, R.string.image_invalid, Toast.LENGTH_LONG).show();
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+
+
+ }
+
+ private void initMindspore(Bitmap bitmap) {
+ progressBar.setVisibility(View.VISIBLE);
+
+ if (isHasCarModelFile()) {
+ boolean ret = trackingMobile.loadModelFromBuf(DIR_FILE.getPath());
+ if (!ret) {
+ textResult.setText("Load model error.");
+ Log.e(TAG, "Load model error.");
+ return;
+ }
+ // run net.
+ long startTime = System.currentTimeMillis();
+ String result = trackingMobile.MindSpore_runnet(bitmap);
+ long endTime = System.currentTimeMillis();
+ progressBar.setVisibility(View.GONE);
+ textResult.setText(result);
+ Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
+ Log.d(TAG, "result:" + result);
+ } else {
+ if (recognitionObjectBeanList != null) {
+ recognitionObjectBeanList.clear();
+ } else {
+ recognitionObjectBeanList = new ArrayList<>();
+ }
+
+ boolean ret = imageTrackingMobile.loadModelFromBuf(IMAGE_SCENE_MS);
+ if (!ret) {
+ textResult.setText("Load model error.");
+ Log.e(TAG, "Load model error.");
+ return;
+ }
+ // run net.
+ long startTime = System.currentTimeMillis();
+ String result = imageTrackingMobile.MindSpore_runnet(bitmap);
+ long endTime = System.currentTimeMillis();
+ progressBar.setVisibility(View.GONE);
+ Log.d(TAG, "RUNNET CONSUMING:" + (endTime - startTime) + "ms");
+ Log.d(TAG, "result:" + result);
+
+ if (!TextUtils.isEmpty(result)) {
+ String[] resultArray = result.split(";");
+ for (String singleRecognitionResult : resultArray) {
+ String[] singleResult = singleRecognitionResult.split(":");
+ float score = Float.parseFloat(singleResult[1]);
+ if (score > 0.5) {
+ recognitionObjectBeanList.add(new RecognitionImageBean(singleResult[0], score));
+ }
+ }
+ Collections.sort(recognitionObjectBeanList, (t1, t2) -> Float.compare(t2.getScore(), t1.getScore()));
+ showResultsInBottomSheet(recognitionObjectBeanList, (endTime - startTime) + "ms");
+ }
+ }
+ if (!bitmap.isRecycled()) {
+ bitmap.recycle();
+ }
+ }
+
+ @UiThread
+ protected void showResultsInBottomSheet(List list, String time) {
+ if (list == null || list.size() < 1) {
+ return;
+ }
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < list.size(); i++) {
+ RecognitionImageBean bean = list.get(i);
+ stringBuilder.append(bean.getName()).append("\r:\r").append(String.format("%.2f", (100 * bean.getScore())) + "%").append("\r\n");
+ if (i > 3) { // set maximum display is 3.
+ break;
+ }
+ }
+ textResult.setText(stringBuilder);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (trackingMobile != null) {
+ trackingMobile.unloadModel();
+ }
+ if (imageTrackingMobile != null) {
+ imageTrackingMobile.unloadModel();
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/OnBackgroundImageListener.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/OnBackgroundImageListener.java
new file mode 100644
index 0000000000..2eab47c9c7
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/OnBackgroundImageListener.java
@@ -0,0 +1,9 @@
+package com.mindspore.classificationforcar.widget;
+
+import android.view.View;
+
+public interface OnBackgroundImageListener {
+ void onBackImageSelected(int position);
+
+// void onImageAdd(View view);
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/RecyclerViewAdapter.java b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/RecyclerViewAdapter.java
new file mode 100644
index 0000000000..99462d8146
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/java/com/mindspore/classificationforcar/widget/RecyclerViewAdapter.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright 2020 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar.widget;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.bumptech.glide.Glide;
+import com.mindspore.classificationforcar.R;
+
+public class RecyclerViewAdapter extends RecyclerView.Adapter {
+
+ private final int[] IMAGES;
+ private final Context context;
+ private final OnBackgroundImageListener mListener;
+
+ public RecyclerViewAdapter(Context context, int[] IMAGES, OnBackgroundImageListener mListener) {
+ this.IMAGES = IMAGES;
+ this.context = context;
+ this.mListener = mListener;
+ }
+
+ @NonNull
+ @Override
+ public StyleItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(context)
+ .inflate(R.layout.image_item, parent, false);
+ return new StyleItemViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull StyleItemViewHolder holder, int position) {
+ Glide.with(context).
+ load(IMAGES[position]).
+ into(holder.getImageView());
+
+ View view = holder.getMView();
+ view.setTag(IMAGES[position]);
+ view.setOnClickListener(view1 -> {
+ if (mListener != null) {
+// if (IMAGES.length - 1 == position) {
+// mListener.onImageAdd(holder.getImageView());
+// } else {
+ mListener.onBackImageSelected(position);
+// }
+ }
+ });
+ }
+
+
+ @Override
+ public int getItemCount() {
+ return IMAGES == null ? 0 : IMAGES.length;
+ }
+
+
+ public class StyleItemViewHolder extends RecyclerView.ViewHolder {
+ private ImageView imageView;
+ private final View mView;
+
+ public final ImageView getImageView() {
+ return this.imageView;
+ }
+
+ public final void setImageView(ImageView imageView) {
+ this.imageView = imageView;
+ }
+
+ public final View getMView() {
+ return this.mView;
+ }
+
+ public StyleItemViewHolder(View mView) {
+ super(mView);
+ this.mView = mView;
+ this.imageView = mView.findViewById(R.id.image_view);
+ }
+ }
+}
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000000..2b068d1146
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/logo.png b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/logo.png
new file mode 100644
index 0000000000..c90f1dda43
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/logo.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/logo2.png b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/logo2.png
new file mode 100644
index 0000000000..589b9926f6
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/logo2.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style0.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style0.jpg
new file mode 100644
index 0000000000..a15c66e731
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style0.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style1.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style1.jpg
new file mode 100644
index 0000000000..2953c88e6c
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style1.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style10.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style10.jpg
new file mode 100644
index 0000000000..d40cc299af
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style10.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style11.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style11.jpg
new file mode 100644
index 0000000000..0c795c3cc2
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style11.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style12.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style12.jpg
new file mode 100644
index 0000000000..0ed9d3eaf9
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style12.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style13.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style13.jpg
new file mode 100644
index 0000000000..da48fa48eb
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style13.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style14.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style14.jpg
new file mode 100644
index 0000000000..3ec23af0ca
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style14.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style15.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style15.jpg
new file mode 100644
index 0000000000..96ed6d63aa
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style15.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style16.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style16.jpg
new file mode 100644
index 0000000000..54aa5dbbb7
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style16.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style17.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style17.jpg
new file mode 100644
index 0000000000..ab7fe41ae5
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style17.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style18.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style18.jpg
new file mode 100644
index 0000000000..d17a5c2a73
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style18.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style19.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style19.jpg
new file mode 100644
index 0000000000..1aaac971f2
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style19.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style2.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style2.jpg
new file mode 100644
index 0000000000..9be984259a
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style2.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style3.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style3.jpg
new file mode 100644
index 0000000000..030c07c76d
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style3.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style4.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style4.jpg
new file mode 100644
index 0000000000..4d1344ba5d
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style4.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style5.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style5.jpg
new file mode 100644
index 0000000000..0ce9254ec2
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style5.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style6.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style6.jpg
new file mode 100644
index 0000000000..abfa2a17b6
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style6.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style7.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style7.jpg
new file mode 100644
index 0000000000..7404ec8d98
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style7.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style8.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style8.jpg
new file mode 100644
index 0000000000..cc6cc8dd9c
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style8.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style9.jpg b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style9.jpg
new file mode 100644
index 0000000000..5412d6730b
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/drawable-xxhdpi/style9.jpg differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable/ic_launcher_background.xml b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000000..d5fccc538c
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable/progressbar.xml b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/progressbar.xml
new file mode 100644
index 0000000000..d48a929d88
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/progressbar.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable/rectangle.xml b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/rectangle.xml
new file mode 100644
index 0000000000..b8f5d3559c
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/rectangle.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable/switch_thumb.xml b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/switch_thumb.xml
new file mode 100644
index 0000000000..ef6cfd2339
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/switch_thumb.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/drawable/switch_track.xml b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/switch_track.xml
new file mode 100644
index 0000000000..3088fe56f6
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/drawable/switch_track.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/layout/activity_camera.xml b/model_zoo/official/lite/car_classification/app/src/main/res/layout/activity_camera.xml
new file mode 100644
index 0000000000..153f51149e
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/layout/activity_camera.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/layout/activity_main.xml b/model_zoo/official/lite/car_classification/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000000..b5c433283b
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/layout/fragment_camera.xml b/model_zoo/official/lite/car_classification/app/src/main/res/layout/fragment_camera.xml
new file mode 100644
index 0000000000..6e0897de31
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/layout/fragment_camera.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/layout/image_item.xml b/model_zoo/official/lite/car_classification/app/src/main/res/layout/image_item.xml
new file mode 100644
index 0000000000..7109ec85ca
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/layout/image_item.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/layout/layout_hor_text_view.xml b/model_zoo/official/lite/car_classification/app/src/main/res/layout/layout_hor_text_view.xml
new file mode 100644
index 0000000000..eb9bea42d1
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/layout/layout_hor_text_view.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000000..036d09bc5f
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000000..036d09bc5f
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..ad551dcf1c
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000000..cea70b6899
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..12602e9e7b
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..534bc3b190
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000000..0cc30d70ba
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..13d25d7dcb
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..ce4d40a739
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000000..4f8f320bf7
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..674ae88e4d
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..7c87876ea0
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000000..d4b8095ea9
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..2528822d4d
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/logo.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/logo.png
new file mode 100644
index 0000000000..c90f1dda43
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxhdpi/logo.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..cae0e3a326
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000000..c1229997eb
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..24849e26b4
Binary files /dev/null and b/model_zoo/official/lite/car_classification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/values/colors.xml b/model_zoo/official/lite/car_classification/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..7d780cf808
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/values/colors.xml
@@ -0,0 +1,17 @@
+
+
+ #303030
+ #3700B3
+ #03DAC5
+
+ #ffffff
+ #000000
+ #A69D9D
+ #424242
+
+ #6DA7FF
+ #F8E71C
+ #FF844D
+ #66B50A
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/values/dimens.xml b/model_zoo/official/lite/car_classification/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..a7b5dd0995
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/values/dimens.xml
@@ -0,0 +1,9 @@
+
+
+ 15dp
+ 8dp
+
+ 15dp
+ 6dp
+ 15sp
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/values/ic_launcher_background.xml b/model_zoo/official/lite/car_classification/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000000..c5d5899fdf
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #FFFFFF
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/values/strings.xml b/model_zoo/official/lite/car_classification/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..88ed5903bf
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/values/strings.xml
@@ -0,0 +1,32 @@
+
+ CarClassification
+ 设置
+
+ This sample needs camera permission.
+ This device doesn\'t support Camera2 API.
+ 使用的google的camera2demo.
+ EXAMPLE
+ Add widget
+
+ The image path you selected is not valid. Please choose again
+ Sorry, there is no object identified in this picture. Try another picture
+
+ TFL Classify
+ This device doesn\'t support Camera2 API.
+ GPU does not yet supported quantized models.
+ Model:
+
+ - Quantized_EfficientNet
+ - Float_EfficientNet
+ - Quantized_MobileNet
+ - Float_MobileNet
+
+
+ Device:
+
+ - CPU
+ - GPU
+ - NNAPI
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/values/styles.xml b/model_zoo/official/lite/car_classification/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000000..13f74a4612
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/values/styles.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/app/src/main/res/xml/file_paths.xml b/model_zoo/official/lite/car_classification/app/src/main/res/xml/file_paths.xml
new file mode 100644
index 0000000000..a075ef96b4
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/main/res/xml/file_paths.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/model_zoo/official/lite/car_classification/app/src/test/java/com/mindspore/classificationforcar/ExampleUnitTest.java b/model_zoo/official/lite/car_classification/app/src/test/java/com/mindspore/classificationforcar/ExampleUnitTest.java
new file mode 100644
index 0000000000..be8d4b887f
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/app/src/test/java/com/mindspore/classificationforcar/ExampleUnitTest.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2021 Huawei Technologies Co., Ltd
+ *
+ * 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.mindspore.classificationforcar;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
diff --git a/model_zoo/official/lite/car_classification/build.gradle b/model_zoo/official/lite/car_classification/build.gradle
new file mode 100644
index 0000000000..8205219fc6
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/build.gradle
@@ -0,0 +1,27 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:4.0.1"
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ maven {
+ url "https://mirrors.huaweicloud.com/repository/maven/"
+ }
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/gradle.properties b/model_zoo/official/lite/car_classification/gradle.properties
new file mode 100644
index 0000000000..f5020a3b37
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+android.injected.testOnly=false
\ No newline at end of file
diff --git a/model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.jar b/model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..f6b961fd5a
Binary files /dev/null and b/model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.properties b/model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..1d8635ad73
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue Jul 28 10:28:05 CST 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
diff --git a/model_zoo/official/lite/car_classification/gradlew b/model_zoo/official/lite/car_classification/gradlew
new file mode 100644
index 0000000000..cccdd3d517
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/model_zoo/official/lite/car_classification/gradlew.bat b/model_zoo/official/lite/car_classification/gradlew.bat
new file mode 100644
index 0000000000..f9553162f1
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/model_zoo/official/lite/car_classification/settings.gradle b/model_zoo/official/lite/car_classification/settings.gradle
new file mode 100644
index 0000000000..f761014d56
--- /dev/null
+++ b/model_zoo/official/lite/car_classification/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "CarClassification"
\ No newline at end of file