From 3fd54d68841e01e333c94c32f2378addc56e8146 Mon Sep 17 00:00:00 2001 From: WinterGeng <1558270516@qq.com> Date: Thu, 3 Nov 2022 10:32:43 +0800 Subject: [PATCH 1/2] 1.Move EasyEdge Ui code to fastdeploy; 2.Add photo recognition, real-time recognition, album selection recognition, detail page display and other functions. --- java/android/app/src/main/AndroidManifest.xml | 4 +- .../app/examples/detection/MainActivity.java | 198 ++++++++- .../examples/detection/SettingsActivity.java | 5 +- .../app/examples/ocr/MainActivity.java | 2 +- .../app/examples/ocr/SettingsActivity.java | 2 +- .../fastdeploy/app/ui/CameraSurfaceView.java | 2 + .../app/ui/camera/CameraListener.java | 19 + .../app/ui/camera/CameraProxy1.java | 296 ++++++++++++++ .../app/ui/camera/ICameraProxy.java | 27 ++ .../app/ui/{ => layout}/ActionBarLayout.java | 2 +- .../app/ui/layout/OperationFrameLayout.java | 37 ++ .../fastdeploy/app/ui/util/ImageUtil.java | 155 +++++++ .../fastdeploy/app/ui/util/StringUtil.java | 14 + .../app/ui/util/ThreadPoolManager.java | 78 ++++ .../paddle/fastdeploy/app/ui/util/UiLog.java | 15 + .../app/ui/view/PreviewDecoratorView.java | 162 ++++++++ .../fastdeploy/app/ui/view/PreviewView.java | 144 +++++++ .../app/ui/view/ResultListView.java | 47 +++ .../app/ui/view/ResultMaskView.java | 381 ++++++++++++++++++ .../fastdeploy/app/ui/{ => view}/Utils.java | 2 +- .../ui/view/adapter/DetectResultAdapter.java | 47 +++ .../ui/view/model/BasePolygonResultModel.java | 149 +++++++ .../app/ui/view/model/BaseResultModel.java | 45 +++ .../ui/view/model/PoseViewResultModel.java | 11 + .../app/src/main/res/layout/activity_main.xml | 169 +------- .../app/src/main/res/layout/camera_page.xml | 161 ++++++++ .../main/res/layout/result_detect_item.xml | 26 ++ .../app/src/main/res/layout/result_page.xml | 164 ++++++++ .../main/res/layout/result_table_popview.xml | 42 ++ .../app/src/main/res/values/strings.xml | 5 +- .../app/src/main/res/values/values.xml | 17 + 31 files changed, 2247 insertions(+), 181 deletions(-) create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java rename java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/{ => layout}/ActionBarLayout.java (94%) create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java rename java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/{ => view}/Utils.java (99%) create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java create mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java create mode 100644 java/android/app/src/main/res/layout/camera_page.xml create mode 100644 java/android/app/src/main/res/layout/result_detect_item.xml create mode 100644 java/android/app/src/main/res/layout/result_page.xml create mode 100644 java/android/app/src/main/res/layout/result_table_popview.xml create mode 100644 java/android/app/src/main/res/values/values.xml diff --git a/java/android/app/src/main/AndroidManifest.xml b/java/android/app/src/main/AndroidManifest.xml index 754b0b6c3b..83dfc75422 100644 --- a/java/android/app/src/main/AndroidManifest.xml +++ b/java/android/app/src/main/AndroidManifest.xml @@ -15,14 +15,14 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - + diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java index bbe184b45b..bdafaeb728 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java @@ -9,30 +9,40 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.database.Cursor; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; import android.os.Bundle; +import android.os.SystemClock; import android.preference.PreferenceManager; +import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.view.View; +import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.SeekBar; import android.widget.TextView; -import android.widget.Toast; import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; import com.baidu.paddle.fastdeploy.app.ui.CameraSurfaceView; -import com.baidu.paddle.fastdeploy.app.ui.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; +import com.baidu.paddle.fastdeploy.app.ui.view.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.adapter.DetectResultAdapter; +import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.vision.DetectionResult; import com.baidu.paddle.fastdeploy.vision.detection.PicoDet; import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; public class MainActivity extends Activity implements View.OnClickListener, CameraSurfaceView.OnTextureChangedListener { private static final String TAG = MainActivity.class.getSimpleName(); @@ -45,6 +55,25 @@ public class MainActivity extends Activity implements View.OnClickListener, Came ImageView realtimeToggleButton; boolean isRealtimeStatusRunning = false; ImageView backInPreview; + private ImageView albumSelectButton; + private View mCameraPageView; + private ViewGroup mResultPageView; + private ImageView resultImage; + private ImageView backInResult; + private SeekBar confidenceSeekbar; + private TextView seekbarText; + private float resultNum = 1.0f; + private ResultListView detectResultView; + private Bitmap shutterBitmap; + private Bitmap originShutterBitmap; + private Bitmap picBitmap; + private Bitmap originPicBitmap; + public static final int BTN_SHUTTER = 0; + public static final int ALBUM_SELECT = 1; + private static int TYPE = BTN_SHUTTER; + + private static final int REQUEST_PERMISSION_CODE_STORAGE = 101; + private static final int INTENT_CODE_PICK_IMAGE = 100; String savedImagePath = "result.jpg"; int lastFrameIndex = 0; @@ -83,12 +112,13 @@ public void onClick(View v) { svPreview.switchCamera(); break; case R.id.btn_shutter: - @SuppressLint("SimpleDateFormat") - SimpleDateFormat date = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); - synchronized (this) { - savedImagePath = Utils.getDCIMDirectory() + File.separator + date.format(new Date()).toString() + ".png"; - } - Toast.makeText(MainActivity.this, "Save snapshot to " + savedImagePath, Toast.LENGTH_SHORT).show(); + TYPE = BTN_SHUTTER; + svPreview.onPause(); + mCameraPageView.setVisibility(View.GONE); + mResultPageView.setVisibility(View.VISIBLE); + seekbarText.setText(resultNum + ""); + confidenceSeekbar.setProgress((int) (resultNum * 100)); + resultImage.setImageBitmap(shutterBitmap); break; case R.id.btn_settings: startActivity(new Intent(MainActivity.this, SettingsActivity.class)); @@ -99,9 +129,64 @@ public void onClick(View v) { case R.id.back_in_preview: finish(); break; + case R.id.albumSelect: + TYPE = ALBUM_SELECT; + // 判断是否已经赋予权限 + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + // 如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。 + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE_STORAGE); + } else { + Intent intent = new Intent(Intent.ACTION_PICK); + intent.setType("image/*"); + startActivityForResult(intent, INTENT_CODE_PICK_IMAGE); + } + break; + case R.id.back_in_result: + mResultPageView.setVisibility(View.GONE); + mCameraPageView.setVisibility(View.VISIBLE); + svPreview.onResume(); + break; + } } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == INTENT_CODE_PICK_IMAGE) { + if (resultCode == Activity.RESULT_OK) { + mCameraPageView.setVisibility(View.GONE); + mResultPageView.setVisibility(View.VISIBLE); + seekbarText.setText(resultNum + ""); + confidenceSeekbar.setProgress((int) (resultNum * 100)); + Uri uri = data.getData(); + String path = getRealPathFromURI(uri); + picBitmap = decodeBitmap(path, 720, 1280); + originPicBitmap = picBitmap.copy(Bitmap.Config.ARGB_8888, true); + resultImage.setImageBitmap(picBitmap); + } + } + } + + private String getRealPathFromURI(Uri contentURI) { + String result; + Cursor cursor = null; + try { + cursor = getContentResolver().query(contentURI, null, null, null, null); + } catch (Throwable e) { + e.printStackTrace(); + } + if (cursor == null) { + result = contentURI.getPath(); + } else { + cursor.moveToFirst(); + int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); + result = cursor.getString(idx); + cursor.close(); + } + return result; + } + private void toggleRealtimeStyle() { if (isRealtimeStatusRunning) { isRealtimeStatusRunning = false; @@ -125,8 +210,10 @@ public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) { public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) { String savedImagePath = ""; synchronized (this) { - savedImagePath = MainActivity.this.savedImagePath; + savedImagePath = Utils.getDCIMDirectory() + File.separator + "result.png"; } + shutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888,true); + originShutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888,true); boolean modified = false; DetectionResult result = predictor.predict( ARGB8888ImageBitmap, savedImagePath, SettingsActivity.scoreThreshold); @@ -151,6 +238,38 @@ public void run() { return modified; } + /** + * @param path 路径 + * @param displayWidth 需要显示的宽度 + * @param displayHeight 需要显示的高度 + * @return Bitmap + */ + public static Bitmap decodeBitmap(String path, int displayWidth, int displayHeight) { + BitmapFactory.Options op = new BitmapFactory.Options(); + op.inJustDecodeBounds = true; + // op.inJustDecodeBounds = true;表示我们只读取Bitmap的宽高等信息,不读取像素。 + Bitmap bmp = BitmapFactory.decodeFile(path, op); // 获取尺寸信息 + // op.outWidth表示的是图像真实的宽度 + // op.inSamplySize 表示的是缩小的比例 + // op.inSamplySize = 4,表示缩小1/4的宽和高,1/16的像素,android认为设置为2是最快的。 + // 获取比例大小 + int wRatio = (int) Math.ceil(op.outWidth / (float) displayWidth); + int hRatio = (int) Math.ceil(op.outHeight / (float) displayHeight); + // 如果超出指定大小,则缩小相应的比例 + if (wRatio > 1 && hRatio > 1) { + if (wRatio > hRatio) { + // 如果太宽,我们就缩小宽度到需要的大小,注意,高度就会变得更加的小。 + op.inSampleSize = wRatio; + } else { + op.inSampleSize = hRatio; + } + } + op.inJustDecodeBounds = false; + bmp = BitmapFactory.decodeFile(path, op); + // 从原Bitmap创建一个给定宽高的Bitmap + return Bitmap.createScaledBitmap(bmp, displayWidth, displayHeight, true); + } + @Override protected void onResume() { super.onResume(); @@ -191,6 +310,63 @@ public void initView() { realtimeToggleButton.setOnClickListener(this); backInPreview = findViewById(R.id.back_in_preview); backInPreview.setOnClickListener(this); + albumSelectButton = findViewById(R.id.albumSelect); + albumSelectButton.setOnClickListener(this); + mCameraPageView = findViewById(R.id.camera_page); + mResultPageView = findViewById(R.id.result_page); + resultImage = findViewById(R.id.result_image); + backInResult = findViewById(R.id.back_in_result); + backInResult.setOnClickListener(this); + confidenceSeekbar = findViewById(R.id.confidence_seekbar); + seekbarText = findViewById(R.id.seekbar_text); + detectResultView = findViewById(R.id.result_list_view); + + List results = new ArrayList<>(); + results.add(new BaseResultModel(1, "cup", 0.4f)); + results.add(new BaseResultModel(2, "pen", 0.6f)); + results.add(new BaseResultModel(3, "tang", 1.0f)); + final DetectResultAdapter adapter = new DetectResultAdapter(this, R.layout.result_detect_item, results); + detectResultView.setAdapter(adapter); + detectResultView.invalidate(); + + confidenceSeekbar.setMax(100); + confidenceSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + float resultConfidence = seekBar.getProgress() / 100f; + BigDecimal bd = new BigDecimal(resultConfidence); + resultNum = bd.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue(); + seekbarText.setText(resultNum + ""); + confidenceSeekbar.setProgress((int) (resultNum * 100)); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (TYPE == ALBUM_SELECT) { + SystemClock.sleep(500); + predictor.predict(picBitmap, savedImagePath, resultNum); + resultImage.setImageBitmap(picBitmap); + picBitmap = originPicBitmap.copy(Bitmap.Config.ARGB_8888, true); + resultNum = 1.0f; + } else { + SystemClock.sleep(500); + predictor.predict(shutterBitmap, savedImagePath, resultNum); + resultImage.setImageBitmap(shutterBitmap); + shutterBitmap = originShutterBitmap.copy(Bitmap.Config.ARGB_8888, true); + resultNum = 1.0f; + } + } + }); + } + }); } @SuppressLint("ApplySharedPref") diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java index 17e168f075..edae95ba8e 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java @@ -11,7 +11,7 @@ import com.baidu.paddle.fastdeploy.app.examples.R; import com.baidu.paddle.fastdeploy.app.ui.AppCompatPreferenceActivity; -import com.baidu.paddle.fastdeploy.app.ui.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.Utils; import java.util.ArrayList; import java.util.List; @@ -46,8 +46,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity implements @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // addPreferencesFromResource(R.xml.settings); - addPreferencesFromResource(R.xml.detection_settings); + addPreferencesFromResource(R.xml.settings); ActionBar supportActionBar = getSupportActionBar(); if (supportActionBar != null) { supportActionBar.setDisplayHomeAsUpEnabled(true); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/MainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/MainActivity.java index 0ea0486e0a..df53d42ebc 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/MainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/MainActivity.java @@ -26,7 +26,7 @@ import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; import com.baidu.paddle.fastdeploy.app.ui.CameraSurfaceView; -import com.baidu.paddle.fastdeploy.app.ui.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.Utils; import com.baidu.paddle.fastdeploy.vision.OCRResult; import com.baidu.paddle.fastdeploy.pipeline.PPOCRv2; import com.baidu.paddle.fastdeploy.vision.ocr.Classifier; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/SettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/SettingsActivity.java index ea2c4ff726..27b0c9e437 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/SettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/ocr/SettingsActivity.java @@ -11,7 +11,7 @@ import com.baidu.paddle.fastdeploy.app.examples.R; import com.baidu.paddle.fastdeploy.app.ui.AppCompatPreferenceActivity; -import com.baidu.paddle.fastdeploy.app.ui.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.Utils; import java.util.ArrayList; import java.util.List; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/CameraSurfaceView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/CameraSurfaceView.java index 6db97d68a3..ba26dbebee 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/CameraSurfaceView.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/CameraSurfaceView.java @@ -15,6 +15,8 @@ import android.util.AttributeSet; import android.util.Log; +import com.baidu.paddle.fastdeploy.app.ui.view.Utils; + import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java new file mode 100644 index 0000000000..377de1b2ef --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java @@ -0,0 +1,19 @@ +package com.baidu.paddle.fastdeploy.app.ui.camera; + +import android.graphics.Bitmap; + +/** + * Created by ruanshimin on 2017/11/30. + */ + +public class CameraListener { + public interface CommonListener { + void onSurfaceReady(); + + void onSwitchCamera(); + } + + public interface TakePictureListener { + void onTakenPicture(Bitmap bitmap); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java new file mode 100644 index 0000000000..0836ac640a --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java @@ -0,0 +1,296 @@ +package com.baidu.paddle.fastdeploy.app.ui.camera; + +import static android.hardware.Camera.getCameraInfo; +import static android.hardware.Camera.getNumberOfCameras; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.ImageFormat; +import android.graphics.Rect; +import android.graphics.SurfaceTexture; +import android.graphics.YuvImage; +import android.hardware.Camera; +import android.util.Log; + +import com.baidu.paddle.fastdeploy.app.ui.util.ImageUtil; +import com.baidu.paddle.fastdeploy.app.ui.util.UiLog; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Created by ruanshimin on 2018/4/16. + */ + +public class CameraProxy1 implements ICameraProxy { + + private static final int STATUS_INIT = 0; + + private static final int STATUS_OPENED = 1; + + private static final int STATUS_PREVIEWING = 2; + + private static final int TEXTURE_STATUS_INITED = 0; + + private static final int TEXTURE_STATUS_READY = 1; + + private SurfaceTexture mSurfaceTexture; + + private boolean isBack = true; + + private Camera mCamera; + + private int status; + private int textureStatus; + + private boolean hasDestoryUnexcepted = false; + + private int layoutWidth; + private int layoutHeight; + + private int[] previewSize = new int[2]; + + private CameraListener.CommonListener mCameraListener; + + private int minPreviewCandidateWidth = 0; + + private int previewRotation = 90; + private int displayRotation = 0; + + private int previewCaptureRotation = 0; + + private Camera.Parameters cameraParameters; + + public CameraProxy1(int width, int height) { + layoutWidth = width; + layoutHeight = height; + status = STATUS_INIT; + textureStatus = TEXTURE_STATUS_INITED; + } + + public int[] getPreviewSize() { + return previewSize; + } + + private Camera.Size getPreviewSize(List list) { + ArrayList validSizeList = new ArrayList(); + float ratio = (float) layoutHeight / layoutWidth; + for (Camera.Size size : list) { + if ((float) size.width / size.height >= ratio && size.width > minPreviewCandidateWidth) { + validSizeList.add(size); + } + } + + // 没有符合条件的,直接返回第一个吧 + if (validSizeList.size() == 0) { + UiLog.info("no valid preview size"); + return list.get(0); + } + + Camera.Size size = (Camera.Size) Collections.min(validSizeList, new Comparator() { + @Override + public int compare(Camera.Size s1, Camera.Size s2) { + return s1.width - s2.width; + } + }); + + return (Camera.Size) validSizeList.get(1); + // return size; + } + + + public Camera open(boolean isOpenBack) { + int numberOfCameras = getNumberOfCameras(); + UiLog.info("cameraNumber is " + numberOfCameras); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int i = 0; i < numberOfCameras; i++) { + getCameraInfo(i, cameraInfo); + if (isOpenBack) { + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + caculatePreviewRotation(cameraInfo); + return Camera.open(i); + } + } else { + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + caculatePreviewRotation(cameraInfo); + return Camera.open(i); + } + } + + } + // 兼容只有前置摄像头的开发板 + return Camera.open(0); + } + + public void setDisplayRotation(int degree) { + displayRotation = degree; + } + + private void caculatePreviewRotation(Camera.CameraInfo info) { + int degree; + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + degree = (info.orientation + displayRotation) % 360; + degree = (360 - degree) % 360; // compensate the mirror + previewCaptureRotation = (360 - degree) % 360; + } else { // back-facing + degree = (info.orientation - displayRotation + 360) % 360; + previewCaptureRotation = (360 + degree) % 360; + } + + previewRotation = degree; + } + + @Override + public void startPreview() { + // MIUI上会在activity stop时destory关闭相机,触发textureview的destory方法 + if (hasDestoryUnexcepted) { + openCamera(); + } + // 如果已经TextureAvailable,设置texture并且预览,(必须先调用了openCamera) + if (textureStatus == TEXTURE_STATUS_READY) { + try { + mCamera.setPreviewTexture(mSurfaceTexture); + } catch (IOException e) { + e.printStackTrace(); + } + + mCamera.startPreview(); + mCamera.setPreviewCallback(mPreviewCallback); + status = STATUS_PREVIEWING; + return; + } + } + + public void resumePreview() { + mCamera.startPreview(); + } + + private byte[] currentFrameData; + + private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() { + @Override + public void onPreviewFrame(byte[] data, Camera camera) { + // 在某些机型和某项项目中,某些帧的data的数据不符合nv21的格式,需要过滤,否则后续处理会导致crash + if (data.length != cameraParameters.getPreviewSize().width + * cameraParameters.getPreviewSize().height * 1.5) { + return; + } + currentFrameData = data; + } + }; + + public void openCamera() { + mCamera = open(isBack); + cameraParameters = mCamera.getParameters(); + Camera.Size previewSize = cameraParameters.getPreviewSize(); + List supportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); + Camera.Size size = getPreviewSize(supportedPreviewSizes); + if (previewRotation == 90 || previewRotation == 270) { + this.previewSize[0] = size.height; + this.previewSize[1] = size.width; + } else { + this.previewSize[0] = size.width; + this.previewSize[1] = size.height; + } + previewSize.height = size.height; + if (isBack && cameraParameters.getSupportedFocusModes().contains( + Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { + cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } + cameraParameters.setPreviewSize(size.width, size.height); + mCamera.setDisplayOrientation(previewRotation); + mCamera.setParameters(cameraParameters); + status = STATUS_OPENED; + if (mCameraListener != null) { + mCameraListener.onSwitchCamera(); + } + } + + public void closeCamera() { + stopPreview(); + mCamera.setPreviewCallback(null); + mCamera.release(); + mCamera = null; + status = STATUS_INIT; + } + + @Override + public void stopPreview() { + + mCamera.stopPreview(); + mCamera.setPreviewCallback(null); + status = STATUS_OPENED; + Log.e("literrr", "stoped"); + } + + @Override + public void switchSide() { + isBack = !isBack; + stopPreview(); + closeCamera(); + openCamera(); + startPreview(); + } + + private Bitmap convertPreviewDataToBitmap(byte[] data) { + Camera.Size size = cameraParameters.getPreviewSize(); + YuvImage img = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null); + ByteArrayOutputStream os = null; + os = new ByteArrayOutputStream(data.length); + img.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, os); + byte[] jpeg = os.toByteArray(); + Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length); + Bitmap bitmapRotate; + if (isBack) { + bitmapRotate = ImageUtil.createRotateBitmap(bitmap, previewCaptureRotation); + } else { + bitmapRotate = ImageUtil.createMirrorRotateBitmap(bitmap, previewCaptureRotation); + } + try { + os.close(); + } catch (IOException e) { + UiLog.info("convertPreviewDataToBitmap close bitmap"); + } + return bitmapRotate; + } + + @Override + public void takePicture(CameraListener.TakePictureListener listener) { + if (currentFrameData != null) { + Bitmap bitmap = convertPreviewDataToBitmap(currentFrameData); + listener.onTakenPicture(bitmap); + UiLog.info("convert bitmap success"); + } + } + + @Override + public void setEventListener(CameraListener.CommonListener listener) { + mCameraListener = listener; + } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + mSurfaceTexture = surface; + textureStatus = TEXTURE_STATUS_READY; + mCameraListener.onSurfaceReady(); + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + hasDestoryUnexcepted = true; + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java new file mode 100644 index 0000000000..9e656d4eaf --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java @@ -0,0 +1,27 @@ +package com.baidu.paddle.fastdeploy.app.ui.camera; + +import android.view.TextureView; + + +/** + * Created by ruanshimin on 2017/3/29. + */ +public interface ICameraProxy extends TextureView.SurfaceTextureListener { + void openCamera(); + + void setDisplayRotation(int degree); + + void startPreview(); + + void stopPreview(); + + void closeCamera(); + + void switchSide(); + + int[] getPreviewSize(); + + void takePicture(CameraListener.TakePictureListener listener); + + void setEventListener(CameraListener.CommonListener commonListener); +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/ActionBarLayout.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/ActionBarLayout.java similarity index 94% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/ActionBarLayout.java rename to java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/ActionBarLayout.java index 6616a290b3..099219fa9f 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/ActionBarLayout.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/ActionBarLayout.java @@ -1,4 +1,4 @@ -package com.baidu.paddle.fastdeploy.app.ui; +package com.baidu.paddle.fastdeploy.app.ui.layout; import android.content.Context; import android.graphics.Color; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java new file mode 100644 index 0000000000..1d11b5a3cd --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java @@ -0,0 +1,37 @@ +package com.baidu.paddle.fastdeploy.app.ui.layout; + +import android.content.Context; +import android.graphics.Color; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +/** + * Created by ruanshimin on 2018/5/3. + */ + +public class OperationFrameLayout extends RelativeLayout { + private int layoutHeight = 360; + + public OperationFrameLayout(@NonNull Context context) { + super(context); + } + + public OperationFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public OperationFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = MeasureSpec.getSize(heightMeasureSpec); + setMeasuredDimension(width, layoutHeight); + setBackgroundColor(Color.BLACK); + } + +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java new file mode 100644 index 0000000000..85a36e9d81 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java @@ -0,0 +1,155 @@ +package com.baidu.paddle.fastdeploy.app.ui.util; + +import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.media.ExifInterface; +import android.util.Log; + +/** + * Created by ruanshimin on 2018/5/8. + */ + +public class ImageUtil { + private static final String TAG = "CameraExif"; + + public static Bitmap createRotateBitmap(Bitmap bitmap, int rotation) { + Matrix matrix = new Matrix(); + matrix.postRotate(rotation); + return Bitmap.createBitmap( + bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); + } + + public static Bitmap createMirrorRotateBitmap(Bitmap bitmap, int rotation) { + Matrix matrix = new Matrix(); + matrix.postRotate(rotation); + matrix.postScale(-1, 1); + return Bitmap.createBitmap( + bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); + } + + public static int exifToDegrees(int exifOrientation) { + if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { + return 90; + } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { + return 180; + } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { + return 270; + } + return 0; + } + + // Returns the degrees in clockwise. Values are 0, 90, 180, or 270. + public static int getOrientation(byte[] jpeg) { + if (jpeg == null) { + return 0; + } + + int offset = 0; + int length = 0; + + // ISO/IEC 10918-1:1993(E) + while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) { + int marker = jpeg[offset] & 0xFF; + + // Check if the marker is a padding. + if (marker == 0xFF) { + continue; + } + offset++; + + // Check if the marker is SOI or TEM. + if (marker == 0xD8 || marker == 0x01) { + continue; + } + // Check if the marker is EOI or SOS. + if (marker == 0xD9 || marker == 0xDA) { + break; + } + + // Get the length and check if it is reasonable. + length = pack(jpeg, offset, 2, false); + if (length < 2 || offset + length > jpeg.length) { + Log.e(TAG, "Invalid length"); + return 0; + } + + // Break if the marker is EXIF in APP1. + if (marker == 0xE1 && length >= 8 + && pack(jpeg, offset + 2, 4, false) == 0x45786966 + && pack(jpeg, offset + 6, 2, false) == 0) { + offset += 8; + length -= 8; + break; + } + + // Skip other markers. + offset += length; + length = 0; + } + + // JEITA CP-3451 Exif Version 2.2 + if (length > 8) { + // Identify the byte order. + int tag = pack(jpeg, offset, 4, false); + if (tag != 0x49492A00 && tag != 0x4D4D002A) { + Log.e(TAG, "Invalid byte order"); + return 0; + } + boolean littleEndian = (tag == 0x49492A00); + + // Get the offset and check if it is reasonable. + int count = pack(jpeg, offset + 4, 4, littleEndian) + 2; + if (count < 10 || count > length) { + Log.e(TAG, "Invalid offset"); + return 0; + } + offset += count; + length -= count; + + // Get the count and go through all the elements. + count = pack(jpeg, offset - 2, 2, littleEndian); + while (count-- > 0 && length >= 12) { + // Get the tag and check if it is orientation. + tag = pack(jpeg, offset, 2, littleEndian); + if (tag == 0x0112) { + // We do not really care about type and count, do we? + int orientation = pack(jpeg, offset + 8, 2, littleEndian); + switch (orientation) { + case 1: + return 0; + case 3: + return 180; + case 6: + return 90; + case 8: + return 270; + default: + return 0; + } + } + offset += 12; + length -= 12; + } + } + + Log.i(TAG, "Orientation not found"); + return 0; + } + + private static int pack(byte[] bytes, int offset, int length, + boolean littleEndian) { + int step = 1; + if (littleEndian) { + offset += length - 1; + step = -1; + } + + int value = 0; + while (length-- > 0) { + value = (value << 8) | (bytes[offset] & 0xFF); + offset += step; + } + return value; + } + +} \ No newline at end of file diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java new file mode 100644 index 0000000000..c36e370906 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java @@ -0,0 +1,14 @@ +package com.baidu.paddle.fastdeploy.app.ui.util; + +import java.text.DecimalFormat; + +/** + * Created by ruanshimin on 2018/5/24. + */ + +public class StringUtil { + public static String formatFloatString(float number) { + DecimalFormat df = new DecimalFormat("0.00"); + return df.format(number); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java new file mode 100644 index 0000000000..00772e74fb --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2017 Baidu, Inc. All Rights Reserved. + */ +package com.baidu.paddle.fastdeploy.app.ui.util; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ThreadPoolManager { + + static Timer timerFocus = null; + + /* + * 对焦频率 + */ + static final long cameraScanInterval = 2000; + + /* + * 线程池大小 + */ + private static int poolCount = Runtime.getRuntime().availableProcessors(); + + private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(poolCount); + + private static ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); + + /** + * 给线程池添加任务 + * + * @param runnable 任务 + */ + public static void execute(Runnable runnable) { + fixedThreadPool.execute(runnable); + } + + /** + * 单独线程任务 + * + * @param runnable 任务 + */ + public static void executeSingle(Runnable runnable) { + singleThreadPool.execute(runnable); + } + + /** + * 创建一个定时对焦的timer任务 + * + * @param runnable 对焦代码 + * @return Timer Timer对象,用来终止自动对焦 + */ + public static Timer createAutoFocusTimerTask(final Runnable runnable) { + if (timerFocus != null) { + return timerFocus; + } + timerFocus = new Timer(); + TimerTask task = new TimerTask() { + @Override + public void run() { + runnable.run(); + } + }; + timerFocus.scheduleAtFixedRate(task, 0, cameraScanInterval); + return timerFocus; + } + + /** + * 终止自动对焦任务,实际调用了cancel方法并且清空对象 + * 但是无法终止执行中的任务,需额外处理 + */ + public static void cancelAutoFocusTimer() { + if (timerFocus != null) { + timerFocus.cancel(); + timerFocus = null; + } + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java new file mode 100644 index 0000000000..ebf6c41115 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java @@ -0,0 +1,15 @@ +package com.baidu.paddle.fastdeploy.app.ui.util; + +import android.util.Log; + +/** + * Created by ruanshimin on 2018/5/4. + */ + +public class UiLog { + private static final String TAG = "edge_log"; + + public static void info(String log) { + Log.i(TAG, log); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java new file mode 100644 index 0000000000..eefca92140 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java @@ -0,0 +1,162 @@ +package com.baidu.paddle.fastdeploy.app.ui.view; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + + +/** + * Created by ruanshimin on 2018/5/7. + */ + +public class PreviewDecoratorView extends View { + + static final String RUNNING_HINT_TEXT = "对准识别物体,自动识别物体"; + + static final String STOP_HINT_TEXT = "已暂定实时识别,请点击下方按钮开启"; + + private String hintText = STOP_HINT_TEXT; + + public PreviewDecoratorView(Context context) { + super(context); + } + + public PreviewDecoratorView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public PreviewDecoratorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + + public void setStatus(boolean isRunning) { + if (isRunning) { + hintText = RUNNING_HINT_TEXT; + } else { + hintText = STOP_HINT_TEXT; + } + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + int offset = 50; + int offsetBottom = 170; + int stokeWidth = 15; + int extendOffset = stokeWidth / 2; + int height = getHeight(); + int width = getWidth(); + int barSize = 40; + + + canvas.save(); + + Paint paintBar = new Paint(); + paintBar.setColor(Color.WHITE); + paintBar.setStrokeWidth(stokeWidth); + paintBar.setStyle(Paint.Style.STROKE); + + + Point leftTop = new Point(offset, offset); + Point rightTop = new Point(width - offset, offset); + Point leftBottom = new Point(offset, height - offsetBottom); + Point rightBottom = new Point(width - offset, height - offsetBottom); + + + Path path = new Path(); + path.moveTo(leftTop.x, leftTop.y + barSize); + path.lineTo(leftTop.x, leftTop.y); + path.lineTo(leftTop.x + barSize, leftTop.y); + + path.moveTo(rightTop.x - barSize, leftTop.y); + path.lineTo(rightTop.x, rightTop.y); + path.lineTo(rightTop.x, rightTop.y + barSize); + + path.moveTo(leftBottom.x, leftBottom.y - barSize); + path.lineTo(leftBottom.x, leftBottom.y); + path.lineTo(leftBottom.x + barSize, leftBottom.y); + + path.moveTo(rightBottom.x - barSize, rightBottom.y); + path.lineTo(rightBottom.x, rightBottom.y); + path.lineTo(rightBottom.x, rightBottom.y - barSize); + + + // 绘制半透明遮罩 + Rect rect = new Rect(0, 0, width, height); + Paint paint = new Paint(); + paint.setColor(Color.BLACK); + paint.setAlpha(50); + canvas.drawRect(rect, paint); + + // 擦除可见部分半透明遮罩 + rect = new Rect(leftTop.x - extendOffset, leftTop.y - extendOffset, + rightBottom.x + extendOffset, rightBottom.y + extendOffset); + canvas.clipRect(rect); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + + // 绘制四个小角 + canvas.drawPath(path, paintBar); + canvas.restore(); + // 设置留给hint的位置 + rect = new Rect(0, rightBottom.y + extendOffset, width, height); + + drawHint(canvas, rect, hintText); + + super.onDraw(canvas); + } + + public void drawHint(Canvas canvas, Rect rect, String text) { + int textSizePx = 16; + int imageSizePx = 48; + int padInTextAndIcon = 22; + Paint textPaint = new Paint(); + textPaint.setTextSize(textSizePx); + textPaint.setColor(Color.WHITE); + textPaint.setTextAlign(Paint.Align.LEFT); + + Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.scan_icon); + + float textWidth = getTextWidth(this.getContext(), text, textPaint, textSizePx); + int width = padInTextAndIcon + imageSizePx + (int) textWidth; + int height = imageSizePx; + + int startX = rect.left + (rect.width() - width) / 2; + int startY = rect.top + (rect.height() - height) / 2; + + Rect srcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + Rect destRect = new Rect(startX, startY, startX + imageSizePx, startY + imageSizePx); + + Paint mBitPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBitPaint.setFilterBitmap(true); + mBitPaint.setDither(true); + canvas.drawBitmap(bitmap, srcRect, destRect, mBitPaint); + + startX += padInTextAndIcon + imageSizePx; + + canvas.drawText(text, startX, startY + textSizePx + 23, textPaint); + } + + public float getTextWidth(Context context, String text, Paint paint, int textSize) { + float scaledDensity = getResources().getDisplayMetrics().scaledDensity; + paint.setTextSize(scaledDensity * textSize); + return paint.measureText(text); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java new file mode 100644 index 0000000000..0d01c7cf1f --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java @@ -0,0 +1,144 @@ +package com.baidu.paddle.fastdeploy.app.ui.view; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.util.AttributeSet; +import android.view.Surface; +import android.view.TextureView; + +import com.baidu.paddle.fastdeploy.app.ui.camera.CameraListener; +import com.baidu.paddle.fastdeploy.app.ui.camera.CameraProxy1; +import com.baidu.paddle.fastdeploy.app.ui.camera.ICameraProxy; + +/** + * Created by ruanshimin on 2018/5/3. + */ + +public class PreviewView extends TextureView { + ICameraProxy mCameraProxy; + private int layoutWidth; + private int layoutHeight; + private int actualHeight; + private int cropHeight; + + public PreviewView(Context context) { + super(context); + } + + public PreviewView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public PreviewView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + /** + * 手动调用开始预览 + */ + public void start() { + if (mCameraProxy != null) { + mCameraProxy.startPreview(); + } + } + + /** + * 释放摄像头 + */ + public void destory() { + if (mCameraProxy != null) { + mCameraProxy.closeCamera(); + } + } + + /** + * 手动停止 + */ + public void stopPreview() { + mCameraProxy.stopPreview(); + } + + /** + * 设置实际可见layout的长宽 + */ + public void setLayoutSize(int width, int height) { + layoutWidth = width; + layoutHeight = height; + } + + public void takePicture(final CameraListener.TakePictureListener listener) { + // 裁剪图片 + mCameraProxy.takePicture(new CameraListener.TakePictureListener() { + @Override + public void onTakenPicture(Bitmap bitmap) { + Bitmap cropBitmap = Bitmap.createBitmap(bitmap, 0, 0, + bitmap.getWidth(), cropHeight); + listener.onTakenPicture(cropBitmap); + } + }); + } + + /** + * 切换摄像头面 + */ + public void switchSide() { + mCameraProxy.switchSide(); + } + + public int getActualHeight() { + return actualHeight; + } + + private void setDisplayDegree() { + int rotation = ((Activity) this.getContext()).getWindowManager().getDefaultDisplay() + .getRotation(); + int degrees = 0; + switch (rotation) { + case Surface.ROTATION_0: + degrees = 0; + break; + case Surface.ROTATION_90: + degrees = 90; + break; + case Surface.ROTATION_180: + degrees = 180; + break; + case Surface.ROTATION_270: + degrees = 270; + break; + default: + degrees = 0; + } + mCameraProxy.setDisplayRotation(degrees); + } + + private void refreshCropHeight() { + int[] size = mCameraProxy.getPreviewSize(); + actualHeight = (int) (((float) size[1] / size[0]) * layoutWidth); + cropHeight = (int) (((float) layoutHeight / layoutWidth) * size[0]); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (mCameraProxy == null) { + mCameraProxy = new CameraProxy1(layoutWidth, layoutHeight); + setDisplayDegree(); + setSurfaceTextureListener(mCameraProxy); + mCameraProxy.openCamera(); + refreshCropHeight(); + mCameraProxy.setEventListener(new CameraListener.CommonListener() { + @Override + public void onSurfaceReady() { + mCameraProxy.startPreview(); + } + + @Override + public void onSwitchCamera() { + refreshCropHeight(); + } + }); + } + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java new file mode 100644 index 0000000000..a028c0f9cd --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultListView.java @@ -0,0 +1,47 @@ +package com.baidu.paddle.fastdeploy.app.ui.view; + +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.widget.ListView; + +/** + * Created by ruanshimin on 2018/5/14. + */ + +public class ResultListView extends ListView { + public ResultListView(Context context) { + super(context); + } + + public ResultListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ResultListView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + private Handler handler; + + public void setHandler(Handler mHandler) { + handler = mHandler; + } + + public void clear() { + handler.post(new Runnable() { + @Override + public void run() { + removeAllViewsInLayout(); + invalidate(); + } + }); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, + MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java new file mode 100644 index 0000000000..13e3241ee6 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java @@ -0,0 +1,381 @@ +package com.baidu.paddle.fastdeploy.app.ui.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Handler; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.ui.util.StringUtil; +import com.baidu.paddle.fastdeploy.app.ui.view.model.BasePolygonResultModel; +import com.baidu.paddle.fastdeploy.app.ui.view.model.PoseViewResultModel; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +/** + * Created by ruanshimin on 2018/5/15. + */ + +public class ResultMaskView extends View { + private static final int[][] COLOR_MAP_DEF = { + {0, 0, 0}, + {244, 35, 232}, + {70, 70, 70}, + {102, 102, 156}, + {190, 153, 153}, + {153, 153, 153}, + {250, 170, 30}, + {220, 220, 0}, + {107, 142, 35}, + {152, 251, 152}, + {70, 130, 180}, + {220, 20, 60}, + {255, 0, 0}, + {0, 0, 142}, + {0, 0, 70}, + {0, 60, 100}, + {0, 80, 100}, + {0, 0, 230}, + {119, 11, 32}, + {128, 64, 128} + }; + + private float sizeRatio; + private List mResultModelList; + private Point originPt = new Point(); + private int imgWidth; + private int imgHeight; + private Paint textPaint; + + private Handler handler; + + public void setHandler(Handler mHandler) { + handler = mHandler; + } + + public ResultMaskView(Context context) { + super(context); + } + + private Map paintFixPool = new HashMap<>(); + + public ResultMaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + + + public void setPolygonListInfo(List modelList, int width, int height) { + imgWidth = width; + imgHeight = height; + mResultModelList = modelList; + handler.post(new Runnable() { + @Override + public void run() { + invalidate(); + } + }); + } + + + public void clear() { + mResultModelList = null; + handler.post(new Runnable() { + @Override + public void run() { + invalidate(); + } + }); + } + + private void preCaculate() { + float ratio = (float) getMeasuredWidth() / (float) getMeasuredHeight(); + float ratioBitmap = (float) imgWidth / (float) imgHeight; + // | |#####| |模式 + if (ratioBitmap < ratio) { + sizeRatio = (float) getMeasuredHeight() / (float) imgHeight; + int x = (int) (getMeasuredWidth() - sizeRatio * imgWidth) / 2; + originPt.set(x, 0); + } else { + // ------------ + // + // ------------ + // ############ + // ------------ + // + // ------------ + sizeRatio = (float) getMeasuredWidth() / (float) imgWidth; + int y = (int) (getMeasuredHeight() - sizeRatio * imgHeight) / 2; + originPt.set(0, y); + } + + } + + private Map paintRandomPool = new HashMap<>(); + + public ResultMaskView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + textPaint = new Paint(); + textPaint.setTextSize(30); + textPaint.setARGB(255, 255, 255, 255); + } + + private Paint getRandomMaskPaint(int index) { + if (paintRandomPool.containsKey(index)) { + + return paintRandomPool.get(index); + } + + int[] seed = new int[3]; + int offset = index % 3; + seed[offset] = 255; + + Paint paint = new Paint(); + Random rnd = new Random(); + paint.setARGB(170, + (rnd.nextInt(255) + seed[0]) / 2, + (rnd.nextInt(255) + seed[1]) / 2, + (rnd.nextInt(255) + seed[2]) / 2); + paint.setStyle(Paint.Style.FILL_AND_STROKE); + + paintRandomPool.put(index, paint); + + return paint; + } + + private Paint getFixColorPaint(int colorId) { + + // float alpha = 90; + String[] colors = {"#FF0000", "#FF0000", "#00FF00", "#0000FF", "#FF00FF"}; + int index = colorId % colors.length; + if (paintFixPool.containsKey(index)) { + return paintFixPool.get(index); + } + + int color = Color.parseColor(colors[index]); + Paint paint = new Paint(); + paint.setColor(color); + //paint.setAlpha(90); + paintFixPool.put(index, paint); + return paint; + } + + @Override + protected void onDraw(Canvas canvas) { + // 实时识别的时候第一次渲染 + if (mResultModelList == null) { + super.onDraw(canvas); + return; + } + + preCaculate(); + + int stokeWidth = 5; + + int fontSize = 38; + int labelPadding = 5; + int labelHeight = 46 + 2 * labelPadding; + Paint paint = new Paint(); + paint.setColor(Color.parseColor("#3B85F5")); + paint.setStrokeWidth(stokeWidth); + paint.setStyle(Paint.Style.STROKE); + + Paint paintFillAlpha = new Paint(); + paintFillAlpha.setStyle(Paint.Style.FILL); + paintFillAlpha.setColor(Color.parseColor("#3B85F5")); + paintFillAlpha.setAlpha(50); + + Paint paintFill = new Paint(); + paintFill.setStyle(Paint.Style.FILL); + paintFill.setColor(Color.parseColor("#3B85F5")); + + Paint paintText = new Paint(); + paintText.setColor(Color.WHITE); + paintText.setTextAlign(Paint.Align.LEFT); + paintText.setTextSize(fontSize); + DecimalFormat df = new DecimalFormat("0.00"); + + + List points; + for (int i = 0; i < mResultModelList.size(); i++) { + + BasePolygonResultModel model = mResultModelList.get(i); + Path path = new Path(); + List polygon = model.getBounds(sizeRatio, originPt); + + path.moveTo(polygon.get(0).x, polygon.get(0).y); + for (int j = 1; j < polygon.size(); j++) { + path.lineTo(polygon.get(j).x, polygon.get(j).y); + } + path.close(); + + if (model.isDrawPoints()) { + Paint paintFillPoint = new Paint(); + paintFillPoint.setStyle(Paint.Style.FILL_AND_STROKE); + + paintFillPoint.setColor(Color.YELLOW); + List polygonPoints = model.getBounds(sizeRatio, originPt); + for (Point p : polygonPoints) { + canvas.drawCircle(p.x, p.y, 10 * sizeRatio, paintFillPoint); + } + + } + + // 绘制框 + if (!model.isHasMask()) { + if (model instanceof PoseViewResultModel && model.isHasGroupColor()) { + paint = getFixColorPaint(model.getColorId()); + paint.setStrokeWidth(stokeWidth); + paint.setStyle(Paint.Style.STROKE); + paint.setAlpha(90); + } + canvas.drawPath(path, paint); + canvas.drawPath(path, paintFillAlpha); + if (model.isRect()) { + Rect rect = model.getRect(sizeRatio, originPt); + canvas.drawRect(new Rect(rect.left, rect.top, rect.right, + rect.top + labelHeight), paintFill); + } + } + if (model.isRect()) { + Rect rect = model.getRect(sizeRatio, originPt); + canvas.drawText(model.getName() + " " + StringUtil.formatFloatString(model.getConfidence()), + rect.left + labelPadding, + rect.top + fontSize + labelPadding, paintText); + } + + if (model.isTextOverlay()) { + canvas.drawText(model.getName(), + polygon.get(0).x, polygon.get(0).y, textPaint); + } + + // 绘制mask + if (model.isHasMask()) { + if (!model.isSemanticMask()) { + // 实例分割绘制 + Paint paintMask = getRandomMaskPaint(model.getColorId()); + points = new ArrayList<>(); + byte[] maskData = model.getMask(); + + for (int w = 0; w < imgWidth * sizeRatio; w++) { + for (int h = 0; h < imgHeight * sizeRatio; h++) { + + int realX = (int) (w / sizeRatio); + int realY = (int) (h / sizeRatio); + + int offset = imgWidth * realY + realX; + if (offset < maskData.length && maskData[offset] == 1) { + points.add(originPt.x + (float) w); + points.add(originPt.y + (float) h); + } + } + } + + float[] ptft = new float[points.size()]; + for (int j = 0; j < points.size(); j++) { + ptft[j] = points.get(j); + } + canvas.drawPoints(ptft, paintMask); + } else { + // 语义分割绘制 + drawSemanticMask(canvas, model); + } + } + } + + + super.onDraw(canvas); + } + + /** + * 语义分割基于mask不同值绘制颜色 + */ + private void drawSemanticMask(Canvas canvas, BasePolygonResultModel model) { + List colorPointsPairList = new ArrayList<>(); + for (int[] rgb : COLOR_MAP_DEF) { + Paint paint = new Paint(); + paint.setARGB(170, rgb[0], rgb[1], rgb[2]); + colorPointsPairList.add(new ColorPointsPair(paint)); + } + + byte[] maskData = model.getMask(); + for (int w = 0; w < imgWidth * sizeRatio; w++) { + for (int h = 0; h < imgHeight * sizeRatio; h++) { + + int realX = (int) (w / sizeRatio); + int realY = (int) (h / sizeRatio); + + int offset = imgWidth * realY + realX; + byte label = maskData[offset]; + + if (label >= colorPointsPairList.size()) { + for (int i = colorPointsPairList.size(); i <= label; i++ ) { + Paint newPaint = getRandomMaskPaint(i); + colorPointsPairList.add(new ColorPointsPair(newPaint)); + } + } + + colorPointsPairList.get(label).addPoint(originPt.x + (float) w); + colorPointsPairList.get(label).addPoint(originPt.y + (float) h); + } + } + + for (ColorPointsPair pair : colorPointsPairList) { + float[] points = pair.getPointsArray(); + if (points != null) { + canvas.drawPoints(points, pair.getPaint()); + } + } + } + + /** + * 用于分割模型,一个颜色对应一系列点 + */ + private class ColorPointsPair { + private final Paint paint; + private List points; + + public ColorPointsPair(Paint paint) { + this.paint = paint; + } + + public void addPoint(float point) { + if (points == null) { + points = new ArrayList<>(); + } + points.add(point); + } + + public float[] getPointsArray() { + if (points == null || points.size() == 0) { + return null; + } + float[] array = new float[points.size()]; + for (int i = 0; i < points.size(); i++) { + array[i] = points.get(i); + } + return array; + } + + public Paint getPaint() { + return paint; + } + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/Utils.java similarity index 99% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java rename to java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/Utils.java index ef990237fd..7f415f3db6 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/Utils.java @@ -1,4 +1,4 @@ -package com.baidu.paddle.fastdeploy.app.ui; +package com.baidu.paddle.fastdeploy.app.ui.view; import android.content.Context; import android.content.res.Resources; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java new file mode 100644 index 0000000000..5f854aed13 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java @@ -0,0 +1,47 @@ +package com.baidu.paddle.fastdeploy.app.ui.view.adapter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import com.baidu.paddle.fastdeploy.app.examples.R; +import com.baidu.paddle.fastdeploy.app.ui.util.StringUtil; +import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; + +import java.util.List; + +/** + * Created by ruanshimin on 2018/5/13. + */ + +public class DetectResultAdapter extends ArrayAdapter { + private int resourceId; + + public DetectResultAdapter(@NonNull Context context, int resource) { + super(context, resource); + } + + public DetectResultAdapter(@NonNull Context context, int resource, @NonNull List objects) { + super(context, resource, objects); + resourceId = resource; + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + BaseResultModel model = getItem(position); + View view = LayoutInflater.from(getContext()).inflate(resourceId, null); + TextView indexText = (TextView) view.findViewById(R.id.index); + TextView nameText = (TextView) view.findViewById(R.id.name); + TextView confidenceText = (TextView) view.findViewById(R.id.confidence); + indexText.setText(String.valueOf(model.getIndex())); + nameText.setText(String.valueOf(model.getName())); + confidenceText.setText(StringUtil.formatFloatString(model.getConfidence())); + return view; + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java new file mode 100644 index 0000000000..6b967c3b26 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java @@ -0,0 +1,149 @@ +package com.baidu.paddle.fastdeploy.app.ui.view.model; + +import android.graphics.Point; +import android.graphics.Rect; + +import java.util.ArrayList; +import java.util.List; + +public class BasePolygonResultModel extends BaseResultModel { + private int colorId; + private boolean isRect; + private boolean isTextOverlay; + + private boolean isHasGroupColor = false; + private boolean isDrawPoints = false; + + + public boolean isTextOverlay() { + return isTextOverlay; + } + + public void setTextOverlay(boolean textOverlay) { + isTextOverlay = textOverlay; + } + + public int getColorId() { + return colorId; + } + + public void setColorId(int colorId) { + this.colorId = colorId; + } + + private byte[] mask; + + /** + * 是否是语义分割mask + */ + private boolean semanticMask; + + private Rect rect; + + BasePolygonResultModel() { + super(); + } + + BasePolygonResultModel(int index, String name, float confidence, Rect bounds) { + super(index, name, confidence); + parseFromRect(bounds); + } + + BasePolygonResultModel(int index, String name, float confidence, List bounds) { + super(index, name, confidence); + this.bounds = bounds; + } + + public Rect getRect() { + return rect; + } + + public Rect getRect(float ratio, Point origin) { + return new Rect((int) (origin.x + rect.left * ratio), + (int) (origin.y + rect.top * ratio), + (int) (origin.x + rect.right * ratio), + (int) (origin.y + rect.bottom * ratio)); + } + + private void parseFromRect(Rect rect) { + Point ptTL = new Point(rect.left, rect.top); + Point ptTR = new Point(rect.right, rect.top); + Point ptRB = new Point(rect.right, rect.bottom); + Point ptLB = new Point(rect.left, rect.bottom); + this.bounds = new ArrayList<>(); + this.bounds.add(ptTL); + this.bounds.add(ptTR); + this.bounds.add(ptRB); + this.bounds.add(ptLB); + this.rect = rect; + isRect = true; + } + + public boolean isRect() { + return isRect; + } + + public void setRect(boolean rect) { + isRect = rect; + } + + public byte[] getMask() { + return mask; + } + + public void setMask(byte[] mask) { + this.mask = mask; + } + + public void setSemanticMask(boolean semanticMask) { + this.semanticMask = semanticMask; + } + + public boolean isSemanticMask() { + return semanticMask; + } + + private List bounds; + + public List getBounds() { + return bounds; + } + + public List getBounds(float ratio, Point origin) { + List pointList = new ArrayList<>(); + for (Point pt : bounds) { + int nx = (int) (origin.x + pt.x * ratio); + int ny = (int) (origin.y + pt.y * ratio); + pointList.add(new Point(nx, ny)); + } + return pointList; + } + + public void setBounds(List bounds) { + this.bounds = bounds; + } + + public void setBounds(Rect bounds) { + parseFromRect(bounds); + } + + public boolean isHasMask() { + return (mask != null); + } + + public boolean isHasGroupColor() { + return isHasGroupColor; + } + + public void setHasGroupColor(boolean hasGroupColor) { + isHasGroupColor = hasGroupColor; + } + + public boolean isDrawPoints() { + return isDrawPoints; + } + + public void setDrawPoints(boolean drawPoints) { + isDrawPoints = drawPoints; + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java new file mode 100644 index 0000000000..5cab72c500 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BaseResultModel.java @@ -0,0 +1,45 @@ +package com.baidu.paddle.fastdeploy.app.ui.view.model; + +/** + * Created by ruanshimin on 2018/5/16. + */ + +public class BaseResultModel { + private int index; + private String name; + private float confidence; + + public BaseResultModel() { + + } + + public BaseResultModel(int index, String name, float confidence) { + this.index = index; + this.name = name; + this.confidence = confidence; + } + + public float getConfidence() { + return confidence; + } + + public void setConfidence(float confidence) { + this.confidence = confidence; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java new file mode 100644 index 0000000000..3652903e3f --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java @@ -0,0 +1,11 @@ +package com.baidu.paddle.fastdeploy.app.ui.view.model; + +public class PoseViewResultModel extends BasePolygonResultModel { + public PoseViewResultModel() { + super(); + setRect(false); + setTextOverlay(false); + setDrawPoints(true); + } + +} diff --git a/java/android/app/src/main/res/layout/activity_main.xml b/java/android/app/src/main/res/layout/activity_main.xml index b6efea6d6c..8fe754aa11 100644 --- a/java/android/app/src/main/res/layout/activity_main.xml +++ b/java/android/app/src/main/res/layout/activity_main.xml @@ -1,163 +1,14 @@ - + android:layout_height="match_parent"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + diff --git a/java/android/app/src/main/res/layout/camera_page.xml b/java/android/app/src/main/res/layout/camera_page.xml new file mode 100644 index 0000000000..b89cf725ce --- /dev/null +++ b/java/android/app/src/main/res/layout/camera_page.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/android/app/src/main/res/layout/result_detect_item.xml b/java/android/app/src/main/res/layout/result_detect_item.xml new file mode 100644 index 0000000000..6a2b09ebff --- /dev/null +++ b/java/android/app/src/main/res/layout/result_detect_item.xml @@ -0,0 +1,26 @@ + + + + + + + + + \ No newline at end of file diff --git a/java/android/app/src/main/res/layout/result_page.xml b/java/android/app/src/main/res/layout/result_page.xml new file mode 100644 index 0000000000..a7b17c0535 --- /dev/null +++ b/java/android/app/src/main/res/layout/result_page.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/android/app/src/main/res/layout/result_table_popview.xml b/java/android/app/src/main/res/layout/result_table_popview.xml new file mode 100644 index 0000000000..681dfb42fa --- /dev/null +++ b/java/android/app/src/main/res/layout/result_table_popview.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + . + + \ No newline at end of file diff --git a/java/android/app/src/main/res/values/strings.xml b/java/android/app/src/main/res/values/strings.xml index 1d8f1c2da8..a2128791fa 100644 --- a/java/android/app/src/main/res/values/strings.xml +++ b/java/android/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - FastDeploy PicoDet + EasyEdge FastDeploy PicoDet FastDeploy PP-OCRv2 @@ -17,6 +17,7 @@ LITE_POWER_HIGH 0.4 true + models/picodet_s_320_coco_lcnet labels/coco_label_list.txt @@ -35,4 +36,4 @@ 阈值控制 重新识别 保存结果 - \ No newline at end of file + diff --git a/java/android/app/src/main/res/values/values.xml b/java/android/app/src/main/res/values/values.xml new file mode 100644 index 0000000000..156146d9ad --- /dev/null +++ b/java/android/app/src/main/res/values/values.xml @@ -0,0 +1,17 @@ + + + 120dp + 46px + + 126px + 136px + + 46px + + 36px + + 15dp + + 15dp + + \ No newline at end of file From 87823173bbc49004d8af6eaac63bba2745b49a7c Mon Sep 17 00:00:00 2001 From: WinterGeng <1558270516@qq.com> Date: Mon, 7 Nov 2022 18:50:53 +0800 Subject: [PATCH 2/2] specification has submitted code. --- .../app/examples/detection/MainActivity.java | 8 +- .../examples/detection/SettingsActivity.java | 6 +- .../fastdeploy/app/ui/{view => }/Utils.java | 2 +- .../app/ui/camera/CameraListener.java | 19 - .../app/ui/camera/CameraProxy1.java | 296 -------------- .../app/ui/camera/ICameraProxy.java | 27 -- .../app/ui/layout/OperationFrameLayout.java | 37 -- .../fastdeploy/app/ui/util/ImageUtil.java | 155 ------- .../fastdeploy/app/ui/util/StringUtil.java | 14 - .../app/ui/util/ThreadPoolManager.java | 78 ---- .../paddle/fastdeploy/app/ui/util/UiLog.java | 15 - .../AppCompatPreferenceActivity.java | 2 +- .../app/ui/{ => view}/CameraSurfaceView.java | 4 +- .../app/ui/view/PreviewDecoratorView.java | 162 -------- .../fastdeploy/app/ui/view/PreviewView.java | 144 ------- .../app/ui/view/ResultMaskView.java | 381 ------------------ .../ui/view/adapter/DetectResultAdapter.java | 9 +- .../ui/view/model/BasePolygonResultModel.java | 149 ------- .../ui/view/model/PoseViewResultModel.java | 11 - ...ity_main.xml => default_activity_main.xml} | 2 +- ...ity_main.xml => default_activity_main.xml} | 4 +- ...amera_page.xml => default_camera_page.xml} | 4 +- ...esult_page.xml => default_result_page.xml} | 4 - ..._item.xml => default_result_page_item.xml} | 0 .../main/res/layout/result_table_popview.xml | 42 -- .../{settings.xml => default_settings.xml} | 0 26 files changed, 23 insertions(+), 1552 deletions(-) rename java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/{view => }/Utils.java (99%) delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java rename java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/{ => view}/AppCompatPreferenceActivity.java (98%) rename java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/{ => view}/CameraSurfaceView.java (99%) delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java delete mode 100644 java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java rename java/android/app/src/main/res/layout-land/{activity_main.xml => default_activity_main.xml} (98%) rename java/android/app/src/main/res/layout/{activity_main.xml => default_activity_main.xml} (80%) rename java/android/app/src/main/res/layout/{camera_page.xml => default_camera_page.xml} (98%) rename java/android/app/src/main/res/layout/{result_page.xml => default_result_page.xml} (96%) rename java/android/app/src/main/res/layout/{result_detect_item.xml => default_result_page_item.xml} (100%) delete mode 100644 java/android/app/src/main/res/layout/result_table_popview.xml rename java/android/app/src/main/res/xml/{settings.xml => default_settings.xml} (100%) diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java index bdafaeb728..e071ae56e5 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/MainActivity.java @@ -31,9 +31,9 @@ import com.baidu.paddle.fastdeploy.RuntimeOption; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.CameraSurfaceView; +import com.baidu.paddle.fastdeploy.app.ui.view.CameraSurfaceView; import com.baidu.paddle.fastdeploy.app.ui.view.ResultListView; -import com.baidu.paddle.fastdeploy.app.ui.view.Utils; +import com.baidu.paddle.fastdeploy.app.ui.Utils; import com.baidu.paddle.fastdeploy.app.ui.view.adapter.DetectResultAdapter; import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; import com.baidu.paddle.fastdeploy.vision.DetectionResult; @@ -90,7 +90,7 @@ protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_main); + setContentView(R.layout.default_activity_main); // Clear all setting items to avoid app crashing due to the incorrect settings initSettings(); @@ -325,7 +325,7 @@ public void initView() { results.add(new BaseResultModel(1, "cup", 0.4f)); results.add(new BaseResultModel(2, "pen", 0.6f)); results.add(new BaseResultModel(3, "tang", 1.0f)); - final DetectResultAdapter adapter = new DetectResultAdapter(this, R.layout.result_detect_item, results); + final DetectResultAdapter adapter = new DetectResultAdapter(this, R.layout.default_result_page_item, results); detectResultView.setAdapter(adapter); detectResultView.invalidate(); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java index edae95ba8e..bcb56d703b 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/detection/SettingsActivity.java @@ -10,8 +10,8 @@ import android.support.v7.app.ActionBar; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.AppCompatPreferenceActivity; -import com.baidu.paddle.fastdeploy.app.ui.view.Utils; +import com.baidu.paddle.fastdeploy.app.ui.view.AppCompatPreferenceActivity; +import com.baidu.paddle.fastdeploy.app.ui.Utils; import java.util.ArrayList; import java.util.List; @@ -46,7 +46,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity implements @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.settings); + addPreferencesFromResource(R.xml.detection_settings); ActionBar supportActionBar = getSupportActionBar(); if (supportActionBar != null) { supportActionBar.setDisplayHomeAsUpEnabled(true); diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/Utils.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java similarity index 99% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/Utils.java rename to java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java index 7f415f3db6..ef990237fd 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/Utils.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/Utils.java @@ -1,4 +1,4 @@ -package com.baidu.paddle.fastdeploy.app.ui.view; +package com.baidu.paddle.fastdeploy.app.ui; import android.content.Context; import android.content.res.Resources; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java deleted file mode 100644 index 377de1b2ef..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.camera; - -import android.graphics.Bitmap; - -/** - * Created by ruanshimin on 2017/11/30. - */ - -public class CameraListener { - public interface CommonListener { - void onSurfaceReady(); - - void onSwitchCamera(); - } - - public interface TakePictureListener { - void onTakenPicture(Bitmap bitmap); - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java deleted file mode 100644 index 0836ac640a..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/CameraProxy1.java +++ /dev/null @@ -1,296 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.camera; - -import static android.hardware.Camera.getCameraInfo; -import static android.hardware.Camera.getNumberOfCameras; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.ImageFormat; -import android.graphics.Rect; -import android.graphics.SurfaceTexture; -import android.graphics.YuvImage; -import android.hardware.Camera; -import android.util.Log; - -import com.baidu.paddle.fastdeploy.app.ui.util.ImageUtil; -import com.baidu.paddle.fastdeploy.app.ui.util.UiLog; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * Created by ruanshimin on 2018/4/16. - */ - -public class CameraProxy1 implements ICameraProxy { - - private static final int STATUS_INIT = 0; - - private static final int STATUS_OPENED = 1; - - private static final int STATUS_PREVIEWING = 2; - - private static final int TEXTURE_STATUS_INITED = 0; - - private static final int TEXTURE_STATUS_READY = 1; - - private SurfaceTexture mSurfaceTexture; - - private boolean isBack = true; - - private Camera mCamera; - - private int status; - private int textureStatus; - - private boolean hasDestoryUnexcepted = false; - - private int layoutWidth; - private int layoutHeight; - - private int[] previewSize = new int[2]; - - private CameraListener.CommonListener mCameraListener; - - private int minPreviewCandidateWidth = 0; - - private int previewRotation = 90; - private int displayRotation = 0; - - private int previewCaptureRotation = 0; - - private Camera.Parameters cameraParameters; - - public CameraProxy1(int width, int height) { - layoutWidth = width; - layoutHeight = height; - status = STATUS_INIT; - textureStatus = TEXTURE_STATUS_INITED; - } - - public int[] getPreviewSize() { - return previewSize; - } - - private Camera.Size getPreviewSize(List list) { - ArrayList validSizeList = new ArrayList(); - float ratio = (float) layoutHeight / layoutWidth; - for (Camera.Size size : list) { - if ((float) size.width / size.height >= ratio && size.width > minPreviewCandidateWidth) { - validSizeList.add(size); - } - } - - // 没有符合条件的,直接返回第一个吧 - if (validSizeList.size() == 0) { - UiLog.info("no valid preview size"); - return list.get(0); - } - - Camera.Size size = (Camera.Size) Collections.min(validSizeList, new Comparator() { - @Override - public int compare(Camera.Size s1, Camera.Size s2) { - return s1.width - s2.width; - } - }); - - return (Camera.Size) validSizeList.get(1); - // return size; - } - - - public Camera open(boolean isOpenBack) { - int numberOfCameras = getNumberOfCameras(); - UiLog.info("cameraNumber is " + numberOfCameras); - Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); - for (int i = 0; i < numberOfCameras; i++) { - getCameraInfo(i, cameraInfo); - if (isOpenBack) { - if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { - caculatePreviewRotation(cameraInfo); - return Camera.open(i); - } - } else { - if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { - caculatePreviewRotation(cameraInfo); - return Camera.open(i); - } - } - - } - // 兼容只有前置摄像头的开发板 - return Camera.open(0); - } - - public void setDisplayRotation(int degree) { - displayRotation = degree; - } - - private void caculatePreviewRotation(Camera.CameraInfo info) { - int degree; - if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { - degree = (info.orientation + displayRotation) % 360; - degree = (360 - degree) % 360; // compensate the mirror - previewCaptureRotation = (360 - degree) % 360; - } else { // back-facing - degree = (info.orientation - displayRotation + 360) % 360; - previewCaptureRotation = (360 + degree) % 360; - } - - previewRotation = degree; - } - - @Override - public void startPreview() { - // MIUI上会在activity stop时destory关闭相机,触发textureview的destory方法 - if (hasDestoryUnexcepted) { - openCamera(); - } - // 如果已经TextureAvailable,设置texture并且预览,(必须先调用了openCamera) - if (textureStatus == TEXTURE_STATUS_READY) { - try { - mCamera.setPreviewTexture(mSurfaceTexture); - } catch (IOException e) { - e.printStackTrace(); - } - - mCamera.startPreview(); - mCamera.setPreviewCallback(mPreviewCallback); - status = STATUS_PREVIEWING; - return; - } - } - - public void resumePreview() { - mCamera.startPreview(); - } - - private byte[] currentFrameData; - - private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() { - @Override - public void onPreviewFrame(byte[] data, Camera camera) { - // 在某些机型和某项项目中,某些帧的data的数据不符合nv21的格式,需要过滤,否则后续处理会导致crash - if (data.length != cameraParameters.getPreviewSize().width - * cameraParameters.getPreviewSize().height * 1.5) { - return; - } - currentFrameData = data; - } - }; - - public void openCamera() { - mCamera = open(isBack); - cameraParameters = mCamera.getParameters(); - Camera.Size previewSize = cameraParameters.getPreviewSize(); - List supportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); - Camera.Size size = getPreviewSize(supportedPreviewSizes); - if (previewRotation == 90 || previewRotation == 270) { - this.previewSize[0] = size.height; - this.previewSize[1] = size.width; - } else { - this.previewSize[0] = size.width; - this.previewSize[1] = size.height; - } - previewSize.height = size.height; - if (isBack && cameraParameters.getSupportedFocusModes().contains( - Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { - cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); - } - cameraParameters.setPreviewSize(size.width, size.height); - mCamera.setDisplayOrientation(previewRotation); - mCamera.setParameters(cameraParameters); - status = STATUS_OPENED; - if (mCameraListener != null) { - mCameraListener.onSwitchCamera(); - } - } - - public void closeCamera() { - stopPreview(); - mCamera.setPreviewCallback(null); - mCamera.release(); - mCamera = null; - status = STATUS_INIT; - } - - @Override - public void stopPreview() { - - mCamera.stopPreview(); - mCamera.setPreviewCallback(null); - status = STATUS_OPENED; - Log.e("literrr", "stoped"); - } - - @Override - public void switchSide() { - isBack = !isBack; - stopPreview(); - closeCamera(); - openCamera(); - startPreview(); - } - - private Bitmap convertPreviewDataToBitmap(byte[] data) { - Camera.Size size = cameraParameters.getPreviewSize(); - YuvImage img = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null); - ByteArrayOutputStream os = null; - os = new ByteArrayOutputStream(data.length); - img.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, os); - byte[] jpeg = os.toByteArray(); - Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length); - Bitmap bitmapRotate; - if (isBack) { - bitmapRotate = ImageUtil.createRotateBitmap(bitmap, previewCaptureRotation); - } else { - bitmapRotate = ImageUtil.createMirrorRotateBitmap(bitmap, previewCaptureRotation); - } - try { - os.close(); - } catch (IOException e) { - UiLog.info("convertPreviewDataToBitmap close bitmap"); - } - return bitmapRotate; - } - - @Override - public void takePicture(CameraListener.TakePictureListener listener) { - if (currentFrameData != null) { - Bitmap bitmap = convertPreviewDataToBitmap(currentFrameData); - listener.onTakenPicture(bitmap); - UiLog.info("convert bitmap success"); - } - } - - @Override - public void setEventListener(CameraListener.CommonListener listener) { - mCameraListener = listener; - } - - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - mSurfaceTexture = surface; - textureStatus = TEXTURE_STATUS_READY; - mCameraListener.onSurfaceReady(); - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - hasDestoryUnexcepted = true; - return false; - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java deleted file mode 100644 index 9e656d4eaf..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/camera/ICameraProxy.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.camera; - -import android.view.TextureView; - - -/** - * Created by ruanshimin on 2017/3/29. - */ -public interface ICameraProxy extends TextureView.SurfaceTextureListener { - void openCamera(); - - void setDisplayRotation(int degree); - - void startPreview(); - - void stopPreview(); - - void closeCamera(); - - void switchSide(); - - int[] getPreviewSize(); - - void takePicture(CameraListener.TakePictureListener listener); - - void setEventListener(CameraListener.CommonListener commonListener); -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java deleted file mode 100644 index 1d11b5a3cd..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/layout/OperationFrameLayout.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.layout; - -import android.content.Context; -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.widget.RelativeLayout; - -/** - * Created by ruanshimin on 2018/5/3. - */ - -public class OperationFrameLayout extends RelativeLayout { - private int layoutHeight = 360; - - public OperationFrameLayout(@NonNull Context context) { - super(context); - } - - public OperationFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public OperationFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - int width = MeasureSpec.getSize(heightMeasureSpec); - setMeasuredDimension(width, layoutHeight); - setBackgroundColor(Color.BLACK); - } - -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java deleted file mode 100644 index 85a36e9d81..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ImageUtil.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.util; - -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.media.ExifInterface; -import android.util.Log; - -/** - * Created by ruanshimin on 2018/5/8. - */ - -public class ImageUtil { - private static final String TAG = "CameraExif"; - - public static Bitmap createRotateBitmap(Bitmap bitmap, int rotation) { - Matrix matrix = new Matrix(); - matrix.postRotate(rotation); - return Bitmap.createBitmap( - bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); - } - - public static Bitmap createMirrorRotateBitmap(Bitmap bitmap, int rotation) { - Matrix matrix = new Matrix(); - matrix.postRotate(rotation); - matrix.postScale(-1, 1); - return Bitmap.createBitmap( - bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); - } - - public static int exifToDegrees(int exifOrientation) { - if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { - return 90; - } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { - return 180; - } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { - return 270; - } - return 0; - } - - // Returns the degrees in clockwise. Values are 0, 90, 180, or 270. - public static int getOrientation(byte[] jpeg) { - if (jpeg == null) { - return 0; - } - - int offset = 0; - int length = 0; - - // ISO/IEC 10918-1:1993(E) - while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) { - int marker = jpeg[offset] & 0xFF; - - // Check if the marker is a padding. - if (marker == 0xFF) { - continue; - } - offset++; - - // Check if the marker is SOI or TEM. - if (marker == 0xD8 || marker == 0x01) { - continue; - } - // Check if the marker is EOI or SOS. - if (marker == 0xD9 || marker == 0xDA) { - break; - } - - // Get the length and check if it is reasonable. - length = pack(jpeg, offset, 2, false); - if (length < 2 || offset + length > jpeg.length) { - Log.e(TAG, "Invalid length"); - return 0; - } - - // Break if the marker is EXIF in APP1. - if (marker == 0xE1 && length >= 8 - && pack(jpeg, offset + 2, 4, false) == 0x45786966 - && pack(jpeg, offset + 6, 2, false) == 0) { - offset += 8; - length -= 8; - break; - } - - // Skip other markers. - offset += length; - length = 0; - } - - // JEITA CP-3451 Exif Version 2.2 - if (length > 8) { - // Identify the byte order. - int tag = pack(jpeg, offset, 4, false); - if (tag != 0x49492A00 && tag != 0x4D4D002A) { - Log.e(TAG, "Invalid byte order"); - return 0; - } - boolean littleEndian = (tag == 0x49492A00); - - // Get the offset and check if it is reasonable. - int count = pack(jpeg, offset + 4, 4, littleEndian) + 2; - if (count < 10 || count > length) { - Log.e(TAG, "Invalid offset"); - return 0; - } - offset += count; - length -= count; - - // Get the count and go through all the elements. - count = pack(jpeg, offset - 2, 2, littleEndian); - while (count-- > 0 && length >= 12) { - // Get the tag and check if it is orientation. - tag = pack(jpeg, offset, 2, littleEndian); - if (tag == 0x0112) { - // We do not really care about type and count, do we? - int orientation = pack(jpeg, offset + 8, 2, littleEndian); - switch (orientation) { - case 1: - return 0; - case 3: - return 180; - case 6: - return 90; - case 8: - return 270; - default: - return 0; - } - } - offset += 12; - length -= 12; - } - } - - Log.i(TAG, "Orientation not found"); - return 0; - } - - private static int pack(byte[] bytes, int offset, int length, - boolean littleEndian) { - int step = 1; - if (littleEndian) { - offset += length - 1; - step = -1; - } - - int value = 0; - while (length-- > 0) { - value = (value << 8) | (bytes[offset] & 0xFF); - offset += step; - } - return value; - } - -} \ No newline at end of file diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java deleted file mode 100644 index c36e370906..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/StringUtil.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.util; - -import java.text.DecimalFormat; - -/** - * Created by ruanshimin on 2018/5/24. - */ - -public class StringUtil { - public static String formatFloatString(float number) { - DecimalFormat df = new DecimalFormat("0.00"); - return df.format(number); - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java deleted file mode 100644 index 00772e74fb..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/ThreadPoolManager.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2017 Baidu, Inc. All Rights Reserved. - */ -package com.baidu.paddle.fastdeploy.app.ui.util; - -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class ThreadPoolManager { - - static Timer timerFocus = null; - - /* - * 对焦频率 - */ - static final long cameraScanInterval = 2000; - - /* - * 线程池大小 - */ - private static int poolCount = Runtime.getRuntime().availableProcessors(); - - private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(poolCount); - - private static ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); - - /** - * 给线程池添加任务 - * - * @param runnable 任务 - */ - public static void execute(Runnable runnable) { - fixedThreadPool.execute(runnable); - } - - /** - * 单独线程任务 - * - * @param runnable 任务 - */ - public static void executeSingle(Runnable runnable) { - singleThreadPool.execute(runnable); - } - - /** - * 创建一个定时对焦的timer任务 - * - * @param runnable 对焦代码 - * @return Timer Timer对象,用来终止自动对焦 - */ - public static Timer createAutoFocusTimerTask(final Runnable runnable) { - if (timerFocus != null) { - return timerFocus; - } - timerFocus = new Timer(); - TimerTask task = new TimerTask() { - @Override - public void run() { - runnable.run(); - } - }; - timerFocus.scheduleAtFixedRate(task, 0, cameraScanInterval); - return timerFocus; - } - - /** - * 终止自动对焦任务,实际调用了cancel方法并且清空对象 - * 但是无法终止执行中的任务,需额外处理 - */ - public static void cancelAutoFocusTimer() { - if (timerFocus != null) { - timerFocus.cancel(); - timerFocus = null; - } - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java deleted file mode 100644 index ebf6c41115..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/util/UiLog.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.util; - -import android.util.Log; - -/** - * Created by ruanshimin on 2018/5/4. - */ - -public class UiLog { - private static final String TAG = "edge_log"; - - public static void info(String log) { - Log.i(TAG, log); - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/AppCompatPreferenceActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/AppCompatPreferenceActivity.java similarity index 98% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/AppCompatPreferenceActivity.java rename to java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/AppCompatPreferenceActivity.java index 8195c52fa8..c1a952dcff 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/AppCompatPreferenceActivity.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/AppCompatPreferenceActivity.java @@ -1,4 +1,4 @@ -package com.baidu.paddle.fastdeploy.app.ui; +package com.baidu.paddle.fastdeploy.app.ui.view; import android.content.res.Configuration; import android.os.Bundle; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/CameraSurfaceView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java similarity index 99% rename from java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/CameraSurfaceView.java rename to java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java index ba26dbebee..06248fede4 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/CameraSurfaceView.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/CameraSurfaceView.java @@ -1,4 +1,4 @@ -package com.baidu.paddle.fastdeploy.app.ui; +package com.baidu.paddle.fastdeploy.app.ui.view; import android.content.Context; import android.graphics.Bitmap; @@ -15,7 +15,7 @@ import android.util.AttributeSet; import android.util.Log; -import com.baidu.paddle.fastdeploy.app.ui.view.Utils; +import com.baidu.paddle.fastdeploy.app.ui.Utils; import java.io.IOException; import java.nio.ByteBuffer; diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java deleted file mode 100644 index eefca92140..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewDecoratorView.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.view; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Point; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.view.View; - -import com.baidu.paddle.fastdeploy.app.examples.R; - - -/** - * Created by ruanshimin on 2018/5/7. - */ - -public class PreviewDecoratorView extends View { - - static final String RUNNING_HINT_TEXT = "对准识别物体,自动识别物体"; - - static final String STOP_HINT_TEXT = "已暂定实时识别,请点击下方按钮开启"; - - private String hintText = STOP_HINT_TEXT; - - public PreviewDecoratorView(Context context) { - super(context); - } - - public PreviewDecoratorView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public PreviewDecoratorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } - - public void setStatus(boolean isRunning) { - if (isRunning) { - hintText = RUNNING_HINT_TEXT; - } else { - hintText = STOP_HINT_TEXT; - } - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - int offset = 50; - int offsetBottom = 170; - int stokeWidth = 15; - int extendOffset = stokeWidth / 2; - int height = getHeight(); - int width = getWidth(); - int barSize = 40; - - - canvas.save(); - - Paint paintBar = new Paint(); - paintBar.setColor(Color.WHITE); - paintBar.setStrokeWidth(stokeWidth); - paintBar.setStyle(Paint.Style.STROKE); - - - Point leftTop = new Point(offset, offset); - Point rightTop = new Point(width - offset, offset); - Point leftBottom = new Point(offset, height - offsetBottom); - Point rightBottom = new Point(width - offset, height - offsetBottom); - - - Path path = new Path(); - path.moveTo(leftTop.x, leftTop.y + barSize); - path.lineTo(leftTop.x, leftTop.y); - path.lineTo(leftTop.x + barSize, leftTop.y); - - path.moveTo(rightTop.x - barSize, leftTop.y); - path.lineTo(rightTop.x, rightTop.y); - path.lineTo(rightTop.x, rightTop.y + barSize); - - path.moveTo(leftBottom.x, leftBottom.y - barSize); - path.lineTo(leftBottom.x, leftBottom.y); - path.lineTo(leftBottom.x + barSize, leftBottom.y); - - path.moveTo(rightBottom.x - barSize, rightBottom.y); - path.lineTo(rightBottom.x, rightBottom.y); - path.lineTo(rightBottom.x, rightBottom.y - barSize); - - - // 绘制半透明遮罩 - Rect rect = new Rect(0, 0, width, height); - Paint paint = new Paint(); - paint.setColor(Color.BLACK); - paint.setAlpha(50); - canvas.drawRect(rect, paint); - - // 擦除可见部分半透明遮罩 - rect = new Rect(leftTop.x - extendOffset, leftTop.y - extendOffset, - rightBottom.x + extendOffset, rightBottom.y + extendOffset); - canvas.clipRect(rect); - canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - - // 绘制四个小角 - canvas.drawPath(path, paintBar); - canvas.restore(); - // 设置留给hint的位置 - rect = new Rect(0, rightBottom.y + extendOffset, width, height); - - drawHint(canvas, rect, hintText); - - super.onDraw(canvas); - } - - public void drawHint(Canvas canvas, Rect rect, String text) { - int textSizePx = 16; - int imageSizePx = 48; - int padInTextAndIcon = 22; - Paint textPaint = new Paint(); - textPaint.setTextSize(textSizePx); - textPaint.setColor(Color.WHITE); - textPaint.setTextAlign(Paint.Align.LEFT); - - Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.scan_icon); - - float textWidth = getTextWidth(this.getContext(), text, textPaint, textSizePx); - int width = padInTextAndIcon + imageSizePx + (int) textWidth; - int height = imageSizePx; - - int startX = rect.left + (rect.width() - width) / 2; - int startY = rect.top + (rect.height() - height) / 2; - - Rect srcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); - Rect destRect = new Rect(startX, startY, startX + imageSizePx, startY + imageSizePx); - - Paint mBitPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBitPaint.setFilterBitmap(true); - mBitPaint.setDither(true); - canvas.drawBitmap(bitmap, srcRect, destRect, mBitPaint); - - startX += padInTextAndIcon + imageSizePx; - - canvas.drawText(text, startX, startY + textSizePx + 23, textPaint); - } - - public float getTextWidth(Context context, String text, Paint paint, int textSize) { - float scaledDensity = getResources().getDisplayMetrics().scaledDensity; - paint.setTextSize(scaledDensity * textSize); - return paint.measureText(text); - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java deleted file mode 100644 index 0d01c7cf1f..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/PreviewView.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.view; - -import android.app.Activity; -import android.content.Context; -import android.graphics.Bitmap; -import android.util.AttributeSet; -import android.view.Surface; -import android.view.TextureView; - -import com.baidu.paddle.fastdeploy.app.ui.camera.CameraListener; -import com.baidu.paddle.fastdeploy.app.ui.camera.CameraProxy1; -import com.baidu.paddle.fastdeploy.app.ui.camera.ICameraProxy; - -/** - * Created by ruanshimin on 2018/5/3. - */ - -public class PreviewView extends TextureView { - ICameraProxy mCameraProxy; - private int layoutWidth; - private int layoutHeight; - private int actualHeight; - private int cropHeight; - - public PreviewView(Context context) { - super(context); - } - - public PreviewView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public PreviewView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - /** - * 手动调用开始预览 - */ - public void start() { - if (mCameraProxy != null) { - mCameraProxy.startPreview(); - } - } - - /** - * 释放摄像头 - */ - public void destory() { - if (mCameraProxy != null) { - mCameraProxy.closeCamera(); - } - } - - /** - * 手动停止 - */ - public void stopPreview() { - mCameraProxy.stopPreview(); - } - - /** - * 设置实际可见layout的长宽 - */ - public void setLayoutSize(int width, int height) { - layoutWidth = width; - layoutHeight = height; - } - - public void takePicture(final CameraListener.TakePictureListener listener) { - // 裁剪图片 - mCameraProxy.takePicture(new CameraListener.TakePictureListener() { - @Override - public void onTakenPicture(Bitmap bitmap) { - Bitmap cropBitmap = Bitmap.createBitmap(bitmap, 0, 0, - bitmap.getWidth(), cropHeight); - listener.onTakenPicture(cropBitmap); - } - }); - } - - /** - * 切换摄像头面 - */ - public void switchSide() { - mCameraProxy.switchSide(); - } - - public int getActualHeight() { - return actualHeight; - } - - private void setDisplayDegree() { - int rotation = ((Activity) this.getContext()).getWindowManager().getDefaultDisplay() - .getRotation(); - int degrees = 0; - switch (rotation) { - case Surface.ROTATION_0: - degrees = 0; - break; - case Surface.ROTATION_90: - degrees = 90; - break; - case Surface.ROTATION_180: - degrees = 180; - break; - case Surface.ROTATION_270: - degrees = 270; - break; - default: - degrees = 0; - } - mCameraProxy.setDisplayRotation(degrees); - } - - private void refreshCropHeight() { - int[] size = mCameraProxy.getPreviewSize(); - actualHeight = (int) (((float) size[1] / size[0]) * layoutWidth); - cropHeight = (int) (((float) layoutHeight / layoutWidth) * size[0]); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mCameraProxy == null) { - mCameraProxy = new CameraProxy1(layoutWidth, layoutHeight); - setDisplayDegree(); - setSurfaceTextureListener(mCameraProxy); - mCameraProxy.openCamera(); - refreshCropHeight(); - mCameraProxy.setEventListener(new CameraListener.CommonListener() { - @Override - public void onSurfaceReady() { - mCameraProxy.startPreview(); - } - - @Override - public void onSwitchCamera() { - refreshCropHeight(); - } - }); - } - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java deleted file mode 100644 index 13e3241ee6..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/ResultMaskView.java +++ /dev/null @@ -1,381 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.view; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Handler; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.view.View; - -import com.baidu.paddle.fastdeploy.app.ui.util.StringUtil; -import com.baidu.paddle.fastdeploy.app.ui.view.model.BasePolygonResultModel; -import com.baidu.paddle.fastdeploy.app.ui.view.model.PoseViewResultModel; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -/** - * Created by ruanshimin on 2018/5/15. - */ - -public class ResultMaskView extends View { - private static final int[][] COLOR_MAP_DEF = { - {0, 0, 0}, - {244, 35, 232}, - {70, 70, 70}, - {102, 102, 156}, - {190, 153, 153}, - {153, 153, 153}, - {250, 170, 30}, - {220, 220, 0}, - {107, 142, 35}, - {152, 251, 152}, - {70, 130, 180}, - {220, 20, 60}, - {255, 0, 0}, - {0, 0, 142}, - {0, 0, 70}, - {0, 60, 100}, - {0, 80, 100}, - {0, 0, 230}, - {119, 11, 32}, - {128, 64, 128} - }; - - private float sizeRatio; - private List mResultModelList; - private Point originPt = new Point(); - private int imgWidth; - private int imgHeight; - private Paint textPaint; - - private Handler handler; - - public void setHandler(Handler mHandler) { - handler = mHandler; - } - - public ResultMaskView(Context context) { - super(context); - } - - private Map paintFixPool = new HashMap<>(); - - public ResultMaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } - - - public void setPolygonListInfo(List modelList, int width, int height) { - imgWidth = width; - imgHeight = height; - mResultModelList = modelList; - handler.post(new Runnable() { - @Override - public void run() { - invalidate(); - } - }); - } - - - public void clear() { - mResultModelList = null; - handler.post(new Runnable() { - @Override - public void run() { - invalidate(); - } - }); - } - - private void preCaculate() { - float ratio = (float) getMeasuredWidth() / (float) getMeasuredHeight(); - float ratioBitmap = (float) imgWidth / (float) imgHeight; - // | |#####| |模式 - if (ratioBitmap < ratio) { - sizeRatio = (float) getMeasuredHeight() / (float) imgHeight; - int x = (int) (getMeasuredWidth() - sizeRatio * imgWidth) / 2; - originPt.set(x, 0); - } else { - // ------------ - // - // ------------ - // ############ - // ------------ - // - // ------------ - sizeRatio = (float) getMeasuredWidth() / (float) imgWidth; - int y = (int) (getMeasuredHeight() - sizeRatio * imgHeight) / 2; - originPt.set(0, y); - } - - } - - private Map paintRandomPool = new HashMap<>(); - - public ResultMaskView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - textPaint = new Paint(); - textPaint.setTextSize(30); - textPaint.setARGB(255, 255, 255, 255); - } - - private Paint getRandomMaskPaint(int index) { - if (paintRandomPool.containsKey(index)) { - - return paintRandomPool.get(index); - } - - int[] seed = new int[3]; - int offset = index % 3; - seed[offset] = 255; - - Paint paint = new Paint(); - Random rnd = new Random(); - paint.setARGB(170, - (rnd.nextInt(255) + seed[0]) / 2, - (rnd.nextInt(255) + seed[1]) / 2, - (rnd.nextInt(255) + seed[2]) / 2); - paint.setStyle(Paint.Style.FILL_AND_STROKE); - - paintRandomPool.put(index, paint); - - return paint; - } - - private Paint getFixColorPaint(int colorId) { - - // float alpha = 90; - String[] colors = {"#FF0000", "#FF0000", "#00FF00", "#0000FF", "#FF00FF"}; - int index = colorId % colors.length; - if (paintFixPool.containsKey(index)) { - return paintFixPool.get(index); - } - - int color = Color.parseColor(colors[index]); - Paint paint = new Paint(); - paint.setColor(color); - //paint.setAlpha(90); - paintFixPool.put(index, paint); - return paint; - } - - @Override - protected void onDraw(Canvas canvas) { - // 实时识别的时候第一次渲染 - if (mResultModelList == null) { - super.onDraw(canvas); - return; - } - - preCaculate(); - - int stokeWidth = 5; - - int fontSize = 38; - int labelPadding = 5; - int labelHeight = 46 + 2 * labelPadding; - Paint paint = new Paint(); - paint.setColor(Color.parseColor("#3B85F5")); - paint.setStrokeWidth(stokeWidth); - paint.setStyle(Paint.Style.STROKE); - - Paint paintFillAlpha = new Paint(); - paintFillAlpha.setStyle(Paint.Style.FILL); - paintFillAlpha.setColor(Color.parseColor("#3B85F5")); - paintFillAlpha.setAlpha(50); - - Paint paintFill = new Paint(); - paintFill.setStyle(Paint.Style.FILL); - paintFill.setColor(Color.parseColor("#3B85F5")); - - Paint paintText = new Paint(); - paintText.setColor(Color.WHITE); - paintText.setTextAlign(Paint.Align.LEFT); - paintText.setTextSize(fontSize); - DecimalFormat df = new DecimalFormat("0.00"); - - - List points; - for (int i = 0; i < mResultModelList.size(); i++) { - - BasePolygonResultModel model = mResultModelList.get(i); - Path path = new Path(); - List polygon = model.getBounds(sizeRatio, originPt); - - path.moveTo(polygon.get(0).x, polygon.get(0).y); - for (int j = 1; j < polygon.size(); j++) { - path.lineTo(polygon.get(j).x, polygon.get(j).y); - } - path.close(); - - if (model.isDrawPoints()) { - Paint paintFillPoint = new Paint(); - paintFillPoint.setStyle(Paint.Style.FILL_AND_STROKE); - - paintFillPoint.setColor(Color.YELLOW); - List polygonPoints = model.getBounds(sizeRatio, originPt); - for (Point p : polygonPoints) { - canvas.drawCircle(p.x, p.y, 10 * sizeRatio, paintFillPoint); - } - - } - - // 绘制框 - if (!model.isHasMask()) { - if (model instanceof PoseViewResultModel && model.isHasGroupColor()) { - paint = getFixColorPaint(model.getColorId()); - paint.setStrokeWidth(stokeWidth); - paint.setStyle(Paint.Style.STROKE); - paint.setAlpha(90); - } - canvas.drawPath(path, paint); - canvas.drawPath(path, paintFillAlpha); - if (model.isRect()) { - Rect rect = model.getRect(sizeRatio, originPt); - canvas.drawRect(new Rect(rect.left, rect.top, rect.right, - rect.top + labelHeight), paintFill); - } - } - if (model.isRect()) { - Rect rect = model.getRect(sizeRatio, originPt); - canvas.drawText(model.getName() + " " + StringUtil.formatFloatString(model.getConfidence()), - rect.left + labelPadding, - rect.top + fontSize + labelPadding, paintText); - } - - if (model.isTextOverlay()) { - canvas.drawText(model.getName(), - polygon.get(0).x, polygon.get(0).y, textPaint); - } - - // 绘制mask - if (model.isHasMask()) { - if (!model.isSemanticMask()) { - // 实例分割绘制 - Paint paintMask = getRandomMaskPaint(model.getColorId()); - points = new ArrayList<>(); - byte[] maskData = model.getMask(); - - for (int w = 0; w < imgWidth * sizeRatio; w++) { - for (int h = 0; h < imgHeight * sizeRatio; h++) { - - int realX = (int) (w / sizeRatio); - int realY = (int) (h / sizeRatio); - - int offset = imgWidth * realY + realX; - if (offset < maskData.length && maskData[offset] == 1) { - points.add(originPt.x + (float) w); - points.add(originPt.y + (float) h); - } - } - } - - float[] ptft = new float[points.size()]; - for (int j = 0; j < points.size(); j++) { - ptft[j] = points.get(j); - } - canvas.drawPoints(ptft, paintMask); - } else { - // 语义分割绘制 - drawSemanticMask(canvas, model); - } - } - } - - - super.onDraw(canvas); - } - - /** - * 语义分割基于mask不同值绘制颜色 - */ - private void drawSemanticMask(Canvas canvas, BasePolygonResultModel model) { - List colorPointsPairList = new ArrayList<>(); - for (int[] rgb : COLOR_MAP_DEF) { - Paint paint = new Paint(); - paint.setARGB(170, rgb[0], rgb[1], rgb[2]); - colorPointsPairList.add(new ColorPointsPair(paint)); - } - - byte[] maskData = model.getMask(); - for (int w = 0; w < imgWidth * sizeRatio; w++) { - for (int h = 0; h < imgHeight * sizeRatio; h++) { - - int realX = (int) (w / sizeRatio); - int realY = (int) (h / sizeRatio); - - int offset = imgWidth * realY + realX; - byte label = maskData[offset]; - - if (label >= colorPointsPairList.size()) { - for (int i = colorPointsPairList.size(); i <= label; i++ ) { - Paint newPaint = getRandomMaskPaint(i); - colorPointsPairList.add(new ColorPointsPair(newPaint)); - } - } - - colorPointsPairList.get(label).addPoint(originPt.x + (float) w); - colorPointsPairList.get(label).addPoint(originPt.y + (float) h); - } - } - - for (ColorPointsPair pair : colorPointsPairList) { - float[] points = pair.getPointsArray(); - if (points != null) { - canvas.drawPoints(points, pair.getPaint()); - } - } - } - - /** - * 用于分割模型,一个颜色对应一系列点 - */ - private class ColorPointsPair { - private final Paint paint; - private List points; - - public ColorPointsPair(Paint paint) { - this.paint = paint; - } - - public void addPoint(float point) { - if (points == null) { - points = new ArrayList<>(); - } - points.add(point); - } - - public float[] getPointsArray() { - if (points == null || points.size() == 0) { - return null; - } - float[] array = new float[points.size()]; - for (int i = 0; i < points.size(); i++) { - array[i] = points.get(i); - } - return array; - } - - public Paint getPaint() { - return paint; - } - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java index 5f854aed13..3aecc5d4dd 100644 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/adapter/DetectResultAdapter.java @@ -10,9 +10,9 @@ import android.widget.TextView; import com.baidu.paddle.fastdeploy.app.examples.R; -import com.baidu.paddle.fastdeploy.app.ui.util.StringUtil; import com.baidu.paddle.fastdeploy.app.ui.view.model.BaseResultModel; +import java.text.DecimalFormat; import java.util.List; /** @@ -41,7 +41,12 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup TextView confidenceText = (TextView) view.findViewById(R.id.confidence); indexText.setText(String.valueOf(model.getIndex())); nameText.setText(String.valueOf(model.getName())); - confidenceText.setText(StringUtil.formatFloatString(model.getConfidence())); + confidenceText.setText(formatFloatString(model.getConfidence())); return view; } + + public static String formatFloatString(float number) { + DecimalFormat df = new DecimalFormat("0.00"); + return df.format(number); + } } diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java deleted file mode 100644 index 6b967c3b26..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/BasePolygonResultModel.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.view.model; - -import android.graphics.Point; -import android.graphics.Rect; - -import java.util.ArrayList; -import java.util.List; - -public class BasePolygonResultModel extends BaseResultModel { - private int colorId; - private boolean isRect; - private boolean isTextOverlay; - - private boolean isHasGroupColor = false; - private boolean isDrawPoints = false; - - - public boolean isTextOverlay() { - return isTextOverlay; - } - - public void setTextOverlay(boolean textOverlay) { - isTextOverlay = textOverlay; - } - - public int getColorId() { - return colorId; - } - - public void setColorId(int colorId) { - this.colorId = colorId; - } - - private byte[] mask; - - /** - * 是否是语义分割mask - */ - private boolean semanticMask; - - private Rect rect; - - BasePolygonResultModel() { - super(); - } - - BasePolygonResultModel(int index, String name, float confidence, Rect bounds) { - super(index, name, confidence); - parseFromRect(bounds); - } - - BasePolygonResultModel(int index, String name, float confidence, List bounds) { - super(index, name, confidence); - this.bounds = bounds; - } - - public Rect getRect() { - return rect; - } - - public Rect getRect(float ratio, Point origin) { - return new Rect((int) (origin.x + rect.left * ratio), - (int) (origin.y + rect.top * ratio), - (int) (origin.x + rect.right * ratio), - (int) (origin.y + rect.bottom * ratio)); - } - - private void parseFromRect(Rect rect) { - Point ptTL = new Point(rect.left, rect.top); - Point ptTR = new Point(rect.right, rect.top); - Point ptRB = new Point(rect.right, rect.bottom); - Point ptLB = new Point(rect.left, rect.bottom); - this.bounds = new ArrayList<>(); - this.bounds.add(ptTL); - this.bounds.add(ptTR); - this.bounds.add(ptRB); - this.bounds.add(ptLB); - this.rect = rect; - isRect = true; - } - - public boolean isRect() { - return isRect; - } - - public void setRect(boolean rect) { - isRect = rect; - } - - public byte[] getMask() { - return mask; - } - - public void setMask(byte[] mask) { - this.mask = mask; - } - - public void setSemanticMask(boolean semanticMask) { - this.semanticMask = semanticMask; - } - - public boolean isSemanticMask() { - return semanticMask; - } - - private List bounds; - - public List getBounds() { - return bounds; - } - - public List getBounds(float ratio, Point origin) { - List pointList = new ArrayList<>(); - for (Point pt : bounds) { - int nx = (int) (origin.x + pt.x * ratio); - int ny = (int) (origin.y + pt.y * ratio); - pointList.add(new Point(nx, ny)); - } - return pointList; - } - - public void setBounds(List bounds) { - this.bounds = bounds; - } - - public void setBounds(Rect bounds) { - parseFromRect(bounds); - } - - public boolean isHasMask() { - return (mask != null); - } - - public boolean isHasGroupColor() { - return isHasGroupColor; - } - - public void setHasGroupColor(boolean hasGroupColor) { - isHasGroupColor = hasGroupColor; - } - - public boolean isDrawPoints() { - return isDrawPoints; - } - - public void setDrawPoints(boolean drawPoints) { - isDrawPoints = drawPoints; - } -} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java deleted file mode 100644 index 3652903e3f..0000000000 --- a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/ui/view/model/PoseViewResultModel.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baidu.paddle.fastdeploy.app.ui.view.model; - -public class PoseViewResultModel extends BasePolygonResultModel { - public PoseViewResultModel() { - super(); - setRect(false); - setTextOverlay(false); - setDrawPoints(true); - } - -} diff --git a/java/android/app/src/main/res/layout-land/activity_main.xml b/java/android/app/src/main/res/layout-land/default_activity_main.xml similarity index 98% rename from java/android/app/src/main/res/layout-land/activity_main.xml rename to java/android/app/src/main/res/layout-land/default_activity_main.xml index d6e88a09a2..4cae72e1d9 100644 --- a/java/android/app/src/main/res/layout-land/activity_main.xml +++ b/java/android/app/src/main/res/layout-land/default_activity_main.xml @@ -12,7 +12,7 @@ android:layout_height="match_parent" android:background="@color/colorWindow"> - diff --git a/java/android/app/src/main/res/layout/camera_page.xml b/java/android/app/src/main/res/layout/default_camera_page.xml similarity index 98% rename from java/android/app/src/main/res/layout/camera_page.xml rename to java/android/app/src/main/res/layout/default_camera_page.xml index b89cf725ce..098c50d9d2 100644 --- a/java/android/app/src/main/res/layout/camera_page.xml +++ b/java/android/app/src/main/res/layout/default_camera_page.xml @@ -54,8 +54,8 @@ - - + - - - - - - - - - - - - - . - - \ No newline at end of file diff --git a/java/android/app/src/main/res/xml/settings.xml b/java/android/app/src/main/res/xml/default_settings.xml similarity index 100% rename from java/android/app/src/main/res/xml/settings.xml rename to java/android/app/src/main/res/xml/default_settings.xml