未验证 提交 ec903eb5 编写于 作者: X xiaoting 提交者: GitHub

Merge pull request #492 from authorfu/develop

mini demo modification
...@@ -3,11 +3,11 @@ import java.security.MessageDigest ...@@ -3,11 +3,11 @@ import java.security.MessageDigest
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 28 compileSdkVersion 29
defaultConfig { defaultConfig {
applicationId "com.baidu.paddle.lite.demo.ocr" applicationId "com.baidu.paddle.lite.demo.ocr"
minSdkVersion 15 minSdkVersion 23
targetSdkVersion 28 targetSdkVersion 29
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
...@@ -39,9 +39,8 @@ android { ...@@ -39,9 +39,8 @@ android {
dependencies { dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.android.support:design:28.0.0'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
......
...@@ -14,10 +14,10 @@ ...@@ -14,10 +14,10 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<!-- to test MiniActivity, change this to com.baidu.paddle.lite.demo.ocr.MiniActivity -->
<activity android:name="com.baidu.paddle.lite.demo.ocr.MainActivity"> <activity android:name="com.baidu.paddle.lite.demo.ocr.MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
android:label="Settings"> android:label="Settings">
</activity> </activity>
<provider <provider
android:name="android.support.v4.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="com.baidu.paddle.lite.demo.ocr.fileprovider" android:authorities="com.baidu.paddle.lite.demo.ocr.fileprovider"
android:exported="false" android:exported="false"
android:grantUriPermissions="true"> android:grantUriPermissions="true">
......
...@@ -30,7 +30,7 @@ Java_com_baidu_paddle_lite_demo_ocr_OCRPredictorNative_init(JNIEnv *env, jobject ...@@ -30,7 +30,7 @@ Java_com_baidu_paddle_lite_demo_ocr_OCRPredictorNative_init(JNIEnv *env, jobject
} }
/** /**
* "LITE_POWER_HIGH" 转为 paddle::lite_api::LITE_POWER_HIGH * "LITE_POWER_HIGH" convert to paddle::lite_api::LITE_POWER_HIGH
* @param cpu_mode * @param cpu_mode
* @return * @return
*/ */
......
...@@ -37,7 +37,7 @@ int OCR_PPredictor::init_from_file(const std::string &det_model_path, const std: ...@@ -37,7 +37,7 @@ int OCR_PPredictor::init_from_file(const std::string &det_model_path, const std:
return RETURN_OK; return RETURN_OK;
} }
/** /**
* 调试用,保存第一步的框选结果 * for debug use, show result of First Step
* @param filter_boxes * @param filter_boxes
* @param boxes * @param boxes
* @param srcimg * @param srcimg
......
...@@ -12,26 +12,26 @@ ...@@ -12,26 +12,26 @@
namespace ppredictor { namespace ppredictor {
/** /**
* 配置 * Config
*/ */
struct OCR_Config { struct OCR_Config {
int thread_num = 4; // 线程数 int thread_num = 4; // Thread num
paddle::lite_api::PowerMode mode = paddle::lite_api::LITE_POWER_HIGH; // PaddleLite Mode paddle::lite_api::PowerMode mode = paddle::lite_api::LITE_POWER_HIGH; // PaddleLite Mode
}; };
/** /**
* 一个四边形内图片的推理结果, * PolyGone Result
*/ */
struct OCRPredictResult { struct OCRPredictResult {
std::vector<int> word_index; // std::vector<int> word_index;
std::vector<std::vector<int>> points; std::vector<std::vector<int>> points;
float score; float score;
}; };
/** /**
* OCR 一共有2个模型进行推理, * OCR there are 2 models
* 1. 使用第一个模型(det),框选出多个四边形 * 1. First model(det),select polygones to show where are the texts
* 2. 从原图从抠出这些多边形,使用第二个模型(rec),获取文本 * 2. crop from the origin images, use these polygones to infer
*/ */
class OCR_PPredictor : public PPredictor_Interface { class OCR_PPredictor : public PPredictor_Interface {
public: public:
...@@ -50,7 +50,7 @@ public: ...@@ -50,7 +50,7 @@ public:
int init(const std::string &det_model_content, const std::string &rec_model_content); int init(const std::string &det_model_content, const std::string &rec_model_content);
int init_from_file(const std::string &det_model_path, const std::string &rec_model_path); int init_from_file(const std::string &det_model_path, const std::string &rec_model_path);
/** /**
* 返回OCR结果 * Return OCR result
* @param dims * @param dims
* @param input_data * @param input_data
* @param input_len * @param input_len
...@@ -69,7 +69,7 @@ public: ...@@ -69,7 +69,7 @@ public:
private: private:
/** /**
* 从第一个模型的结果中计算有文字的四边形 * calcul Polygone from the result image of first model
* @param pred * @param pred
* @param output_height * @param output_height
* @param output_width * @param output_width
...@@ -81,7 +81,7 @@ private: ...@@ -81,7 +81,7 @@ private:
const cv::Mat &origin); const cv::Mat &origin);
/** /**
* 第二个模型的推理 * infer for second model
* *
* @param boxes * @param boxes
* @param origin * @param origin
...@@ -91,14 +91,14 @@ private: ...@@ -91,14 +91,14 @@ private:
infer_rec(const std::vector<std::vector<std::vector<int>>> &boxes, const cv::Mat &origin); infer_rec(const std::vector<std::vector<std::vector<int>>> &boxes, const cv::Mat &origin);
/** /**
* 第二个模型提取文字的后处理 * Postprocess or sencod model to extract text
* @param res * @param res
* @return * @return
*/ */
std::vector<int> postprocess_rec_word_index(const PredictorOutput &res); std::vector<int> postprocess_rec_word_index(const PredictorOutput &res);
/** /**
* 计算第二个模型的文字的置信度 * calculate confidence of second model text result
* @param res * @param res
* @return * @return
*/ */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
namespace ppredictor { namespace ppredictor {
/** /**
* PaddleLite Preditor 通用接口 * PaddleLite Preditor Common Interface
*/ */
class PPredictor_Interface { class PPredictor_Interface {
public: public:
...@@ -21,7 +21,7 @@ public: ...@@ -21,7 +21,7 @@ public:
}; };
/** /**
* 通用推理 * Common Predictor
*/ */
class PPredictor : public PPredictor_Interface { class PPredictor : public PPredictor_Interface {
public: public:
...@@ -33,9 +33,9 @@ public: ...@@ -33,9 +33,9 @@ public:
} }
/** /**
* 初始化paddlitelite的opt模型,nb格式,与init_paddle二选一 * init paddlitelite opt model,nb format ,or use ini_paddle
* @param model_content * @param model_content
* @return 0 目前是固定值0, 之后其他值表示失败 * @return 0
*/ */
virtual int init_nb(const std::string &model_content); virtual int init_nb(const std::string &model_content);
......
...@@ -21,10 +21,10 @@ public: ...@@ -21,10 +21,10 @@ public:
const std::vector<std::vector<uint64_t>> get_lod() const; const std::vector<std::vector<uint64_t>> get_lod() const;
const std::vector<int64_t> get_shape() const; const std::vector<int64_t> get_shape() const;
std::vector<float> data; // 通常是float返回,与下面的data_int二选一 std::vector<float> data; // return float, or use data_int
std::vector<int> data_int; // 少数层是int返回,与 data二选一 std::vector<int> data_int; // several layers return int ,or use data
std::vector<int64_t> shape; // PaddleLite输出层的shape std::vector<int64_t> shape; // PaddleLite output shape
std::vector<std::vector<uint64_t>> lod; // PaddleLite输出层的lod std::vector<std::vector<uint64_t>> lod; // PaddleLite output lod
private: private:
std::unique_ptr<const paddle::lite_api::Tensor> _tensor; std::unique_ptr<const paddle::lite_api::Tensor> _tensor;
......
...@@ -19,15 +19,16 @@ package com.baidu.paddle.lite.demo.ocr; ...@@ -19,15 +19,16 @@ package com.baidu.paddle.lite.demo.ocr;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
/** /**
* A {@link PreferenceActivity} which implements and proxies the necessary calls * A {@link PreferenceActivity} which implements and proxies the necessary calls
* to be used with AppCompat. * to be used with AppCompat.
......
...@@ -19,11 +19,6 @@ import android.os.HandlerThread; ...@@ -19,11 +19,6 @@ import android.os.HandlerThread;
import android.os.Message; import android.os.Message;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
...@@ -33,6 +28,12 @@ import android.widget.ImageView; ...@@ -33,6 +28,12 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
......
package com.baidu.paddle.lite.demo.ocr;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.io.InputStream;
public class MiniActivity extends AppCompatActivity {
public static final int REQUEST_LOAD_MODEL = 0;
public static final int REQUEST_RUN_MODEL = 1;
public static final int REQUEST_UNLOAD_MODEL = 2;
public static final int RESPONSE_LOAD_MODEL_SUCCESSED = 0;
public static final int RESPONSE_LOAD_MODEL_FAILED = 1;
public static final int RESPONSE_RUN_MODEL_SUCCESSED = 2;
public static final int RESPONSE_RUN_MODEL_FAILED = 3;
private static final String TAG = "MiniActivity";
protected Handler receiver = null; // Receive messages from worker thread
protected Handler sender = null; // Send command to worker thread
protected HandlerThread worker = null; // Worker thread to load&run model
protected volatile Predictor predictor = null;
private String assetModelDirPath = "models/ocr_v1_for_cpu";
private String assetlabelFilePath = "labels/ppocr_keys_v1.txt";
private Button button;
private ImageView imageView; // image result
private TextView textView; // text result
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mini);
Log.i(TAG, "SHOW in Logcat");
// Prepare the worker thread for mode loading and inference
worker = new HandlerThread("Predictor Worker");
worker.start();
sender = new Handler(worker.getLooper()) {
public void handleMessage(Message msg) {
switch (msg.what) {
case REQUEST_LOAD_MODEL:
// Load model and reload test image
if (!onLoadModel()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MiniActivity.this, "Load model failed!", Toast.LENGTH_SHORT).show();
}
});
}
break;
case REQUEST_RUN_MODEL:
// Run model if model is loaded
final boolean isSuccessed = onRunModel();
runOnUiThread(new Runnable() {
@Override
public void run() {
if (isSuccessed){
onRunModelSuccessed();
}else{
Toast.makeText(MiniActivity.this, "Run model failed!", Toast.LENGTH_SHORT).show();
}
}
});
break;
}
}
};
sender.sendEmptyMessage(REQUEST_LOAD_MODEL); // corresponding to REQUEST_LOAD_MODEL, to call onLoadModel()
imageView = findViewById(R.id.imageView);
textView = findViewById(R.id.sample_text);
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sender.sendEmptyMessage(REQUEST_RUN_MODEL);
}
});
}
@Override
protected void onDestroy() {
onUnloadModel();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
worker.quitSafely();
} else {
worker.quit();
}
super.onDestroy();
}
/**
* call in onCreate, model init
*
* @return
*/
private boolean onLoadModel() {
if (predictor == null) {
predictor = new Predictor();
}
return predictor.init(this, assetModelDirPath, assetlabelFilePath);
}
/**
* init engine
* call in onCreate
*
* @return
*/
private boolean onRunModel() {
try {
String assetImagePath = "images/5.jpg";
InputStream imageStream = getAssets().open(assetImagePath);
Bitmap image = BitmapFactory.decodeStream(imageStream);
// Input is Bitmap
predictor.setInputImage(image);
return predictor.isLoaded() && predictor.runModel();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
private void onRunModelSuccessed() {
Log.i(TAG, "onRunModelSuccessed");
textView.setText(predictor.outputResult);
imageView.setImageBitmap(predictor.outputImage);
}
private void onUnloadModel() {
if (predictor != null) {
predictor.releaseModel();
}
}
}
...@@ -38,7 +38,7 @@ public class Predictor { ...@@ -38,7 +38,7 @@ public class Predictor {
protected float scoreThreshold = 0.1f; protected float scoreThreshold = 0.1f;
protected Bitmap inputImage = null; protected Bitmap inputImage = null;
protected Bitmap outputImage = null; protected Bitmap outputImage = null;
protected String outputResult = ""; protected volatile String outputResult = "";
protected float preprocessTime = 0; protected float preprocessTime = 0;
protected float postprocessTime = 0; protected float postprocessTime = 0;
...@@ -46,6 +46,16 @@ public class Predictor { ...@@ -46,6 +46,16 @@ public class Predictor {
public Predictor() { public Predictor() {
} }
public boolean init(Context appCtx, String modelPath, String labelPath) {
isLoaded = loadModel(appCtx, modelPath, cpuThreadNum, cpuPowerMode);
if (!isLoaded) {
return false;
}
isLoaded = loadLabel(appCtx, labelPath);
return isLoaded;
}
public boolean init(Context appCtx, String modelPath, String labelPath, int cpuThreadNum, String cpuPowerMode, public boolean init(Context appCtx, String modelPath, String labelPath, int cpuThreadNum, String cpuPowerMode,
String inputColorFormat, String inputColorFormat,
long[] inputShape, float[] inputMean, long[] inputShape, float[] inputMean,
...@@ -76,11 +86,7 @@ public class Predictor { ...@@ -76,11 +86,7 @@ public class Predictor {
Log.e(TAG, "Only BGR color format is supported."); Log.e(TAG, "Only BGR color format is supported.");
return false; return false;
} }
isLoaded = loadModel(appCtx, modelPath, cpuThreadNum, cpuPowerMode); boolean isLoaded = init(appCtx, modelPath, labelPath);
if (!isLoaded) {
return false;
}
isLoaded = loadLabel(appCtx, labelPath);
if (!isLoaded) { if (!isLoaded) {
return false; return false;
} }
...@@ -222,7 +228,7 @@ public class Predictor { ...@@ -222,7 +228,7 @@ public class Predictor {
for (int i = 0; i < warmupIterNum; i++) { for (int i = 0; i < warmupIterNum; i++) {
paddlePredictor.runImage(inputData, width, height, channels, inputImage); paddlePredictor.runImage(inputData, width, height, channels, inputImage);
} }
warmupIterNum = 0; // 之后不要再warm了 warmupIterNum = 0; // do not need warm
// Run inference // Run inference
start = new Date(); start = new Date();
ArrayList<OcrResultModel> results = paddlePredictor.runImage(inputData, width, height, channels, inputImage); ArrayList<OcrResultModel> results = paddlePredictor.runImage(inputData, width, height, channels, inputImage);
...@@ -317,7 +323,7 @@ public class Predictor { ...@@ -317,7 +323,7 @@ public class Predictor {
for (Point p : result.getPoints()) { for (Point p : result.getPoints()) {
sb.append("(").append(p.x).append(",").append(p.y).append(") "); sb.append("(").append(p.x).append(",").append(p.y).append(") ");
} }
Log.i(TAG, sb.toString()); Log.i(TAG, sb.toString()); // show LOG in Logcat panel
outputResultSb.append(i + 1).append(": ").append(result.getLabel()).append("\n"); outputResultSb.append(i + 1).append(": ").append(result.getLabel()).append("\n");
} }
outputResult = outputResultSb.toString(); outputResult = outputResultSb.toString();
......
...@@ -5,7 +5,8 @@ import android.os.Bundle; ...@@ -5,7 +5,8 @@ import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.support.v7.app.ActionBar;
import androidx.appcompat.app.ActionBar;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
...@@ -96,4 +96,4 @@ ...@@ -96,4 +96,4 @@
</RelativeLayout> </RelativeLayout>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- for MiniActivity Use Only -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintLeft_toRightOf="parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/sample_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView"
android:scrollbars="vertical"
/>
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:paddingBottom="20dp"
app:layout_constraintBottom_toTopOf="@id/imageView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:layout_editor_absoluteX="161dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册