diff --git a/java/android/.gitignore b/java/android/.gitignore index f6eba672f..4837bbf3e 100644 --- a/java/android/.gitignore +++ b/java/android/.gitignore @@ -5,14 +5,14 @@ cache build app/cache -app/libs/fastdeploy* +app/libs/* app/.cxx app/build app/src/main/assets/models/* app/.gradle app/.idea fastdeploy/cache -fastdeploy/libs/fastdeploy* +fastdeploy/libs/* fastdeploy/.cxx fastdeploy/build fastdeploy/src/main/assets/models/* diff --git a/java/android/app/build.gradle b/java/android/app/build.gradle index 94ad62657..a0353e01f 100644 --- a/java/android/app/build.gradle +++ b/java/android/app/build.gradle @@ -23,13 +23,14 @@ android { dependencies { implementation fileTree(include: ['*.aar'], dir: 'libs') + //noinspection GradleCompatible implementation 'com.android.support:appcompat-v7:28.0.0' //noinspection GradleDependency implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support:design:28.0.0' implementation 'org.jetbrains:annotations:15.0' - implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0' // implementation project(path: ':fastdeploy') + implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0' implementation project(path: ':ui') //noinspection GradleDependency testImplementation 'junit:junit:4.12' @@ -73,6 +74,10 @@ def FD_MODEL = [ [ 'src' : 'https://bj.bcebos.com/paddlehub/fastdeploy/PP_TinyPose_128x96_infer.tgz', 'dest': 'src/main/assets/models' + ], + [ + 'src': 'https://bj.bcebos.com/paddlehub/fastdeploy/uie-nano.tgz', + 'dest': 'src/main/assets/models' ] ] diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIEMainActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIEMainActivity.java new file mode 100644 index 000000000..a79eeb31c --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIEMainActivity.java @@ -0,0 +1,242 @@ +package com.baidu.paddle.fastdeploy.app.examples.text.uie; + +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.os.Bundle; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +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.Button; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.ImageView; + +import com.baidu.paddle.fastdeploy.RuntimeOption; +import com.baidu.paddle.fastdeploy.app.examples.R; +import com.baidu.paddle.fastdeploy.text.UIEResult; +import com.baidu.paddle.fastdeploy.text.uie.UIEModel; +import com.baidu.paddle.fastdeploy.text.uie.SchemaLanguage; +import com.baidu.paddle.fastdeploy.ui.Utils; + +import java.util.HashMap; + +public class UIEMainActivity extends Activity implements View.OnClickListener { + private static final String TAG = UIEMainActivity.class.getSimpleName() + "[FastDeploy][Java]"; + private ImageView back; + private ImageButton btnSettings; + private EditText etUIEInput; + private EditText etUIESchema; + private EditText etUIEOutput; + private Button btnUIEAnalysis; + private String[] inputTexts; + private String[] schemaTexts; + + // Call 'init' and 'release' manually later + UIEModel predictor = new UIEModel(); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Fullscreen + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setContentView(R.layout.uie_activity_main); + + // Clear all setting items to avoid app crashing due to the incorrect settings + initSettings(); + + // Check and request CAMERA and WRITE_EXTERNAL_STORAGE permissions + if (!checkAllPermissions()) { + requestAllPermissions(); + } + + // Init the camera preview and UI components + initView(); + } + + @Override + protected void onResume() { + super.onResume(); + // Reload settings and re-initialize the predictor + checkAndUpdateSettings(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + if (predictor != null) { + predictor.release(); + } + super.onDestroy(); + } + + private void initView() { + // Back from setting page to main page + back = findViewById(R.id.iv_back); + back.setOnClickListener(this); + // Apply UIE predict + btnUIEAnalysis = findViewById(R.id.btn_uie_analysis); + btnUIEAnalysis.setOnClickListener(this); + // UIE input, schema and output texts + etUIEInput = findViewById(R.id.et_uie_input); + etUIESchema = findViewById(R.id.et_uie_schema); + etUIEOutput = findViewById(R.id.et_uie_output); + // Setting page + btnSettings = findViewById(R.id.btn_settings); + btnSettings.setOnClickListener(this); + } + + @SuppressLint("NonConstantResourceId") + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.btn_settings: + startActivity(new Intent(UIEMainActivity.this, UIESettingsActivity.class)); + break; + case R.id.iv_back: + finish(); + break; + case R.id.btn_uie_analysis: + extractTextsInformation(); + break; + default: + break; + } + + } + + public void extractTextsInformation() { + if (updateInputTexts() && updateSchemaTexts()) { + // Set schema before predict + if (predictor.setSchema(schemaTexts)) { + // Apply Information Extraction + HashMap[] results = predictor.predict(inputTexts); + updateOutputTexts(results); + } + } + } + + public void updateOutputTexts(HashMap[] results) { + if (results == null) { + etUIEOutput.setText("抽取结果为空"); + return; + } + // Merge UIEResult strings -> combinedOutputText + String combinedOutputText = UIEResult.printResult(results); + // Update output text view (EditText) + etUIEOutput.setText(combinedOutputText); + } + + public boolean updateInputTexts() { + String combinedInputText = etUIEInput.getText().toString(); + if (combinedInputText == null || combinedInputText.length() == 0) { + // Use default text if no custom text + combinedInputText = getString(R.string.UIE_INPUT_TEXTS_DEFAULT); + } + String[] texts = combinedInputText.split("[。!!:;:;]"); + if (texts.length <= 0) { + return false; + } + for (int i = 0; i < texts.length; ++i) { + texts[i] = texts[i].trim(); + } + // Update input texts + inputTexts = texts; + return true; + } + + public boolean updateSchemaTexts() { + String combinedSchemaText = etUIESchema.getText().toString(); + if (combinedSchemaText == null || combinedSchemaText.length() == 0) { + // Use default schema if no custom schema + combinedSchemaText = getString(R.string.UIE_SCHEMA_DEFAULT); + } + String[] schemas = combinedSchemaText.split("[,,|、:;:;]"); + if (schemas.length <= 0) { + return false; + } + for (int i = 0; i < schemas.length; ++i) { + schemas[i] = schemas[i].trim(); + } + + // Update schema texts + schemaTexts = schemas; + return true; + } + + @SuppressLint("ApplySharedPref") + public void initSettings() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.clear(); + editor.commit(); + UIESettingsActivity.resetSettings(); + } + + public void checkAndUpdateSettings() { + if (UIESettingsActivity.checkAndUpdateSettings(this)) { + String realModelDir = getCacheDir() + "/" + UIESettingsActivity.modelDir; + Utils.copyDirectoryFromAssets(this, UIESettingsActivity.modelDir, realModelDir); + + String modelFile = realModelDir + "/" + "inference.pdmodel"; + String paramsFile = realModelDir + "/" + "inference.pdiparams"; + String vocabFile = realModelDir + "/" + "vocab.txt"; + RuntimeOption option = new RuntimeOption(); + option.setCpuThreadNum(UIESettingsActivity.cpuThreadNum); + option.setLitePowerMode(UIESettingsActivity.cpuPowerMode); + if (Boolean.parseBoolean(UIESettingsActivity.enableLiteFp16)) { + option.enableLiteFp16(); + } + predictor.init(modelFile, paramsFile, vocabFile, + 0.3f, 128, schemaTexts, + option, SchemaLanguage.ZH); + } + } + + @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(UIEMainActivity.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) { + UIEMainActivity.this.finish(); + } + }).show(); + } + } + + private void requestAllPermissions() { + ActivityCompat.requestPermissions( + this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + 0); + } + + private boolean checkAllPermissions() { + return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED; + } + +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIESettingsActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIESettingsActivity.java new file mode 100644 index 000000000..eda0a37f7 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIESettingsActivity.java @@ -0,0 +1,164 @@ +package com.baidu.paddle.fastdeploy.app.examples.text.uie; + +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.ui.Utils; +import com.baidu.paddle.fastdeploy.ui.view.AppCompatPreferenceActivity; + +import java.util.ArrayList; +import java.util.List; + +public class UIESettingsActivity extends AppCompatPreferenceActivity implements + SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = UIESettingsActivity.class.getSimpleName(); + static public int selectedModelIdx = -1; + static public String modelDir = ""; + static public int cpuThreadNum = 2; + static public String cpuPowerMode = ""; + static public String enableLiteFp16 = "true"; + + ListPreference lpChoosePreInstalledModel = null; + EditTextPreference etModelDir = null; + ListPreference lpCPUThreadNum = null; + ListPreference lpCPUPowerMode = null; + ListPreference lpEnableLiteFp16 = null; + + List preInstalledModelDirs = null; + List preInstalledCPUThreadNums = null; + List preInstalledCPUPowerModes = null; + List preInstalledEnableLiteFp16s = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.uie_settings); + ActionBar supportActionBar = getSupportActionBar(); + if (supportActionBar != null) { + supportActionBar.setDisplayHomeAsUpEnabled(true); + } + + // Initialize pre-installed models + preInstalledModelDirs = new ArrayList(); + preInstalledCPUThreadNums = new ArrayList(); + preInstalledCPUPowerModes = new ArrayList(); + preInstalledEnableLiteFp16s = new ArrayList(); + preInstalledModelDirs.add(getString(R.string.UIE_MODEL_DIR_DEFAULT)); + preInstalledCPUThreadNums.add(getString(R.string.CPU_THREAD_NUM_DEFAULT)); + preInstalledCPUPowerModes.add(getString(R.string.CPU_POWER_MODE_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() + ")"); + 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.UIE_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.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.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.UIE_MODEL_DIR_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 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); + lpCPUThreadNum.setValue(cpu_thread_num); + lpCPUThreadNum.setSummary(cpu_thread_num); + lpCPUPowerMode.setValue(cpu_power_mode); + lpCPUPowerMode.setSummary(cpu_power_mode); + 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.UIE_MODEL_DIR_DEFAULT)); + settingsChanged |= !modelDir.equalsIgnoreCase(model_dir); + modelDir = model_dir; + + 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 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 = ""; + cpuThreadNum = 2; + cpuPowerMode = ""; + 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(); + } + +} diff --git a/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIEWelcomeActivity.java b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIEWelcomeActivity.java new file mode 100644 index 000000000..75ca1f424 --- /dev/null +++ b/java/android/app/src/main/java/com/baidu/paddle/fastdeploy/app/examples/text/uie/UIEWelcomeActivity.java @@ -0,0 +1,30 @@ +package com.baidu.paddle.fastdeploy.app.examples.text.uie; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.baidu.paddle.fastdeploy.app.examples.R; + +public class UIEWelcomeActivity extends Activity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + ); + getWindow().setStatusBarColor(Color.TRANSPARENT); + } + setContentView(R.layout.uie_welcome); + } + + public void startActivity(View view) { + Intent intent = new Intent(UIEWelcomeActivity.this, UIEMainActivity.class); + startActivity(intent); + } +} diff --git a/java/android/app/src/main/res/layout/uie_activity_main.xml b/java/android/app/src/main/res/layout/uie_activity_main.xml new file mode 100644 index 000000000..a35954ae6 --- /dev/null +++ b/java/android/app/src/main/res/layout/uie_activity_main.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + +