[Android] Support PP-OCRv2 & PP-OCRv3 in Android (#445)

* [Android] Add Android build docs and demo (#26)

* [Backend] Add override flag to lite backend

* [Docs] Add Android C++ SDK build docs

* [Doc] fix android_build_docs typos

* Update CMakeLists.txt

* Update android.md

* [Doc] Add PicoDet Android demo docs

* [Doc] Update PicoDet Andorid demo docs

* [Doc] Update PaddleClasModel Android demo docs

* [Doc] Update fastdeploy android jni docs

* [Doc] Update fastdeploy android jni usage docs

* [Android] init fastdeploy android jar package

* [Backend] support int8 option for lite backend

* [Model] add Backend::Lite to paddle model

* [Backend] use CopyFromCpu for lite backend.

* [Android] package jni srcs and java api into aar

* Update infer.cc

* Update infer.cc

* [Android] Update package build.gradle

* [Android] Update android app examples

* [Android] update android detection app

* [Android] Support PP-OCRv2 & PP-OCRv3 in Android

* [Android] bind ORCResult with JNI

* [Android] move static class jni method to instance method

* [Android] bind VisOcr and VisClassification via JNI

* [Android] Add PP-OCRv2 & v3 android demo
This commit is contained in:
DefTruth
2022-10-28 10:56:47 +08:00
committed by GitHub
parent 3c208125b8
commit 04704c8411
32 changed files with 8706 additions and 78 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.baidu.paddle.fastdeploy.app.examples.detection">
package="com.baidu.paddle.fastdeploy.app.examples">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
@@ -11,18 +11,18 @@
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:label="@string/ocr_app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.baidu.paddle.fastdeploy.app.examples.detection.MainActivity">
<activity android:name="com.baidu.paddle.fastdeploy.app.examples.ocr.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="com.baidu.paddle.fastdeploy.app.examples.detection.SettingsActivity"
android:name="com.baidu.paddle.fastdeploy.app.examples.ocr.SettingsActivity"
android:label="Settings">
</activity>
</application>

View File

@@ -0,0 +1,94 @@
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.baidu.paddle.fastdeploy.RuntimeOption;
import com.baidu.paddle.fastdeploy.app.examples.detection.R;
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.vision.DetectionResult;

View File

@@ -9,7 +9,7 @@ import android.preference.ListPreference;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBar;
import com.baidu.paddle.fastdeploy.app.examples.detection.R;
import com.baidu.paddle.fastdeploy.app.examples.R;
import com.baidu.paddle.fastdeploy.app.ui.AppCompatPreferenceActivity;
import com.baidu.paddle.fastdeploy.app.ui.Utils;
@@ -46,7 +46,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity implements
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
// addPreferencesFromResource(R.xml.settings);
addPreferencesFromResource(R.xml.detection_settings);
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setDisplayHomeAsUpEnabled(true);

View File

@@ -0,0 +1,289 @@
package com.baidu.paddle.fastdeploy.app.examples.ocr;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
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.vision.OCRResult;
import com.baidu.paddle.fastdeploy.pipeline.PPOCRv2;
import com.baidu.paddle.fastdeploy.vision.ocr.Classifier;
import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector;
import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends Activity implements View.OnClickListener, CameraSurfaceView.OnTextureChangedListener {
private static final String TAG = MainActivity.class.getSimpleName();
CameraSurfaceView svPreview;
TextView tvStatus;
ImageButton btnSwitch;
ImageButton btnShutter;
ImageButton btnSettings;
ImageView realtimeToggleButton;
boolean isRealtimeStatusRunning = false;
ImageView backInPreview;
String savedImagePath = "result.jpg";
int lastFrameIndex = 0;
long lastFrameTime;
// Call 'init' and 'release' manually later
PPOCRv2 predictor = new PPOCRv2();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Fullscreen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
// Clear all setting items to avoid app crashing due to the incorrect settings
initSettings();
// Init the camera preview and UI components
initView();
// Check and request CAMERA and WRITE_EXTERNAL_STORAGE permissions
if (!checkAllPermissions()) {
requestAllPermissions();
}
}
@SuppressLint("NonConstantResourceId")
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_switch:
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();
break;
case R.id.btn_settings:
startActivity(new Intent(MainActivity.this, SettingsActivity.class));
break;
case R.id.realtime_toggle_btn:
toggleRealtimeStyle();
break;
case R.id.back_in_preview:
finish();
break;
}
}
private void toggleRealtimeStyle() {
if (isRealtimeStatusRunning) {
isRealtimeStatusRunning = false;
realtimeToggleButton.setImageResource(R.drawable.realtime_stop_btn);
svPreview.setOnTextureChangedListener(this);
tvStatus.setVisibility(View.VISIBLE);
} else {
isRealtimeStatusRunning = true;
realtimeToggleButton.setImageResource(R.drawable.realtime_start_btn);
tvStatus.setVisibility(View.GONE);
svPreview.setOnTextureChangedListener(new CameraSurfaceView.OnTextureChangedListener() {
@Override
public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) {
return false;
}
});
}
}
@Override
public boolean onTextureChanged(Bitmap ARGB8888ImageBitmap) {
String savedImagePath = "";
synchronized (this) {
savedImagePath = MainActivity.this.savedImagePath;
}
boolean modified = false;
OCRResult result = predictor.predict(ARGB8888ImageBitmap, savedImagePath);
modified = result.initialized();
if (!savedImagePath.isEmpty()) {
synchronized (this) {
MainActivity.this.savedImagePath = "result.jpg";
}
}
lastFrameIndex++;
if (lastFrameIndex >= 30) {
final int fps = (int) (lastFrameIndex * 1e9 / (System.nanoTime() - lastFrameTime));
runOnUiThread(new Runnable() {
@SuppressLint("SetTextI18n")
public void run() {
tvStatus.setText(Integer.toString(fps) + "fps");
}
});
lastFrameIndex = 0;
lastFrameTime = System.nanoTime();
}
return modified;
}
@Override
protected void onResume() {
super.onResume();
// Reload settings and re-initialize the predictor
checkAndUpdateSettings();
// Open camera until the permissions have been granted
if (!checkAllPermissions()) {
svPreview.disableCamera();
}
svPreview.onResume();
}
@Override
protected void onPause() {
super.onPause();
svPreview.onPause();
}
@Override
protected void onDestroy() {
if (predictor != null) {
predictor.release();
}
super.onDestroy();
}
public void initView() {
svPreview = (CameraSurfaceView) findViewById(R.id.sv_preview);
svPreview.setOnTextureChangedListener(this);
tvStatus = (TextView) findViewById(R.id.tv_status);
btnSwitch = (ImageButton) findViewById(R.id.btn_switch);
btnSwitch.setOnClickListener(this);
btnShutter = (ImageButton) findViewById(R.id.btn_shutter);
btnShutter.setOnClickListener(this);
btnSettings = (ImageButton) findViewById(R.id.btn_settings);
btnSettings.setOnClickListener(this);
realtimeToggleButton = findViewById(R.id.realtime_toggle_btn);
realtimeToggleButton.setOnClickListener(this);
backInPreview = findViewById(R.id.back_in_preview);
backInPreview.setOnClickListener(this);
}
@SuppressLint("ApplySharedPref")
public void initSettings() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.clear();
editor.commit();
SettingsActivity.resetSettings();
}
public void checkAndUpdateSettings() {
if (SettingsActivity.checkAndUpdateSettings(this)) {
String realModelDir = getCacheDir() + "/" + SettingsActivity.modelDir;
// String detModelName = "ch_PP-OCRv2_det_infer";
String detModelName = "ch_PP-OCRv3_det_infer";
// String detModelName = "ch_ppocr_mobile_v2.0_det_infer";
String clsModelName = "ch_ppocr_mobile_v2.0_cls_infer";
// String recModelName = "ch_ppocr_mobile_v2.0_rec_infer";
String recModelName = "ch_PP-OCRv3_rec_infer";
// String recModelName = "ch_PP-OCRv2_rec_infer";
String realDetModelDir = realModelDir + "/" + detModelName;
String realClsModelDir = realModelDir + "/" + clsModelName;
String realRecModelDir = realModelDir + "/" + recModelName;
String srcDetModelDir = SettingsActivity.modelDir + "/" + detModelName;
String srcClsModelDir = SettingsActivity.modelDir + "/" + clsModelName;
String srcRecModelDir = SettingsActivity.modelDir + "/" + recModelName;
Utils.copyDirectoryFromAssets(this, srcDetModelDir, realDetModelDir);
Utils.copyDirectoryFromAssets(this, srcClsModelDir, realClsModelDir);
Utils.copyDirectoryFromAssets(this, srcRecModelDir, realRecModelDir);
String realLabelPath = getCacheDir() + "/" + SettingsActivity.labelPath;
Utils.copyFileFromAssets(this, SettingsActivity.labelPath, realLabelPath);
String detModelFile = realDetModelDir + "/" + "inference.pdmodel";
String detParamsFile = realDetModelDir + "/" + "inference.pdiparams";
String clsModelFile = realClsModelDir + "/" + "inference.pdmodel";
String clsParamsFile = realClsModelDir + "/" + "inference.pdiparams";
String recModelFile = realRecModelDir + "/" + "inference.pdmodel";
String recParamsFile = realRecModelDir + "/" + "inference.pdiparams";
String recLabelFilePath = realLabelPath; // ppocr_keys_v1.txt
RuntimeOption detOption = new RuntimeOption();
RuntimeOption clsOption = new RuntimeOption();
RuntimeOption recOption = new RuntimeOption();
detOption.setCpuThreadNum(SettingsActivity.cpuThreadNum);
clsOption.setCpuThreadNum(SettingsActivity.cpuThreadNum);
recOption.setCpuThreadNum(SettingsActivity.cpuThreadNum);
detOption.setLitePowerMode(SettingsActivity.cpuPowerMode);
clsOption.setLitePowerMode(SettingsActivity.cpuPowerMode);
recOption.setLitePowerMode(SettingsActivity.cpuPowerMode);
detOption.enableRecordTimeOfRuntime();
clsOption.enableRecordTimeOfRuntime();
recOption.enableRecordTimeOfRuntime();
if (Boolean.parseBoolean(SettingsActivity.enableLiteFp16)) {
detOption.enableLiteFp16();
clsOption.enableLiteFp16();
recOption.enableLiteFp16();
}
DBDetector detModel = new DBDetector(detModelFile, detParamsFile, detOption);
Classifier clsModel = new Classifier(clsModelFile, clsParamsFile, clsOption);
Recognizer recModel = new Recognizer(recModelFile, recParamsFile, recLabelFilePath, recOption);
predictor.init(detModel, clsModel, recModel);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
new AlertDialog.Builder(MainActivity.this)
.setTitle("Permission denied")
.setMessage("Click to force quit the app, then open Settings->Apps & notifications->Target " +
"App->Permissions to grant all of the permissions.")
.setCancelable(false)
.setPositiveButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
MainActivity.this.finish();
}
}).show();
}
}
private void requestAllPermissions() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA}, 0);
}
private boolean checkAllPermissions() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
}
}

View File

@@ -0,0 +1,198 @@
package com.baidu.paddle.fastdeploy.app.examples.ocr;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.PreferenceManager;
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.Utils;
import java.util.ArrayList;
import java.util.List;
public class SettingsActivity extends AppCompatPreferenceActivity implements
SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = SettingsActivity.class.getSimpleName();
static public int selectedModelIdx = -1;
static public String modelDir = "";
static public String labelPath = "";
static public int cpuThreadNum = 2;
static public String cpuPowerMode = "";
static public float scoreThreshold = 0.4f;
static public String enableLiteFp16 = "true";
ListPreference lpChoosePreInstalledModel = null;
EditTextPreference etModelDir = null;
EditTextPreference etLabelPath = null;
ListPreference lpCPUThreadNum = null;
ListPreference lpCPUPowerMode = null;
EditTextPreference etScoreThreshold = null;
ListPreference lpEnableLiteFp16 = null;
List<String> preInstalledModelDirs = null;
List<String> preInstalledLabelPaths = null;
List<String> preInstalledCPUThreadNums = null;
List<String> preInstalledCPUPowerModes = null;
List<String> preInstalledScoreThresholds = null;
List<String> preInstalledEnableLiteFp16s = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.ocr_settings);
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setDisplayHomeAsUpEnabled(true);
}
// Initialize pre-installed models
preInstalledModelDirs = new ArrayList<String>();
preInstalledLabelPaths = new ArrayList<String>();
preInstalledCPUThreadNums = new ArrayList<String>();
preInstalledCPUPowerModes = new ArrayList<String>();
preInstalledScoreThresholds = new ArrayList<String>();
preInstalledEnableLiteFp16s = new ArrayList<String>();
preInstalledModelDirs.add(getString(R.string.OCR_MODEL_DIR_DEFAULT));
preInstalledLabelPaths.add(getString(R.string.OCR_REC_LABEL_DEFAULT));
preInstalledCPUThreadNums.add(getString(R.string.CPU_THREAD_NUM_DEFAULT));
preInstalledCPUPowerModes.add(getString(R.string.CPU_POWER_MODE_DEFAULT));
preInstalledScoreThresholds.add(getString(R.string.SCORE_THRESHOLD_DEFAULT));
preInstalledEnableLiteFp16s.add(getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT));
// Setup UI components
lpChoosePreInstalledModel =
(ListPreference) findPreference(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY));
String[] preInstalledModelNames = new String[preInstalledModelDirs.size()];
for (int i = 0; i < preInstalledModelDirs.size(); i++) {
preInstalledModelNames[i] = preInstalledModelDirs.get(i).substring(preInstalledModelDirs.get(i).lastIndexOf("/") + 1);
}
lpChoosePreInstalledModel.setEntries(preInstalledModelNames);
lpChoosePreInstalledModel.setEntryValues(preInstalledModelDirs.toArray(new String[preInstalledModelDirs.size()]));
lpCPUThreadNum = (ListPreference) findPreference(getString(R.string.CPU_THREAD_NUM_KEY));
lpCPUPowerMode = (ListPreference) findPreference(getString(R.string.CPU_POWER_MODE_KEY));
etModelDir = (EditTextPreference) findPreference(getString(R.string.MODEL_DIR_KEY));
etModelDir.setTitle("Model dir (SDCard: " + Utils.getSDCardDirectory() + ")");
etLabelPath = (EditTextPreference) findPreference(getString(R.string.LABEL_PATH_KEY));
etLabelPath.setTitle("Label path (SDCard: " + Utils.getSDCardDirectory() + ")");
etScoreThreshold = (EditTextPreference) findPreference(getString(R.string.SCORE_THRESHOLD_KEY));
lpEnableLiteFp16 = (ListPreference) findPreference(getString(R.string.ENABLE_LITE_FP16_MODE_KEY));
}
@SuppressLint("ApplySharedPref")
private void reloadSettingsAndUpdateUI() {
SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
String selected_model_dir = sharedPreferences.getString(getString(R.string.CHOOSE_PRE_INSTALLED_MODEL_KEY),
getString(R.string.OCR_MODEL_DIR_DEFAULT));
int selected_model_idx = lpChoosePreInstalledModel.findIndexOfValue(selected_model_dir);
if (selected_model_idx >= 0 && selected_model_idx < preInstalledModelDirs.size() && selected_model_idx != selectedModelIdx) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(getString(R.string.MODEL_DIR_KEY), preInstalledModelDirs.get(selected_model_idx));
editor.putString(getString(R.string.LABEL_PATH_KEY), preInstalledLabelPaths.get(selected_model_idx));
editor.putString(getString(R.string.CPU_THREAD_NUM_KEY), preInstalledCPUThreadNums.get(selected_model_idx));
editor.putString(getString(R.string.CPU_POWER_MODE_KEY), preInstalledCPUPowerModes.get(selected_model_idx));
editor.putString(getString(R.string.SCORE_THRESHOLD_KEY), preInstalledScoreThresholds.get(selected_model_idx));
editor.putString(getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT), preInstalledEnableLiteFp16s.get(selected_model_idx));
editor.commit();
lpChoosePreInstalledModel.setSummary(selected_model_dir);
selectedModelIdx = selected_model_idx;
}
String model_dir = sharedPreferences.getString(getString(R.string.MODEL_DIR_KEY),
getString(R.string.OCR_MODEL_DIR_DEFAULT));
String label_path = sharedPreferences.getString(getString(R.string.LABEL_PATH_KEY),
getString(R.string.OCR_REC_LABEL_DEFAULT));
String cpu_thread_num = sharedPreferences.getString(getString(R.string.CPU_THREAD_NUM_KEY),
getString(R.string.CPU_THREAD_NUM_DEFAULT));
String cpu_power_mode = sharedPreferences.getString(getString(R.string.CPU_POWER_MODE_KEY),
getString(R.string.CPU_POWER_MODE_DEFAULT));
String score_threshold = sharedPreferences.getString(getString(R.string.SCORE_THRESHOLD_KEY),
getString(R.string.SCORE_THRESHOLD_DEFAULT));
String enable_lite_fp16 = sharedPreferences.getString(getString(R.string.ENABLE_LITE_FP16_MODE_KEY),
getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT));
etModelDir.setSummary(model_dir);
etLabelPath.setSummary(label_path);
lpCPUThreadNum.setValue(cpu_thread_num);
lpCPUThreadNum.setSummary(cpu_thread_num);
lpCPUPowerMode.setValue(cpu_power_mode);
lpCPUPowerMode.setSummary(cpu_power_mode);
etScoreThreshold.setSummary(score_threshold);
etScoreThreshold.setText(score_threshold);
lpEnableLiteFp16.setValue(enable_lite_fp16);
lpEnableLiteFp16.setSummary(enable_lite_fp16);
}
static boolean checkAndUpdateSettings(Context ctx) {
boolean settingsChanged = false;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx);
String model_dir = sharedPreferences.getString(ctx.getString(R.string.MODEL_DIR_KEY),
ctx.getString(R.string.OCR_MODEL_DIR_DEFAULT));
settingsChanged |= !modelDir.equalsIgnoreCase(model_dir);
modelDir = model_dir;
String label_path = sharedPreferences.getString(ctx.getString(R.string.LABEL_PATH_KEY),
ctx.getString(R.string.OCR_REC_LABEL_DEFAULT));
settingsChanged |= !labelPath.equalsIgnoreCase(label_path);
labelPath = label_path;
String cpu_thread_num = sharedPreferences.getString(ctx.getString(R.string.CPU_THREAD_NUM_KEY),
ctx.getString(R.string.CPU_THREAD_NUM_DEFAULT));
settingsChanged |= cpuThreadNum != Integer.parseInt(cpu_thread_num);
cpuThreadNum = Integer.parseInt(cpu_thread_num);
String cpu_power_mode = sharedPreferences.getString(ctx.getString(R.string.CPU_POWER_MODE_KEY),
ctx.getString(R.string.CPU_POWER_MODE_DEFAULT));
settingsChanged |= !cpuPowerMode.equalsIgnoreCase(cpu_power_mode);
cpuPowerMode = cpu_power_mode;
String score_threshold = sharedPreferences.getString(ctx.getString(R.string.SCORE_THRESHOLD_KEY),
ctx.getString(R.string.SCORE_THRESHOLD_DEFAULT));
settingsChanged |= scoreThreshold != Float.parseFloat(score_threshold);
scoreThreshold = Float.parseFloat(score_threshold);
String enable_lite_fp16 = sharedPreferences.getString(ctx.getString(R.string.ENABLE_LITE_FP16_MODE_KEY),
ctx.getString(R.string.ENABLE_LITE_FP16_MODE_DEFAULT));
settingsChanged |= !enableLiteFp16.equalsIgnoreCase(enable_lite_fp16);
enableLiteFp16 = enable_lite_fp16;
return settingsChanged;
}
static void resetSettings() {
selectedModelIdx = -1;
modelDir = "";
labelPath = "";
cpuThreadNum = 2;
cpuPowerMode = "";
scoreThreshold = 0.4f;
enableLiteFp16 = "true";
}
@Override
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
reloadSettingsAndUpdateUI();
}
@Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
reloadSettingsAndUpdateUI();
}
}

View File

@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
tools:context="com.baidu.paddle.fastdeploy.app.examples.detection.MainActivity">
tools:context="com.baidu.paddle.fastdeploy.app.examples.ocr.MainActivity">
<RelativeLayout
android:layout_width="match_parent"

View File

@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
tools:context="com.baidu.paddle.fastdeploy.app.examples.detection.MainActivity">
tools:context="com.baidu.paddle.fastdeploy.app.examples.ocr.MainActivity">
<RelativeLayout
android:layout_width="match_parent"

View File

@@ -1,5 +1,10 @@
<resources>
<!-- Default App name -->
<string name="app_name">FastDeploy PicoDet</string>
<!-- Other App name -->
<string name="detection_app_name">FastDeploy PicoDet</string>
<string name="ocr_app_name">FastDeploy PP-OCRv2</string>
<!-- Keys for PreferenceScreen -->
<string name="CHOOSE_PRE_INSTALLED_MODEL_KEY">CHOOSE_INSTALLED_MODEL_KEY</string>
<string name="MODEL_DIR_KEY">MODEL_DIR_KEY</string>
<string name="LABEL_PATH_KEY">LABEL_PATH_KEY</string>
@@ -7,13 +12,18 @@
<string name="CPU_POWER_MODE_KEY">CPU_POWER_MODE_KEY</string>
<string name="SCORE_THRESHOLD_KEY">SCORE_THRESHOLD_KEY</string>
<string name="ENABLE_LITE_FP16_MODE_KEY">ENABLE_LITE_FP16_MODE_KEY</string>
<string name="MODEL_DIR_DEFAULT">models/picodet_s_320_coco_lcnet</string>
<string name="LABEL_PATH_DEFAULT">labels/coco_label_list.txt</string>
<!-- Common default values ... -->
<string name="CPU_THREAD_NUM_DEFAULT">2</string>
<string name="CPU_POWER_MODE_DEFAULT">LITE_POWER_HIGH</string>
<string name="SCORE_THRESHOLD_DEFAULT">0.4</string>
<string name="ENABLE_LITE_FP16_MODE_DEFAULT">true</string>
<!--Other values-->
<!-- Default model & Label paths & other values ... -->
<string name="MODEL_DIR_DEFAULT">models/picodet_s_320_coco_lcnet</string>
<string name="LABEL_PATH_DEFAULT">labels/coco_label_list.txt</string>
<!-- PP-OCRv2 & PP-OCRv3 values ... -->
<string name="OCR_MODEL_DIR_DEFAULT">models</string>
<string name="OCR_REC_LABEL_DEFAULT">labels/ppocr_keys_v1.txt</string>
<!-- Other resources values-->
<string name="action_bar_take_photo">拍照识别</string>
<string name="action_bar_realtime">FD 实时识别</string>
<string name="action_bar_back">&lt;</string>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
</PreferenceScreen>

View File

@@ -0,0 +1,45 @@
<?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:key="@string/CHOOSE_PRE_INSTALLED_MODEL_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="Choose Pre-Installed Models" />
<EditTextPreference
android:defaultValue="@string/MODEL_DIR_DEFAULT"
android:key="@string/MODEL_DIR_KEY"
android:title="Model Dir" />
<EditTextPreference
android:defaultValue="@string/LABEL_PATH_DEFAULT"
android:key="@string/LABEL_PATH_KEY"
android:title="Label Path" />
<ListPreference
android:defaultValue="@string/CPU_THREAD_NUM_DEFAULT"
android:entries="@array/cpu_thread_num_entries"
android:entryValues="@array/cpu_thread_num_values"
android:key="@string/CPU_THREAD_NUM_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="CPU Thread Num" />
<ListPreference
android:defaultValue="@string/CPU_POWER_MODE_DEFAULT"
android:entries="@array/cpu_power_mode_entries"
android:entryValues="@array/cpu_power_mode_values"
android:key="@string/CPU_POWER_MODE_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="CPU Power Mode" />
<EditTextPreference
android:key="@string/SCORE_THRESHOLD_KEY"
android:defaultValue="@string/SCORE_THRESHOLD_DEFAULT"
android:title="Score Threshold: (0.0, 1.0)" />
<ListPreference
android:defaultValue="@string/ENABLE_LITE_FP16_MODE_DEFAULT"
android:entries="@array/enable_lite_fp16_mode_entries"
android:entryValues="@array/enable_lite_fp16_mode_values"
android:key="@string/ENABLE_LITE_FP16_MODE_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="Enable Lite FP16" />
</PreferenceScreen>

View File

@@ -0,0 +1,45 @@
<?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:key="@string/CHOOSE_PRE_INSTALLED_MODEL_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="Choose Pre-Installed Models" />
<EditTextPreference
android:defaultValue="@string/OCR_MODEL_DIR_DEFAULT"
android:key="@string/MODEL_DIR_KEY"
android:title="Model Dir" />
<EditTextPreference
android:defaultValue="@string/OCR_REC_LABEL_DEFAULT"
android:key="@string/LABEL_PATH_KEY"
android:title="Label Path" />
<ListPreference
android:defaultValue="@string/CPU_THREAD_NUM_DEFAULT"
android:entries="@array/cpu_thread_num_entries"
android:entryValues="@array/cpu_thread_num_values"
android:key="@string/CPU_THREAD_NUM_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="CPU Thread Num" />
<ListPreference
android:defaultValue="@string/CPU_POWER_MODE_DEFAULT"
android:entries="@array/cpu_power_mode_entries"
android:entryValues="@array/cpu_power_mode_values"
android:key="@string/CPU_POWER_MODE_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="CPU Power Mode" />
<EditTextPreference
android:key="@string/SCORE_THRESHOLD_KEY"
android:defaultValue="@string/SCORE_THRESHOLD_DEFAULT"
android:title="Score Threshold: (0.0, 1.0)" />
<ListPreference
android:defaultValue="@string/ENABLE_LITE_FP16_MODE_DEFAULT"
android:entries="@array/enable_lite_fp16_mode_entries"
android:entryValues="@array/enable_lite_fp16_mode_values"
android:key="@string/ENABLE_LITE_FP16_MODE_KEY"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="Enable Lite FP16" />
</PreferenceScreen>

View File

