Skip to content

Commit

Permalink
[Android] Run button shutter in sub Ui Thread (#598)
Browse files Browse the repository at this point in the history
* [Backend] fix lite backend save model error

* [Backend] fixed typos

* [FlyCV] optimize the integration of FlyCV

* [cmake] close some tests options

* [cmake] close some test option

* [FlyCV] remove un-need warnings

* [FlyCV] remove un-need GetMat method

* [FlyCV] optimize FlyCV codes

* [cmake] remove un-need cmake function in examples/CMakelists

* [cmake] support gflags for Android

* [Android] Run button shutter in sub Ui Thread

* [Android] Update CameraSurfaceView
  • Loading branch information
DefTruth authored Nov 15, 2022
1 parent 37ee101 commit 7084a94
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
import java.util.ArrayList;
import java.util.List;

import javax.microedition.khronos.opengles.GL10;

public class DetectionMainActivity extends Activity implements View.OnClickListener, CameraSurfaceView.OnTextureChangedListener {
private static final String TAG = DetectionMainActivity.class.getSimpleName();

Expand Down Expand Up @@ -75,10 +77,12 @@ public class DetectionMainActivity extends Activity implements View.OnClickListe
public static final int TYPE_UNKNOWN = -1;
public static final int BTN_SHUTTER = 0;
public static final int ALBUM_SELECT = 1;
private static int TYPE = TYPE_UNKNOWN;
public static final int REALTIME_DETECT = 2;
private static int TYPE = REALTIME_DETECT;

private static final int REQUEST_PERMISSION_CODE_STORAGE = 101;
private static final int INTENT_CODE_PICK_IMAGE = 100;
private static final int TIME_SLEEP_INTERVAL = 50; // ms

String savedImagePath = "result.jpg";
int lastFrameIndex = 0;
Expand Down Expand Up @@ -118,12 +122,7 @@ public void onClick(View v) {
break;
case R.id.btn_shutter:
TYPE = BTN_SHUTTER;
svPreview.onPause();
cameraPageView.setVisibility(View.GONE);
resultPageView.setVisibility(View.VISIBLE);
seekbarText.setText(resultNum + "");
confidenceSeekbar.setProgress((int) (resultNum * 100));
resultImage.setImageBitmap(shutterBitmap);
runOnShutterUiThread();
break;
case R.id.btn_settings:
startActivity(new Intent(DetectionMainActivity.this, DetectionSettingsActivity.class));
Expand All @@ -149,9 +148,49 @@ public void onClick(View v) {
case R.id.back_in_result:
resultPageView.setVisibility(View.GONE);
cameraPageView.setVisibility(View.VISIBLE);
TYPE = REALTIME_DETECT;
svPreview.onResume();
break;
}
}

private void runOnShutterUiThread() {
runOnUiThread(new Runnable() {
@SuppressLint("SetTextI18n")
public void run() {
try {
Thread.sleep(TIME_SLEEP_INTERVAL);

svPreview.onPause();
cameraPageView.setVisibility(View.GONE);
resultPageView.setVisibility(View.VISIBLE);
seekbarText.setText(resultNum + "");
confidenceSeekbar.setProgress((int) (resultNum * 100));
if (shutterBitmap != null && !shutterBitmap.isRecycled()) {
resultImage.setImageBitmap(shutterBitmap);
} else {
new AlertDialog.Builder(DetectionMainActivity.this)
.setTitle("Empty Result!")
.setMessage("Current picture is empty, please shutting it again!")
.setCancelable(true)
.show();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}

private void copyBitmapFromCamera(Bitmap ARGB8888ImageBitmap) {
if (ARGB8888ImageBitmap == null) {
return;
}
if (!ARGB8888ImageBitmap.isRecycled()) {
synchronized (this) {
shutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888, true);
originShutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888, true);
}
}
}

Expand Down Expand Up @@ -194,18 +233,17 @@ public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) {

@Override
public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) {
synchronized (this) {
if (TYPE == BTN_SHUTTER) {
copyBitmapFromCamera(ARGB8888ImageBitmap);
return false;
}
}

String savedImagePath = "";
synchronized (this) {
savedImagePath = Utils.getDCIMDirectory() + File.separator + "result.jpg";
}
if (TYPE == BTN_SHUTTER) {
shutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888, true);
originShutterBitmap = ARGB8888ImageBitmap.copy(Bitmap.Config.ARGB_8888, true);
} else {
// Only reference in predict loops.
shutterBitmap = ARGB8888ImageBitmap;
originShutterBitmap = ARGB8888ImageBitmap;
}

boolean modified = false;
DetectionResult result = predictor.predict(
Expand Down Expand Up @@ -258,7 +296,7 @@ protected void onDestroy() {
}

public void initView() {
TYPE = BTN_SHUTTER;
TYPE = REALTIME_DETECT;
svPreview = (CameraSurfaceView) findViewById(R.id.sv_preview);
svPreview.setOnTextureChangedListener(this);
tvStatus = (TextView) findViewById(R.id.tv_status);
Expand Down Expand Up @@ -313,16 +351,20 @@ public void onStopTrackingTouch(SeekBar seekBar) {
@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);
SystemClock.sleep(TIME_SLEEP_INTERVAL * 10);
if (!picBitmap.isRecycled()) {
predictor.predict(picBitmap, true, 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);
SystemClock.sleep(TIME_SLEEP_INTERVAL * 10);
if (!shutterBitmap.isRecycled()) {
predictor.predict(shutterBitmap, true, resultNum);
resultImage.setImageBitmap(shutterBitmap);
shutterBitmap = originShutterBitmap.copy(Bitmap.Config.ARGB_8888, true);
}
resultNum = 1.0f;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public class CameraSurfaceView extends GLSurfaceView implements Renderer,
protected int textureWidth = 0;
protected int textureHeight = 0;

protected Bitmap ARGB8888ImageBitmap;
protected boolean bitmapReleaseMode = true;

// In order to manipulate the camera preview data and render the modified one
// to the screen, three textures are created and the data flow is shown as following:
// previewdata->camTextureId->fboTexureId->drawTexureId->framebuffer
Expand Down Expand Up @@ -198,9 +201,12 @@ public void onDrawFrame(GL10 gl) {
// Read pixels of FBO to a bitmap
ByteBuffer pixelBuffer = ByteBuffer.allocate(textureWidth * textureHeight * 4);
GLES20.glReadPixels(0, 0, textureWidth, textureHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBuffer);
Bitmap ARGB8888ImageBitmap = Bitmap.createBitmap(textureWidth, textureHeight, Bitmap.Config.ARGB_8888);

ARGB8888ImageBitmap = Bitmap.createBitmap(textureWidth, textureHeight, Bitmap.Config.ARGB_8888);
ARGB8888ImageBitmap.copyPixelsFromBuffer(pixelBuffer);

boolean modified = onTextureChangedListener.onTextureChanged(ARGB8888ImageBitmap);

if (modified) {
targetTexureId = drawTexureId[0];
// Update a bitmap to the GL texture if modified
Expand All @@ -209,7 +215,9 @@ public void onDrawFrame(GL10 gl) {
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, targetTexureId);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, ARGB8888ImageBitmap, 0);
}
ARGB8888ImageBitmap.recycle();
if (bitmapReleaseMode) {
ARGB8888ImageBitmap.recycle();
}
}

// fboTexureId/drawTexureId->Screen
Expand All @@ -229,6 +237,16 @@ public void onDrawFrame(GL10 gl) {
GLES20.glFlush();
}

public void setBitmapReleaseMode(boolean mode) {
synchronized (this) {
bitmapReleaseMode = mode;
}
}

public Bitmap getBitmap() {
return ARGB8888ImageBitmap; // may null or recycled.
}

private float[] transformTextureCoordinates(float[] coords, float[] matrix) {
float[] result = new float[coords.length];
float[] vt = new float[4];
Expand Down
2 changes: 1 addition & 1 deletion java/android/app/src/main/res/xml/ocr_settings.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:defaultValue="@string/MODEL_DIR_DEFAULT"
android:defaultValue="@string/OCR_MODEL_DIR_DEFAULT"
android:key="@string/CHOOSE_PRE_INSTALLED_MODEL_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
Expand Down

0 comments on commit 7084a94

Please sign in to comment.