@@ -28,6 +28,7 @@ add_library(
SHARED
utils_jni.cc
bitmap_jni.cc
pipeline/ppocr_jni.cc
vision/results_jni.cc
vision/visualize_jni.cc
vision/detection/picodet_jni.cc

View File

@@ -0,0 +1,418 @@
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <jni.h> // NOLINT
#include "fastdeploy_jni.h" // NOLINT
namespace fastdeploy {
namespace jni {
namespace pipeline {
enum PPOCRVersion {
OCR_V1 = 0,
OCR_V2 = 1,
OCR_V3 = 2
};
/// Handle the native PP-OCR pipeline resources.
class PPOCRHandler {
public:
PPOCRHandler() = default;
PPOCRHandler(fastdeploy::vision::ocr::DBDetector *det_model,
fastdeploy::vision::ocr::Classifier *cls_model,
fastdeploy::vision::ocr::Recognizer *rec_model,
fastdeploy::pipeline::PPOCRv2 *ppocr_v2) :
detector_(det_model), classifier_(cls_model),
recognizer_(rec_model), ppocr_v2_(ppocr_v2) {
if (detector_ != nullptr && classifier_ != nullptr
&& recognizer_ != nullptr && ppocr_v2_ != nullptr) {
initialized_ = true;
}
}
PPOCRHandler(fastdeploy::vision::ocr::DBDetector *det_model,
fastdeploy::vision::ocr::Recognizer *rec_model,
fastdeploy::pipeline::PPOCRv2 *ppocr_v2) :
detector_(det_model), recognizer_(rec_model),
ppocr_v2_(ppocr_v2) {
if (detector_ != nullptr && recognizer_ != nullptr
&& ppocr_v2_ != nullptr) {
initialized_ = true;
}
}
PPOCRHandler(fastdeploy::vision::ocr::DBDetector *det_model,
fastdeploy::vision::ocr::Classifier *cls_model,
fastdeploy::vision::ocr::Recognizer *rec_model,
fastdeploy::pipeline::PPOCRv3 *ppocr_v3) :
detector_(det_model), classifier_(cls_model),
recognizer_(rec_model), ppocr_v3_(ppocr_v3) {
if (detector_ != nullptr && classifier_ != nullptr
&& recognizer_ != nullptr && ppocr_v3_ != nullptr) {
initialized_ = true;
}
}
PPOCRHandler(fastdeploy::vision::ocr::DBDetector *det_model,
fastdeploy::vision::ocr::Recognizer *rec_model,
fastdeploy::pipeline::PPOCRv3 *ppocr_v3) :
detector_(det_model), recognizer_(rec_model),
ppocr_v3_(ppocr_v3) {
if (detector_ != nullptr && recognizer_ != nullptr
&& ppocr_v3_ != nullptr) {
initialized_ = true;
}
}
void SetPPOCRVersion(PPOCRVersion version_tag) {
ppocr_version_tag_ = version_tag;
}
bool Predict(cv::Mat* img, fastdeploy::vision::OCRResult* result) {
if (ppocr_version_tag_ == PPOCRVersion::OCR_V2) {
if (ppocr_v2_ != nullptr) {
return ppocr_v2_->Predict(img, result);
}
return false;
} else if (ppocr_version_tag_ == PPOCRVersion::OCR_V3) {
if (ppocr_v3_ != nullptr) {
return ppocr_v3_->Predict(img, result);
}
return false;
}
return false;
}
bool Initialized() {
if (!initialized_) {
return false;
}
if (ppocr_version_tag_ == PPOCRVersion::OCR_V2) {
if (ppocr_v2_ != nullptr) {
return ppocr_v2_->Initialized();
}
return false;
} else if (ppocr_version_tag_ == PPOCRVersion::OCR_V3) {
if (ppocr_v3_ != nullptr) {
return ppocr_v3_->Initialized();
}
return false;
}
return false;
}
// Call init manually if you want to release the allocated
// PP-OCRv2/v3's memory by 'new' operator via 'delete'.
bool ReleaseAllocatedOCRMemories() {
if (!Initialized()) {
return false;
}
if (detector_ != nullptr) {
delete detector_;
detector_ = nullptr;
LOGD("[End] Release DBDetector in native !");
}
if (classifier_ != nullptr) {
delete classifier_;
classifier_ = nullptr;
LOGD("[End] Release Classifier in native !");
}
if (recognizer_ != nullptr) {
delete recognizer_;
recognizer_ = nullptr;
LOGD("[End] Release Recognizer in native !");
}
if (ppocr_v2_ != nullptr) {
delete ppocr_v2_;
ppocr_v2_ = nullptr;
LOGD("[End] Release PP-OCRv2 in native !");
}
if (ppocr_v3_ != nullptr) {
delete ppocr_v3_;
ppocr_v3_ = nullptr;
LOGD("[End] Release PP-OCRv3 in native !");
}
initialized_ = false;
return true;
}
void PrintPPOCRHandlerTimeOfRuntime() const {
if ((detector_ != nullptr) && (detector_->EnabledRecordTimeOfRuntime())) {
auto det_info_of_runtime = detector_->PrintStatisInfoOfRuntime();
LOGD("[Det] Avg runtime costs %f ms", det_info_of_runtime["avg_time"] * 1000.0f);
}
if ((classifier_ != nullptr) && (classifier_->EnabledRecordTimeOfRuntime())) {
auto cls_info_of_runtime = classifier_->PrintStatisInfoOfRuntime();
LOGD("[Cls] Avg runtime costs %f ms", cls_info_of_runtime["avg_time"] * 1000.0f);
}
if ((recognizer_ != nullptr) && (recognizer_->EnabledRecordTimeOfRuntime())) {
auto rec_info_of_runtime = recognizer_->PrintStatisInfoOfRuntime();
LOGD("[Rec] Avg runtime costs %f ms", rec_info_of_runtime["avg_time"] * 1000.0f);
}
}
public:
fastdeploy::vision::ocr::DBDetector *detector_ = nullptr;
fastdeploy::vision::ocr::Classifier *classifier_ = nullptr;
fastdeploy::vision::ocr::Recognizer *recognizer_ = nullptr;
fastdeploy::pipeline::PPOCRv2 *ppocr_v2_ = nullptr;
fastdeploy::pipeline::PPOCRv3 *ppocr_v3_ = nullptr;
private:
bool initialized_ = false;
PPOCRVersion ppocr_version_tag_ = PPOCRVersion::OCR_V2;
};
} // namespace pipeline
} // namespace jni
} // namespace fastdeploy
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_pipeline_PPOCRBase_bindNative(
JNIEnv *env,
jobject thiz,
jint ocr_version_tag,
jstring det_model_file,
jstring det_params_file,
jstring cls_model_file,
jstring cls_params_file,
jstring rec_model_file,
jstring rec_params_file,
jstring rec_label_path,
jint det_cpu_num_thread,
jint cls_cpu_num_thread,
jint rec_cpu_num_thread,
jboolean det_enable_lite_fp16,
jboolean cls_enable_lite_fp16,
jboolean rec_enable_lite_fp16,
jint det_lite_power_mode,
jint cls_lite_power_mode,
jint rec_lite_power_mode,
jstring det_lite_optimized_model_dir,
jstring cls_lite_optimized_model_dir,
jstring rec_lite_optimized_model_dir,
jboolean det_enable_record_time_of_runtime,
jboolean cls_enable_record_time_of_runtime,
jboolean rec_enable_record_time_of_runtime,
jboolean have_cls_model) {
auto c_ocr_version_tag = static_cast<
fastdeploy::jni::pipeline::PPOCRVersion>(ocr_version_tag);
if (c_ocr_version_tag == fastdeploy::jni::pipeline::PPOCRVersion::OCR_V1) {
LOGE("Not support for PPOCRVersion::OCR_V1 now!");
return 0;
}
// TODO(qiuyanjun): Allows users to set model parameters, such as det_db_box_thresh,
// det_db_thresh, use_dilation, etc. These parameters should be passed in via JNI.
std::string c_det_model_file = fastdeploy::jni::ConvertTo<std::string>(env, det_model_file);
std::string c_det_params_file = fastdeploy::jni::ConvertTo<std::string>(env, det_params_file);
std::string c_cls_model_file = fastdeploy::jni::ConvertTo<std::string>(env, cls_model_file);
std::string c_cls_params_file = fastdeploy::jni::ConvertTo<std::string>(env, cls_params_file);
std::string c_rec_model_file = fastdeploy::jni::ConvertTo<std::string>(env, rec_model_file);
std::string c_rec_params_file = fastdeploy::jni::ConvertTo<std::string>(env, rec_params_file);
std::string c_rec_label_path = fastdeploy::jni::ConvertTo<std::string>(env, rec_label_path);
auto c_det_cpu_num_thread = static_cast<int>(det_cpu_num_thread);
auto c_cls_cpu_num_thread = static_cast<int>(cls_cpu_num_thread);
auto c_rec_cpu_num_thread = static_cast<int>(rec_cpu_num_thread);
auto c_det_enable_lite_fp16 = static_cast<bool>(det_enable_lite_fp16);
auto c_cls_enable_lite_fp16 = static_cast<bool>(cls_enable_lite_fp16);
auto c_rec_enable_lite_fp16 = static_cast<bool>(rec_enable_lite_fp16);
auto c_det_lite_power_mode = static_cast<fastdeploy::LitePowerMode>(det_lite_power_mode);
auto c_cls_lite_power_mode = static_cast<fastdeploy::LitePowerMode>(cls_lite_power_mode);
auto c_rec_lite_power_mode = static_cast<fastdeploy::LitePowerMode>(rec_lite_power_mode);
std::string c_det_lite_optimized_model_dir = fastdeploy::jni::ConvertTo<std::string>(
env, det_lite_optimized_model_dir);
std::string c_cls_lite_optimized_model_dir = fastdeploy::jni::ConvertTo<std::string>(
env, cls_lite_optimized_model_dir);
std::string c_rec_lite_optimized_model_dir = fastdeploy::jni::ConvertTo<std::string>(
env, rec_lite_optimized_model_dir);
auto c_det_enable_record_time_of_runtime = static_cast<bool>(det_enable_record_time_of_runtime);
auto c_cls_enable_record_time_of_runtime = static_cast<bool>(cls_enable_record_time_of_runtime);
auto c_rec_enable_record_time_of_runtime = static_cast<bool>(rec_enable_record_time_of_runtime);
auto c_have_cls_model = static_cast<bool>(have_cls_model);
// RuntimeOptions in native
fastdeploy::RuntimeOption c_det_option;
c_det_option.UseCpu();
c_det_option.UseLiteBackend();
c_det_option.SetCpuThreadNum(c_det_cpu_num_thread);
c_det_option.SetLitePowerMode(c_det_lite_power_mode);
c_det_option.SetLiteOptimizedModelDir(c_det_lite_optimized_model_dir);
if (c_det_enable_lite_fp16) {
c_det_option.EnableLiteFP16();
}
fastdeploy::RuntimeOption c_cls_option;
c_cls_option.UseCpu();
c_cls_option.UseLiteBackend();
c_cls_option.SetCpuThreadNum(c_cls_cpu_num_thread);
c_cls_option.SetLitePowerMode(c_cls_lite_power_mode);
c_cls_option.SetLiteOptimizedModelDir(c_cls_lite_optimized_model_dir);
if (c_cls_enable_lite_fp16) {
c_cls_option.EnableLiteFP16();
}
fastdeploy::RuntimeOption c_rec_option;
c_rec_option.UseCpu();
c_rec_option.UseLiteBackend();
c_rec_option.SetCpuThreadNum(c_rec_cpu_num_thread);
c_rec_option.SetLitePowerMode(c_rec_lite_power_mode);
c_rec_option.SetLiteOptimizedModelDir(c_rec_lite_optimized_model_dir);
if (c_rec_enable_lite_fp16) {
c_rec_option.EnableLiteFP16();
}
// Init PP-OCR pipeline
auto c_det_model_ptr = new fastdeploy::vision::ocr::DBDetector(
c_det_model_file, c_det_params_file, c_det_option);
auto c_rec_model_ptr = new fastdeploy::vision::ocr::Recognizer(
c_rec_model_file, c_rec_params_file, c_rec_label_path, c_rec_option);
// Enable record Runtime time costs.
if (c_det_enable_record_time_of_runtime) {
c_det_model_ptr->EnableRecordTimeOfRuntime();
}
if (c_rec_enable_record_time_of_runtime) {
c_rec_model_ptr->EnableRecordTimeOfRuntime();
}
// PP-OCRv2
if (c_ocr_version_tag == fastdeploy::jni::pipeline::PPOCRVersion::OCR_V2) {
if (c_have_cls_model) {
auto c_cls_model_ptr = new fastdeploy::vision::ocr::Classifier(
c_cls_model_file, c_cls_params_file, c_cls_option);
if (c_cls_enable_record_time_of_runtime) {
c_cls_model_ptr->EnableRecordTimeOfRuntime();
}
auto c_ppocr_pipeline_ptr = new fastdeploy::pipeline::PPOCRv2(
c_det_model_ptr, c_cls_model_ptr, c_rec_model_ptr);
// PP-OCRv2 handler with cls model
auto c_ppocr_handler_ptr = new fastdeploy::jni::pipeline::PPOCRHandler(
c_det_model_ptr, c_cls_model_ptr, c_rec_model_ptr, c_ppocr_pipeline_ptr);
c_ppocr_handler_ptr->SetPPOCRVersion(c_ocr_version_tag);
// WARN: need to release manually in Java !
return reinterpret_cast<jlong>(c_ppocr_handler_ptr); // native handler context
} else {
auto c_ppocr_pipeline_ptr = new fastdeploy::pipeline::PPOCRv2(
c_det_model_ptr, c_rec_model_ptr);
// PP-OCRv2 handler without cls model
auto c_ppocr_handler_ptr = new fastdeploy::jni::pipeline::PPOCRHandler(
c_det_model_ptr, c_rec_model_ptr, c_ppocr_pipeline_ptr);
c_ppocr_handler_ptr->SetPPOCRVersion(c_ocr_version_tag);
// WARN: need to release manually in Java !
return reinterpret_cast<jlong>(c_ppocr_handler_ptr); // native handler context
}
} // PP-OCRv3
else if (c_ocr_version_tag == fastdeploy::jni::pipeline::PPOCRVersion::OCR_V3) {
if (c_have_cls_model) {
auto c_cls_model_ptr = new fastdeploy::vision::ocr::Classifier(
c_cls_model_file, c_cls_params_file, c_cls_option);
if (c_cls_enable_record_time_of_runtime) {
c_cls_model_ptr->EnableRecordTimeOfRuntime();
}
auto c_ppocr_pipeline_ptr = new fastdeploy::pipeline::PPOCRv3(
c_det_model_ptr, c_cls_model_ptr, c_rec_model_ptr);
// PP-OCRv3 handler with cls model
auto c_ppocr_handler_ptr = new fastdeploy::jni::pipeline::PPOCRHandler(
c_det_model_ptr, c_cls_model_ptr, c_rec_model_ptr, c_ppocr_pipeline_ptr);
c_ppocr_handler_ptr->SetPPOCRVersion(c_ocr_version_tag);
// WARN: need to release manually in Java !
return reinterpret_cast<jlong>(c_ppocr_handler_ptr); // native handler context
} else {
auto c_ppocr_pipeline_ptr = new fastdeploy::pipeline::PPOCRv3(
c_det_model_ptr, c_rec_model_ptr);
// PP-OCRv3 handler without cls model
auto c_ppocr_handler_ptr = new fastdeploy::jni::pipeline::PPOCRHandler(
c_det_model_ptr, c_rec_model_ptr, c_ppocr_pipeline_ptr);
c_ppocr_handler_ptr->SetPPOCRVersion(c_ocr_version_tag);
// WARN: need to release manually in Java !
return reinterpret_cast<jlong>(c_ppocr_handler_ptr); // native handler context
}
}
return 0;
}
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_pipeline_PPOCRBase_predictNative(
JNIEnv *env, jobject thiz, jlong native_handler_context,
jobject argb8888_bitmap, jboolean saved, jstring saved_image_path,
jboolean rendering) {
if (native_handler_context == 0) {
return 0;
}
cv::Mat c_bgr;
auto t = fastdeploy::jni::GetCurrentTime();
if (!fastdeploy::jni::ARGB888Bitmap2BGR(env, argb8888_bitmap, &c_bgr)) {
return 0;
}
LOGD("Read from bitmap costs %f ms", fastdeploy::jni::GetElapsedTime(t));
auto c_ppocr_handler_ptr = reinterpret_cast<fastdeploy::jni::pipeline::PPOCRHandler*>(
native_handler_context);
auto c_result_ptr = new fastdeploy::vision::OCRResult();
t = fastdeploy::jni::GetCurrentTime();
if (!c_ppocr_handler_ptr->Predict(&c_bgr, c_result_ptr)) {
delete c_result_ptr;
return 0;
}
LOGD("Predict from native costs %f ms", fastdeploy::jni::GetElapsedTime(t));
// DEBUG: show result
LOGD("Result: %s", c_result_ptr->Str().c_str());
c_ppocr_handler_ptr->PrintPPOCRHandlerTimeOfRuntime();
if (!c_result_ptr->boxes.empty() && rendering) {
t = fastdeploy::jni::GetCurrentTime();
auto c_vis_im = fastdeploy::vision::VisOcr(c_bgr, *(c_result_ptr));
LOGD("Visualize from native costs %f ms", fastdeploy::jni::GetElapsedTime(t));
// Rendering to bitmap
t = fastdeploy::jni::GetCurrentTime();
if (!fastdeploy::jni::BGR2ARGB888Bitmap(env, argb8888_bitmap, c_vis_im)) {
delete c_result_ptr;
return 0;
}
LOGD("Write to bitmap from native costs %f ms",
fastdeploy::jni::GetElapsedTime(t));
std::string c_saved_image_path =
fastdeploy::jni::ConvertTo<std::string>(env, saved_image_path);
if (!c_saved_image_path.empty() && saved) {
t = fastdeploy::jni::GetCurrentTime();
cv::imwrite(c_saved_image_path, c_vis_im);
LOGD("Save image from native costs %f ms, path: %s",
fastdeploy::jni::GetElapsedTime(t), c_saved_image_path.c_str());
}
}
// WARN: need to release it manually in Java !
return reinterpret_cast<jlong>(c_result_ptr); // native result context
}
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_pipeline_PPOCRBase_releaseNative(
JNIEnv *env, jobject thiz, jlong native_handler_context) {
if (native_handler_context == 0) {
return JNI_FALSE;
}
auto c_ppocr_handler_ptr = reinterpret_cast<fastdeploy::jni::pipeline::PPOCRHandler*>(
native_handler_context);
if (!c_ppocr_handler_ptr->ReleaseAllocatedOCRMemories()) {
delete c_ppocr_handler_ptr;
return JNI_FALSE;
}
delete c_ppocr_handler_ptr;
LOGD("[End] Release PPOCRHandler in native !");
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -22,7 +22,7 @@ extern "C" {
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_bindNative(
JNIEnv *env, jclass clazz, jstring model_file, jstring params_file,
JNIEnv *env, jobject thiz, jstring model_file, jstring params_file,
jstring config_file, jint cpu_num_thread, jboolean enable_lite_fp16,
jint lite_power_mode, jstring lite_optimized_model_dir,
jboolean enable_record_time_of_runtime, jstring label_file) {
@@ -66,7 +66,7 @@ Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_bindNativ
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_predictNative(
JNIEnv *env, jclass clazz, jlong native_model_context,
JNIEnv *env, jobject thiz, jlong native_model_context,
jobject argb8888_bitmap, jboolean saved, jstring saved_image_path,
jfloat score_threshold, jboolean rendering) {
if (native_model_context == 0) {
@@ -129,7 +129,7 @@ Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_predictNa
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_classification_PaddleClasModel_releaseNative(
JNIEnv *env, jclass clazz, jlong native_model_context) {
JNIEnv *env, jobject thiz, jlong native_model_context) {
auto c_model_ptr =
reinterpret_cast<fastdeploy::vision::classification::PaddleClasModel *>(
native_model_context);

View File

@@ -22,7 +22,7 @@ extern "C" {
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_bindNative(
JNIEnv *env, jclass clazz, jstring model_file, jstring params_file,
JNIEnv *env, jobject thiz, jstring model_file, jstring params_file,
jstring config_file, jint cpu_num_thread, jboolean enable_lite_fp16,
jint lite_power_mode, jstring lite_optimized_model_dir,
jboolean enable_record_time_of_runtime, jstring label_file) {
@@ -66,7 +66,7 @@ Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_bindNative(
JNIEXPORT jlong JNICALL
Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_predictNative(
JNIEnv *env, jclass clazz, jlong native_model_context,
JNIEnv *env, jobject thiz, jlong native_model_context,
jobject argb8888_bitmap, jboolean saved, jstring saved_image_path,
jfloat score_threshold, jboolean rendering) {
if (native_model_context == 0) {
@@ -128,7 +128,7 @@ Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_predictNative(
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_detection_PicoDet_releaseNative(
JNIEnv *env, jclass clazz, jlong native_model_context) {
JNIEnv *env, jobject thiz, jlong native_model_context) {
if (native_model_context == 0) {
return JNI_FALSE;
}

View File

@@ -25,7 +25,10 @@ extern "C" {
/// Native DetectionResult for vision::DetectionResult.
JNIEXPORT jint JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyBoxesNumFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return 0;
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
return static_cast<jint>(c_result_ptr->boxes.size());
@@ -33,7 +36,10 @@ Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyBoxesNumFromNative(
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyBoxesFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
if (c_result_ptr->boxes.empty()) {
@@ -50,7 +56,10 @@ Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyBoxesFromNative(
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyScoresFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
if (c_result_ptr->scores.empty()) {
@@ -63,7 +72,10 @@ Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyScoresFromNative(
JNIEXPORT jintArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyLabelIdsFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::DetectionResult *>(
native_result_context);
if (c_result_ptr->label_ids.empty()) {
@@ -76,7 +88,7 @@ Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_copyLabelIdsFromNative(
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_releaseNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return JNI_FALSE;
}
@@ -90,7 +102,10 @@ Java_com_baidu_paddle_fastdeploy_vision_DetectionResult_releaseNative(
/// Native ClassifyResult for vision::ClassifyResult.
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_copyScoresFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::ClassifyResult *>(
native_result_context);
if (c_result_ptr->scores.empty()) {
@@ -103,7 +118,10 @@ Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_copyScoresFromNative(
JNIEXPORT jintArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_copyLabelIdsFromNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::ClassifyResult *>(
native_result_context);
if (c_result_ptr->label_ids.empty()) {
@@ -116,7 +134,7 @@ Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_copyLabelIdsFromNative(
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_releaseNative(
JNIEnv *env, jclass clazz, jlong native_result_context) {
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return JNI_FALSE;
}
@@ -127,6 +145,123 @@ Java_com_baidu_paddle_fastdeploy_vision_ClassifyResult_releaseNative(
return JNI_TRUE;
}
/// Native OCRResult for vision::OCRResult.
JNIEXPORT jint JNICALL
Java_com_baidu_paddle_fastdeploy_vision_OCRResult_copyBoxesNumFromNative(
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return 0;
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::OCRResult *>(
native_result_context);
return static_cast<jint>(c_result_ptr->boxes.size());
}
JNIEXPORT jintArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_OCRResult_copyBoxesFromNative(
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::OCRResult *>(
native_result_context);
if (c_result_ptr->boxes.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->boxes.size());
int buffer[len * 8];
const auto &boxes = c_result_ptr->boxes;
for (int64_t i = 0; i < len; ++i) {
std::memcpy((buffer + i * 8), (boxes.at(i).data()), 8 * sizeof(int));
}
return fastdeploy::jni::ConvertTo<jintArray>(env, buffer, len * 4);
}
JNIEXPORT jobjectArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_OCRResult_copyTextFromNative(
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::OCRResult *>(
native_result_context);
if (c_result_ptr->text.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->text.size());
jclass jstr_clazz = env->FindClass("java/lang/String");
jobjectArray jstr_array = env->NewObjectArray(
static_cast<jsize>(len), jstr_clazz,env->NewStringUTF(""));
for (int64_t i = 0; i < len; ++i) {
env->SetObjectArrayElement(jstr_array, static_cast<jsize>(i),
fastdeploy::jni::ConvertTo<jstring>(
env, c_result_ptr->text.at(i)));
}
return jstr_array;
}
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_OCRResult_copyRecScoresFromNative(
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::OCRResult *>(
native_result_context);
if (c_result_ptr->rec_scores.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->rec_scores.size());
const float *buffer = static_cast<float *>(c_result_ptr->rec_scores.data());
return fastdeploy::jni::ConvertTo<jfloatArray>(env, buffer, len);
}
JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_OCRResult_copyClsScoresFromNative(
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::OCRResult *>(
native_result_context);
if (c_result_ptr->cls_scores.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->cls_scores.size());
const float *buffer = static_cast<float *>(c_result_ptr->cls_scores.data());
return fastdeploy::jni::ConvertTo<jfloatArray>(env, buffer, len);
}
JNIEXPORT jintArray JNICALL
Java_com_baidu_paddle_fastdeploy_vision_OCRResult_copyClsLabelsFromNative(
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return {};
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::OCRResult *>(
native_result_context);
if (c_result_ptr->cls_labels.empty()) {
return {};
}
const auto len = static_cast<int64_t>(c_result_ptr->cls_labels.size());
const int *buffer = static_cast<int *>(c_result_ptr->cls_labels.data());
return fastdeploy::jni::ConvertTo<jintArray>(env, buffer, len);
}
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_OCRResult_releaseNative(
JNIEnv *env, jobject thiz, jlong native_result_context) {
if (native_result_context == 0) {
return JNI_FALSE;
}
auto c_result_ptr = reinterpret_cast<fastdeploy::vision::OCRResult *>(
native_result_context);
delete c_result_ptr;
LOGD("Release OCRResult in native !");
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -19,6 +19,7 @@
extern "C" {
#endif
/// VisDetection
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_Visualize_visDetectionNative(
JNIEnv *env, jclass clazz, jobject argb8888_bitmap, jobjectArray boxes,
@@ -32,6 +33,8 @@ Java_com_baidu_paddle_fastdeploy_vision_Visualize_visDetectionNative(
}
fastdeploy::vision::DetectionResult c_result;
c_result.Resize(len);
// boxes [n,4]
bool check_validation = true;
for (int i = 0; i < len; ++i) {
auto j_box =
@@ -48,18 +51,19 @@ Java_com_baidu_paddle_fastdeploy_vision_Visualize_visDetectionNative(
if (!check_validation) {
return JNI_FALSE;
}
// scores [n]
jfloat *j_scores_ptr = env->GetFloatArrayElements(scores, nullptr);
std::memcpy(c_result.scores.data(), j_scores_ptr, len * sizeof(float));
env->ReleaseFloatArrayElements(scores, j_scores_ptr, 0);
// label_ids [n]
jint *j_label_ids_ptr = env->GetIntArrayElements(label_ids, nullptr);
std::memcpy(c_result.label_ids.data(), j_label_ids_ptr, len * sizeof(int));
env->ReleaseIntArrayElements(label_ids, j_label_ids_ptr, 0);
// Get labels from Java
// Get labels from Java [n]
std::vector<std::string> c_labels;
int label_len = env->GetArrayLength(labels);
if (label_len > 0) {
c_labels.reserve(label_len);
for (int i = 0; i < label_len; ++i) {
auto j_str =
reinterpret_cast<jstring>(env->GetObjectArrayElement(labels, i));
@@ -87,6 +91,158 @@ Java_com_baidu_paddle_fastdeploy_vision_Visualize_visDetectionNative(
return JNI_TRUE;
}
/// VisClassification
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_Visualize_visClassificationNative(
JNIEnv *env, jclass clazz, jobject argb8888_bitmap, jfloatArray scores,
jintArray label_ids, jfloat score_threshold, jfloat font_size,
jobjectArray labels) {
// Draw ClassifyResult to ARGB8888 Bitmap
int len = env->GetArrayLength(scores);
if ((len == 0) || (len != env->GetArrayLength(label_ids))) {
return JNI_FALSE;
}
fastdeploy::vision::ClassifyResult c_result;
c_result.scores.resize(len);
c_result.label_ids.resize(len);
// scores [n]
jfloat *j_scores_ptr = env->GetFloatArrayElements(scores, nullptr);
std::memcpy(c_result.scores.data(), j_scores_ptr, len * sizeof(float));
env->ReleaseFloatArrayElements(scores, j_scores_ptr, 0);
// label_ids [n]
jint *j_label_ids_ptr = env->GetIntArrayElements(label_ids, nullptr);
std::memcpy(c_result.label_ids.data(), j_label_ids_ptr, len * sizeof(int));
env->ReleaseIntArrayElements(label_ids, j_label_ids_ptr, 0);
// Get labels from Java [n]
std::vector<std::string> c_labels;
int label_len = env->GetArrayLength(labels);
if (label_len > 0) {
for (int i = 0; i < label_len; ++i) {
auto j_str =
reinterpret_cast<jstring>(env->GetObjectArrayElement(labels, i));
c_labels.push_back(fastdeploy::jni::ConvertTo<std::string>(env, j_str));
}
}
cv::Mat c_bgr;
// From ARGB Bitmap to BGR
if (!fastdeploy::jni::ARGB888Bitmap2BGR(env, argb8888_bitmap, &c_bgr)) {
return JNI_FALSE;
}
cv::Mat c_vis_im;
if (!c_labels.empty()) {
c_vis_im = fastdeploy::vision::VisClassification(
c_bgr, c_result, c_labels, 5, score_threshold, font_size);
} else {
c_vis_im = fastdeploy::vision::VisClassification(
c_bgr, c_result, 5, score_threshold, font_size);
}
// Rendering to bitmap
if (!fastdeploy::jni::BGR2ARGB888Bitmap(env, argb8888_bitmap, c_vis_im)) {
return JNI_FALSE;
}
return JNI_TRUE;
}
/// VisOcr
JNIEXPORT jboolean JNICALL
Java_com_baidu_paddle_fastdeploy_vision_Visualize_visOcrNative(
JNIEnv *env, jclass clazz, jobject argb8888_bitmap,
jobjectArray boxes, jobjectArray text, jfloatArray rec_scores,
jfloatArray cls_scores, jintArray cls_labels) {
// Draw OCRResult to ARGB8888 Bitmap
int len = env->GetArrayLength(boxes);
if ((len == 0) || (len != env->GetArrayLength(text)) ||
(len != env->GetArrayLength(rec_scores)) ||
(len != env->GetArrayLength(cls_scores)) ||
(len != env->GetArrayLength(cls_labels))) {
return JNI_FALSE;
}
fastdeploy::vision::OCRResult c_result;
c_result.boxes.resize(len);
c_result.rec_scores.resize(len);
c_result.cls_scores.resize(len);
c_result.cls_labels.resize(len);
// boxes [n,8]
bool check_validation = true;
for (int i = 0; i < len; ++i) {
auto j_box =
reinterpret_cast<jintArray>(env->GetObjectArrayElement(boxes, i));
if (env->GetArrayLength(j_box) == 8) {
jint *j_box_ptr = env->GetIntArrayElements(j_box, nullptr);
std::memcpy(c_result.boxes[i].data(), j_box_ptr, 8 * sizeof(int));
env->ReleaseIntArrayElements(j_box, j_box_ptr, 0);
} else {
check_validation = false;
break;
}
}
if (!check_validation) {
return JNI_FALSE;
}
// text [n]
int text_len = env->GetArrayLength(text);
if (text_len > 0) {
for (int i = 0; i < text_len; ++i) {
auto j_str =
reinterpret_cast<jstring>(env->GetObjectArrayElement(text, i));
c_result.text.push_back(fastdeploy::jni::ConvertTo<std::string>(env, j_str));
}
}
// rec_scores [n]
jfloat *j_rec_scores_ptr = env->GetFloatArrayElements(rec_scores, nullptr);
std::memcpy(c_result.rec_scores.data(), j_rec_scores_ptr, len * sizeof(float));
env->ReleaseFloatArrayElements(rec_scores, j_rec_scores_ptr, 0);
// cls_scores [n]
jfloat *j_cls_scores_ptr = env->GetFloatArrayElements(cls_scores, nullptr);
std::memcpy(c_result.cls_scores.data(), j_cls_scores_ptr, len * sizeof(float));
env->ReleaseFloatArrayElements(cls_scores, j_cls_scores_ptr, 0);
// cls_labels [n]
jint *j_cls_label_ptr = env->GetIntArrayElements(cls_labels, nullptr);
std::memcpy(c_result.cls_labels.data(), j_cls_label_ptr, len * sizeof(int));
env->ReleaseIntArrayElements(cls_labels, j_cls_label_ptr, 0);
cv::Mat c_bgr;
// From ARGB Bitmap to BGR
if (!fastdeploy::jni::ARGB888Bitmap2BGR(env, argb8888_bitmap, &c_bgr)) {
return JNI_FALSE;
}
auto c_vis_im = fastdeploy::vision::VisOcr(c_bgr, c_result);
// Rendering to bitmap
if (!fastdeploy::jni::BGR2ARGB888Bitmap(env, argb8888_bitmap, c_vis_im)) {
return JNI_FALSE;
}
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,195 @@
package com.baidu.paddle.fastdeploy.pipeline;
import android.graphics.Bitmap;
import com.baidu.paddle.fastdeploy.FastDeployInitializer;
import com.baidu.paddle.fastdeploy.vision.OCRResult;
import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector;
import com.baidu.paddle.fastdeploy.vision.ocr.Classifier;
import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer;
public class PPOCRBase {
protected long mNativeHandlerContext = 0; // Context from native.
protected boolean mInitialized = false;
public PPOCRBase() {
mInitialized = false;
}
// Constructor w/o classifier
public PPOCRBase(DBDetector detModel,
Recognizer recModel,
PPOCRVersion OCRVersionTag) {
init_(detModel, new Classifier(), recModel, OCRVersionTag);
}
public PPOCRBase(DBDetector detModel,
Classifier clsModel,
Recognizer recModel,
PPOCRVersion OCRVersionTag) {
init_(detModel, clsModel, recModel, OCRVersionTag);
}
// Call init manually w/o classifier
public boolean init(DBDetector detModel,
Recognizer recModel,
PPOCRVersion OCRVersionTag) {
return init_(detModel, new Classifier(), recModel, OCRVersionTag);
}
public boolean init(DBDetector detModel,
Classifier clsModel,
Recognizer recModel,
PPOCRVersion OCRVersionTag) {
return init_(detModel, clsModel, recModel, OCRVersionTag);
}
public boolean release() {
mInitialized = false;
if (mNativeHandlerContext == 0) {
return false;
}
return releaseNative(mNativeHandlerContext);
}
public boolean initialized() {
return mInitialized;
}
// Predict without image saving and bitmap rendering.
public OCRResult predict(Bitmap ARGB8888Bitmap) {
if (mNativeHandlerContext == 0) {
return new OCRResult();
}
// Only support ARGB8888 bitmap in native now.
return new OCRResult(predictNative(
mNativeHandlerContext, ARGB8888Bitmap, false,
"", false));
}
// Predict with image saving and bitmap rendering (will cost more times)
public OCRResult predict(Bitmap ARGB8888Bitmap,
String savedImagePath) {
// scoreThreshold is for visualizing only.
if (mNativeHandlerContext == 0) {
return new OCRResult();
}
// Only support ARGB8888 bitmap in native now.
return new OCRResult(predictNative(
mNativeHandlerContext, ARGB8888Bitmap, true,
savedImagePath, true));
}
public boolean init_(DBDetector detModel,
Classifier clsModel,
Recognizer recModel,
PPOCRVersion OCRVersionTag) {
if (!mInitialized) {
mNativeHandlerContext = bindNative(
OCRVersionTag.ordinal(),
detModel.mModelFile,
detModel.mParamsFile,
clsModel.mModelFile,
clsModel.mParamsFile,
recModel.mModelFile,
recModel.mParamsFile,
recModel.mLabelPath,
detModel.mRuntimeOption.mCpuThreadNum,
clsModel.mRuntimeOption.mCpuThreadNum,
recModel.mRuntimeOption.mCpuThreadNum,
detModel.mRuntimeOption.mEnableLiteFp16,
clsModel.mRuntimeOption.mEnableLiteFp16,
recModel.mRuntimeOption.mEnableLiteFp16,
detModel.mRuntimeOption.mLitePowerMode.ordinal(),
clsModel.mRuntimeOption.mLitePowerMode.ordinal(),
recModel.mRuntimeOption.mLitePowerMode.ordinal(),
detModel.mRuntimeOption.mLiteOptimizedModelDir,
clsModel.mRuntimeOption.mLiteOptimizedModelDir,
recModel.mRuntimeOption.mLiteOptimizedModelDir,
detModel.mRuntimeOption.mEnableRecordTimeOfRuntime,
clsModel.mRuntimeOption.mEnableRecordTimeOfRuntime,
recModel.mRuntimeOption.mEnableRecordTimeOfRuntime,
clsModel.initialized());
if (mNativeHandlerContext != 0) {
mInitialized = true;
}
return mInitialized;
} else {
// release current native context and bind a new one.
if (release()) {
mNativeHandlerContext = bindNative(
OCRVersionTag.ordinal(),
detModel.mModelFile,
detModel.mParamsFile,
clsModel.mModelFile,
clsModel.mParamsFile,
recModel.mModelFile,
recModel.mParamsFile,
recModel.mLabelPath,
detModel.mRuntimeOption.mCpuThreadNum,
clsModel.mRuntimeOption.mCpuThreadNum,
recModel.mRuntimeOption.mCpuThreadNum,
detModel.mRuntimeOption.mEnableLiteFp16,
clsModel.mRuntimeOption.mEnableLiteFp16,
recModel.mRuntimeOption.mEnableLiteFp16,
detModel.mRuntimeOption.mLitePowerMode.ordinal(),
clsModel.mRuntimeOption.mLitePowerMode.ordinal(),
recModel.mRuntimeOption.mLitePowerMode.ordinal(),
detModel.mRuntimeOption.mLiteOptimizedModelDir,
clsModel.mRuntimeOption.mLiteOptimizedModelDir,
recModel.mRuntimeOption.mLiteOptimizedModelDir,
detModel.mRuntimeOption.mEnableRecordTimeOfRuntime,
clsModel.mRuntimeOption.mEnableRecordTimeOfRuntime,
recModel.mRuntimeOption.mEnableRecordTimeOfRuntime,
clsModel.initialized());
if (mNativeHandlerContext != 0) {
mInitialized = true;
}
return mInitialized;
}
return false;
}
}
// Bind predictor from native context.
private native long bindNative(int PPOCRVersionTag,
String detModelFile,
String detParamsFile,
String clsModelFile,
String clsParamsFile,
String recModelFile,
String recParamsFile,
String recLabelPath,
int detCpuNumThread,
int clsCpuNumThread,
int recCpuNumThread,
boolean detEnableLiteFp16,
boolean clsEnableLiteFp16,
boolean recEnableLiteFp16,
int detLitePowerMode,
int clsLitePowerMode,
int recLitePowerMode,
String detLiteOptimizedModelDir,
String clsLiteOptimizedModelDir,
String recLiteOptimizedModelDir,
boolean detEnableRecordTimeOfRuntime,
boolean clsEnableRecordTimeOfRuntime,
boolean recEnableRecordTimeOfRuntime,
boolean haveClsModel);
// Call prediction from native context.
private native long predictNative(long nativeHandlerContext,
Bitmap ARGB8888Bitmap,
boolean saved,
String savedImagePath,
boolean rendering);
// Release buffers allocated in native context.
private native boolean releaseNative(long nativeHandlerContext);
// Initializes at the beginning.
static {
FastDeployInitializer.init();
}
}

View File

@@ -0,0 +1,7 @@
package com.baidu.paddle.fastdeploy.pipeline;
public enum PPOCRVersion {
OCR_V1,
OCR_V2,
OCR_V3
}

View File

@@ -0,0 +1,61 @@
package com.baidu.paddle.fastdeploy.pipeline;
import com.baidu.paddle.fastdeploy.vision.ocr.Classifier;
import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector;
import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer;
public class PPOCRv2 extends PPOCRBase {
public PPOCRv2() {
super();
}
// Constructor w/o classifier
public PPOCRv2(DBDetector detModel,
Recognizer recModel) {
super(detModel, recModel, PPOCRVersion.OCR_V2);
}
public PPOCRv2(DBDetector detModel,
Classifier clsModel,
Recognizer recModel) {
super(detModel, clsModel, recModel, PPOCRVersion.OCR_V2);
}
// Call init manually w/o classifier
public boolean init(DBDetector detModel,
Recognizer recModel) {
return init(detModel, recModel, PPOCRVersion.OCR_V2);
}
public boolean init(DBDetector detModel,
Classifier clsModel,
Recognizer recModel) {
return init(detModel, clsModel, recModel, PPOCRVersion.OCR_V2);
}
}

View File

@@ -0,0 +1,36 @@
package com.baidu.paddle.fastdeploy.pipeline;
import com.baidu.paddle.fastdeploy.vision.ocr.Classifier;
import com.baidu.paddle.fastdeploy.vision.ocr.DBDetector;
import com.baidu.paddle.fastdeploy.vision.ocr.Recognizer;
public class PPOCRv3 extends PPOCRBase {
public PPOCRv3() {
super();
}
// Constructor w/o classifier
public PPOCRv3(DBDetector detModel,
Recognizer recModel) {
super(detModel, recModel, PPOCRVersion.OCR_V3);
}
public PPOCRv3(DBDetector detModel,
Classifier clsModel,
Recognizer recModel) {
super(detModel, clsModel, recModel, PPOCRVersion.OCR_V3);
}
// Call init manually w/o classifier
public boolean init(DBDetector detModel,
Recognizer recModel) {
return init(detModel, recModel, PPOCRVersion.OCR_V3);
}
public boolean init(DBDetector detModel,
Classifier clsModel,
Recognizer recModel) {
return init(detModel, clsModel, recModel, PPOCRVersion.OCR_V3);
}
}

View File

@@ -42,10 +42,10 @@ public class ClassifyResult {
}
// Fetch native buffers from native context.
private static native float[] copyScoresFromNative(long nativeResultContext);
private native float[] copyScoresFromNative(long nativeResultContext);
private static native int[] copyLabelIdsFromNative(long nativeResultContext);
private native int[] copyLabelIdsFromNative(long nativeResultContext);
private static native boolean releaseNative(long nativeResultContext);
private native boolean releaseNative(long nativeResultContext);
}

View File

@@ -63,15 +63,15 @@ public class DetectionResult {
}
// Fetch native buffers from native context.
private static native int copyBoxesNumFromNative(long nativeResultContext);
private native int copyBoxesNumFromNative(long nativeResultContext);
private static native float[] copyBoxesFromNative(long nativeResultContext);
private native float[] copyBoxesFromNative(long nativeResultContext);
private static native float[] copyScoresFromNative(long nativeResultContext);
private native float[] copyScoresFromNative(long nativeResultContext);
private static native int[] copyLabelIdsFromNative(long nativeResultContext);
private native int[] copyLabelIdsFromNative(long nativeResultContext);
private static native boolean releaseNative(long nativeResultContext);
private native boolean releaseNative(long nativeResultContext);
// Initializes at the beginning.
static {

View File

@@ -0,0 +1,99 @@
package com.baidu.paddle.fastdeploy.vision;
import android.support.annotation.NonNull;
import com.baidu.paddle.fastdeploy.FastDeployInitializer;
import java.util.Arrays;
public class OCRResult {
public int[][] mBoxes; // [n,8]
public String[] mText; // [n]
public float[] mRecScores; // [n]
public float[] mClsScores; // [n]
public int[] mClsLabels; // [n]
public boolean mInitialized = false;
public OCRResult() {
mInitialized = false;
}
public OCRResult(long nativeResultContext) {
mInitialized = copyAllFromNativeContext(nativeResultContext);
}
public boolean initialized() {
return mInitialized;
}
// Setup results from native buffers.
private boolean copyAllFromNativeContext(long nativeResultContext) {
if (nativeResultContext == 0) {
return false;
}
if (copyBoxesNumFromNative(nativeResultContext) > 0) {
setBoxes(copyBoxesFromNative(nativeResultContext));
setText(copyTextFromNative(nativeResultContext));
setRecScores(copyRecScoresFromNative(nativeResultContext));
setClsScores(copyClsScoresFromNative(nativeResultContext));
setClsLabels(copyClsLabelsFromNative(nativeResultContext));
}
// WARN: must release ctx.
return releaseNative(nativeResultContext);
}
private void setBoxes(@NonNull int[] boxesBuffer) {
int boxesNum = boxesBuffer.length / 8;
if (boxesNum > 0) {
mBoxes = new int[boxesNum][8];
for (int i = 0; i < boxesNum; ++i) {
mBoxes[i] = Arrays.copyOfRange(
boxesBuffer, i * 8, (i + 1) * 8);
}
}
}
private void setText(@NonNull String[] textBuffer) {
if (textBuffer.length > 0) {
mText = textBuffer.clone();
}
}
private void setRecScores(@NonNull float[] recScoresBuffer) {
if (recScoresBuffer.length > 0) {
mRecScores = recScoresBuffer.clone();
}
}
private void setClsScores(@NonNull float[] clsScoresBuffer) {
if (clsScoresBuffer.length > 0) {
mClsScores = clsScoresBuffer.clone();
}
}
private void setClsLabels(@NonNull int[] clsLabelBuffer) {
if (clsLabelBuffer.length > 0) {
mClsLabels = clsLabelBuffer.clone();
}
}
// Fetch native buffers from native context.
private native int copyBoxesNumFromNative(long nativeResultContext);
private native int[] copyBoxesFromNative(long nativeResultContext);
private native String[] copyTextFromNative(long nativeResultContext);
private native float[] copyRecScoresFromNative(long nativeResultContext);
private native float[] copyClsScoresFromNative(long nativeResultContext);
private native int[] copyClsLabelsFromNative(long nativeResultContext);
private native boolean releaseNative(long nativeResultContext);
// Initializes at the beginning.
static {
FastDeployInitializer.init();
}
}

View File

@@ -52,10 +52,10 @@ public class Visualize {
public static boolean visDetection(Bitmap ARGB8888Bitmap,
DetectionResult result,
String[] labels,
float score_threshold,
int line_size,
float font_size,
String[] labels) {
float font_size) {
return visDetectionNative(
ARGB8888Bitmap,
result.mBoxes,
@@ -67,15 +67,97 @@ public class Visualize {
labels);
}
// Visualize ClassifyResult without labels
public static boolean visClassification(Bitmap ARGB8888Bitmap,
ClassifyResult result) {
return visClassificationNative(
ARGB8888Bitmap,
result.mScores,
result.mLabelIds,
0.f, 1,
new String[]{});
}
public static boolean visClassification(Bitmap ARGB8888Bitmap,
ClassifyResult result,
float score_threshold,
float font_size) {
return visClassificationNative(
ARGB8888Bitmap,
result.mScores,
result.mLabelIds,
score_threshold,
font_size,
new String[]{});
}
// Visualize ClassifyResult with labels
public static boolean visClassification(Bitmap ARGB8888Bitmap,
ClassifyResult result,
String[] labels) {
return visClassificationNative(
ARGB8888Bitmap,
result.mScores,
result.mLabelIds,
0.f, 1,
labels);
}
public static boolean visClassification(Bitmap ARGB8888Bitmap,
ClassifyResult result,
String[] labels,
float score_threshold,
float font_size) {
return visClassificationNative(
ARGB8888Bitmap,
result.mScores,
result.mLabelIds,
score_threshold,
font_size,
labels);
}
// Visualize OCRResult
public static boolean visOcr(Bitmap ARGB8888Bitmap,
OCRResult result) {
return visOcrNative(
ARGB8888Bitmap,
result.mBoxes,
result.mText,
result.mRecScores,
result.mClsScores,
result.mClsLabels);
}
// VisDetection in native
public static native boolean visDetectionNative(Bitmap ARGB8888Bitmap,
float[][] boxes,
float[] scores,
int[] labelIds,
float score_threshold,
int line_size,
float font_size,
String[] labels);
private static native boolean visDetectionNative(Bitmap ARGB8888Bitmap,
float[][] boxes,
float[] scores,
int[] labelIds,
float score_threshold,
int line_size,
float font_size,
String[] labels);
// VisClassification in native
private static native boolean visClassificationNative(Bitmap ARGB8888Bitmap,
float[] scores,
int[] labelIds,
float score_threshold,
float font_size,
String[] labels);
// VisOCRResult in native
private static native boolean visOcrNative(Bitmap ARGB8888Bitmap,
int[][] boxes,
String[] text,
float[] recScores,
float[] clsScores,
int[] clsLabels);
/* Initializes at the beginning */

View File

@@ -143,26 +143,26 @@ public class PaddleClasModel {
// Bind predictor from native context.
private static native long bindNative(String modelFile,
String paramsFile,
String configFile,
int cpuNumThread,
boolean enableLiteFp16,
int litePowerMode,
String liteOptimizedModelDir,
boolean enableRecordTimeOfRuntime,
String labelFile);
private native long bindNative(String modelFile,
String paramsFile,
String configFile,
int cpuNumThread,
boolean enableLiteFp16,
int litePowerMode,
String liteOptimizedModelDir,
boolean enableRecordTimeOfRuntime,
String labelFile);
// Call prediction from native context.
private static native long predictNative(long nativeModelContext,
Bitmap ARGB8888Bitmap,
boolean saved,
String savedImagePath,
float scoreThreshold,
boolean rendering);
private native long predictNative(long nativeModelContext,
Bitmap ARGB8888Bitmap,
boolean saved,
String savedImagePath,
float scoreThreshold,
boolean rendering);
// Release buffers allocated in native context.
private static native boolean releaseNative(long nativeModelContext);
private native boolean releaseNative(long nativeModelContext);
// Initializes at the beginning.
static {

View File

@@ -141,26 +141,26 @@ public class PicoDet {
}
// Bind predictor from native context.
private static native long bindNative(String modelFile,
String paramsFile,
String configFile,
int cpuNumThread,
boolean enableLiteFp16,
int litePowerMode,
String liteOptimizedModelDir,
boolean enableRecordTimeOfRuntime,
String labelFile);
private native long bindNative(String modelFile,
String paramsFile,
String configFile,
int cpuNumThread,
boolean enableLiteFp16,
int litePowerMode,
String liteOptimizedModelDir,
boolean enableRecordTimeOfRuntime,
String labelFile);
// Call prediction from native context.
private static native long predictNative(long nativeModelContext,
Bitmap ARGB8888Bitmap,
boolean saved,
String savedImagePath,
float scoreThreshold,
boolean rendering);
private native long predictNative(long nativeModelContext,
Bitmap ARGB8888Bitmap,
boolean saved,
String savedImagePath,
float scoreThreshold,
boolean rendering);
// Release buffers allocated in native context.
private static native boolean releaseNative(long nativeModelContext);
private native boolean releaseNative(long nativeModelContext);
// Initializes at the beginning.
static {

View File

@@ -0,0 +1,41 @@
package com.baidu.paddle.fastdeploy.vision.ocr;
import com.baidu.paddle.fastdeploy.RuntimeOption;
public class Classifier {
// TODO(qiuyanjun): Allows users to set model parameters,
// such as cls_thresh, cls_image_shape, is_scale, etc.
// These parameters should be passed in via JNI.
public String mModelFile;
public String mParamsFile;
public RuntimeOption mRuntimeOption;
public boolean mInitialized = false;
public Classifier() {
mModelFile = "";
mParamsFile = "";
mRuntimeOption = new RuntimeOption();
mInitialized = false;
}
public Classifier(String modelFile,
String paramsFile) {
mModelFile = modelFile;
mParamsFile = paramsFile;
mRuntimeOption = new RuntimeOption();
mInitialized = true;
}
public Classifier(String modelFile,
String paramsFile,
RuntimeOption option) {
mModelFile = modelFile;
mParamsFile = paramsFile;
mRuntimeOption = option;
mInitialized = true;
}
public boolean initialized() {
return mInitialized;
}
}

View File

@@ -0,0 +1,41 @@
package com.baidu.paddle.fastdeploy.vision.ocr;
import com.baidu.paddle.fastdeploy.RuntimeOption;
public class DBDetector {
// TODO(qiuyanjun): Allows users to set model parameters,
// such as det_db_box_thresh, det_db_thresh, use_dilation, etc.
// These parameters should be passed in via JNI.
public String mModelFile;
public String mParamsFile;
public RuntimeOption mRuntimeOption;
public boolean mInitialized = false;
public DBDetector() {
mModelFile = "";
mParamsFile = "";
mRuntimeOption = new RuntimeOption();
mInitialized = false;
}
public DBDetector(String modelFile,
String paramsFile) {
mModelFile = modelFile;
mParamsFile = paramsFile;
mRuntimeOption = new RuntimeOption();
mInitialized = true;
}
public DBDetector(String modelFile,
String paramsFile,
RuntimeOption option) {
mModelFile = modelFile;
mParamsFile = paramsFile;
mRuntimeOption = option;
mInitialized = true;
}
public boolean initialized() {
return mInitialized;
}
}

View File

@@ -0,0 +1,47 @@
package com.baidu.paddle.fastdeploy.vision.ocr;
import com.baidu.paddle.fastdeploy.RuntimeOption;
public class Recognizer {
// TODO(qiuyanjun): Allows users to set model parameters,
// such as rec_img_h, rec_img_w, rec_image_shape, etc.
// These parameters should be passed in via JNI.
public String mModelFile;
public String mParamsFile;
public String mLabelPath;
public RuntimeOption mRuntimeOption;
public boolean mInitialized = false;
public Recognizer() {
mModelFile = "";
mParamsFile = "";
mLabelPath = "";
mRuntimeOption = new RuntimeOption();
mInitialized = false;
}
public Recognizer(String modelFile,
String paramsFile,
String labelPath) {
mModelFile = modelFile;
mParamsFile = paramsFile;
mLabelPath = labelPath;
mRuntimeOption = new RuntimeOption();
mInitialized = true;
}
public Recognizer(String modelFile,
String paramsFile,
String labelPath,
RuntimeOption option) {
mModelFile = modelFile;
mParamsFile = paramsFile;
mLabelPath = labelPath;
mRuntimeOption = option;
mInitialized = true;
}
public boolean initialized() {
return mInitialized;
}
}