当前位置:   article > 正文

基于PaddleOCR文字识别Android端打包成aar包_paddleocr android

paddleocr android

目的

官方其实已经提供了详细的端侧部署,如果按照官方步骤无法正常编译的,可在评论区留言,我将详细编译步骤也发布出来,在这里我主要讲一下如何将官方的提供的代码转成可方便移植的module包,便于方便引入各个项目中。

官方2.5编译教程:PaddleOCR/readme.md at release/2.5 · PaddlePaddle/PaddleOCR (github.com)

开始!!!

官方包结构对比module包结构,可以发现后面结构清晰明了

   

1、首先将官方包下所有文件拷贝到新建的Module包下

2、删除以下文件

    

 3、新建单例模式启动OCRPredictor类和接口OnImagePredictorListener类,代码如下:

  1. package com.yangy.ocr;
  2. import android.annotation.SuppressLint;
  3. import android.content.Context;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapFactory;
  6. import android.media.ExifInterface;
  7. import android.os.Binder;
  8. import android.os.Build;
  9. import android.os.Bundle;
  10. import android.os.Handler;
  11. import android.os.HandlerThread;
  12. import android.os.Message;
  13. import android.text.TextUtils;
  14. import android.util.Base64;
  15. import android.util.Log;
  16. import java.io.IOException;
  17. public class OCRPredictor {
  18. public final int REQUEST_LOAD_MODEL = 0;
  19. public final int REQUEST_RUN_MODEL = 1;
  20. public final int RESPONSE_LOAD_MODEL_SUCCESSED = 0;
  21. public final int RESPONSE_LOAD_MODEL_FAILED = 1;
  22. public final int RESPONSE_RUN_MODEL_SUCCESSED = 2;
  23. public final int RESPONSE_RUN_MODEL_FAILED = 3;
  24. public final int RESPONSE_RUN_MODEL_NO_FILE = 4;
  25. // private final String assetModelDirPath = "models/bank";
  26. // private final String assetlabelFilePath = "labels/ppocr_keys_bank.txt";
  27. private final String assetModelDirPath = "models/ocr";
  28. private final String assetlabelFilePath = "labels/ppocr_keys_v1.txt";
  29. protected Handler sender = null; // Send command to worker thread
  30. protected HandlerThread worker = null; // Worker thread to load&run model
  31. protected volatile Predictor predictor = null;
  32. private OnImagePredictorListener listener;
  33. @SuppressLint("StaticFieldLeak")
  34. private static OCRPredictor ocrPredictor;
  35. private Context context;
  36. public static OCRPredictor getInstance(Context context) {
  37. if (ocrPredictor == null) {
  38. ocrPredictor = new OCRPredictor(context);
  39. }
  40. return ocrPredictor;
  41. }
  42. public OCRPredictor(Context context) {
  43. this.context = context;
  44. init();
  45. }
  46. /**
  47. *
  48. */
  49. private void init() {
  50. worker = new HandlerThread("Predictor Worker");
  51. worker.start();
  52. sender = new Handler(worker.getLooper()) {
  53. public void handleMessage(Message msg) {
  54. switch (msg.what) {
  55. case REQUEST_LOAD_MODEL:
  56. // Load model and reload test image
  57. if (!onLoadModel(context)) {
  58. predictor = null;
  59. Log.d("OCR", "加载模型失败!");
  60. } else {
  61. Log.d("OCR", "加载模型成功!");
  62. }
  63. break;
  64. case REQUEST_RUN_MODEL:
  65. Bundle bundle = msg.getData();
  66. if (predictor == null) {
  67. receiver.sendEmptyMessage(RESPONSE_LOAD_MODEL_FAILED);
  68. } else {
  69. // Run model if model is loaded
  70. if (!TextUtils.isEmpty(bundle.getString("imagePath"))) {
  71. if (!onRunModel(bundle.getString("imagePath"))) {
  72. receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_FAILED);
  73. } else {
  74. receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_SUCCESSED);
  75. }
  76. } else {
  77. ImageBinder imageBinder = (ImageBinder) bundle.getBinder("bitmap");
  78. if (imageBinder != null) {
  79. Bitmap bitmap = imageBinder.getBitmap();
  80. if (!onRunModel(bitmap)) {
  81. receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_FAILED);
  82. } else {
  83. receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_SUCCESSED);
  84. }
  85. } else {
  86. StringBinder stringBinder = (StringBinder) bundle.getBinder("base64");
  87. if (stringBinder != null) {
  88. String str = stringBinder.getStr();
  89. if (!onRunModelBase64(str)) {
  90. receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_FAILED);
  91. } else {
  92. receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_SUCCESSED);
  93. }
  94. } else {
  95. receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_NO_FILE);
  96. }
  97. }
  98. }
  99. }
  100. break;
  101. }
  102. }
  103. };
  104. sender.sendEmptyMessage(REQUEST_LOAD_MODEL);
  105. }
  106. private Handler receiver = new Handler() {
  107. @Override
  108. public void handleMessage(Message msg) {
  109. switch (msg.what) {
  110. // case RESPONSE_LOAD_MODEL_SUCCESSED:
  111. // sender.sendEmptyMessage(REQUEST_RUN_MODEL);
  112. // break;
  113. case RESPONSE_LOAD_MODEL_FAILED:
  114. listener.failure(0, "加载模型失败!");
  115. break;
  116. case RESPONSE_RUN_MODEL_SUCCESSED:
  117. listener.success(predictor.outputResult, predictor.outputResultList, predictor.outputImage);
  118. break;
  119. case RESPONSE_RUN_MODEL_FAILED:
  120. listener.failure(1, "运行模型失败!");
  121. break;
  122. case RESPONSE_RUN_MODEL_NO_FILE:
  123. listener.failure(2, "运行模型失败,请传入待识别图片!");
  124. break;
  125. default:
  126. break;
  127. }
  128. }
  129. };
  130. public void predictor(final String imagePath, final OnImagePredictorListener listener) {
  131. this.listener = listener;
  132. Message message = new Message();
  133. message.what = REQUEST_RUN_MODEL;
  134. Bundle bundle = new Bundle();
  135. bundle.putString("imagePath", imagePath);
  136. message.setData(bundle);
  137. sender.sendMessage(message);
  138. }
  139. public void predictorBitMap(final Bitmap bitmap, final OnImagePredictorListener listener) {
  140. this.listener = listener;
  141. Message message = new Message();
  142. message.what = REQUEST_RUN_MODEL;
  143. Bundle bundle = new Bundle();
  144. bundle.putBinder("bitmap", new ImageBinder(bitmap));
  145. message.setData(bundle);
  146. sender.sendMessage(message);
  147. }
  148. public void predictorBase64(final String base64, final OnImagePredictorListener listener) {
  149. this.listener = listener;
  150. Message message = new Message();
  151. message.what = REQUEST_RUN_MODEL;
  152. Bundle bundle = new Bundle();
  153. bundle.putBinder("base64", new StringBinder(base64));
  154. message.setData(bundle);
  155. sender.sendMessage(message);
  156. }
  157. private static class ImageBinder extends Binder {
  158. private Bitmap bitmap;
  159. public ImageBinder(Bitmap bitmap) {
  160. this.bitmap = bitmap;
  161. }
  162. Bitmap getBitmap() {
  163. return bitmap;
  164. }
  165. }
  166. private static class StringBinder extends Binder {
  167. private String str;
  168. public StringBinder(String str) {
  169. this.str = str;
  170. }
  171. String getStr() {
  172. return str;
  173. }
  174. }
  175. /**
  176. * call in onCreate, model init
  177. *
  178. * @return
  179. */
  180. private boolean onLoadModel(Context context) {
  181. if (predictor == null) {
  182. predictor = new Predictor();
  183. }
  184. return predictor.init(context, assetModelDirPath, assetlabelFilePath);
  185. }
  186. private boolean onRunModel(String imagePath) {
  187. try {
  188. ExifInterface exif = null;
  189. exif = new ExifInterface(imagePath);
  190. int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
  191. ExifInterface.ORIENTATION_UNDEFINED);
  192. Log.i("OCR", "rotation " + orientation);
  193. Bitmap image = BitmapFactory.decodeFile(imagePath);
  194. image = Utils.rotateBitmap(image, orientation);
  195. predictor.setInputImage(image);
  196. return predictor.isLoaded() && predictor.runModel();
  197. } catch (IOException e) {
  198. e.printStackTrace();
  199. return false;
  200. }
  201. }
  202. private boolean onRunModel(Bitmap image) {
  203. try {
  204. predictor.setInputImage(image);
  205. return predictor.isLoaded() && predictor.runModel();
  206. } catch (Exception e) {
  207. e.printStackTrace();
  208. return false;
  209. }
  210. }
  211. private boolean onRunModelBase64(String base64) {
  212. try {
  213. byte[] bitmapByte = Base64.decode(base64, Base64.DEFAULT);
  214. Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapByte, 0, bitmapByte.length);
  215. predictor.setInputImage(bitmap);
  216. return predictor.isLoaded() && predictor.runModel();
  217. } catch (Exception e) {
  218. e.printStackTrace();
  219. return false;
  220. }
  221. }
  222. /**
  223. * 卸载模型
  224. */
  225. private void onUnloadModel() {
  226. if (predictor != null) {
  227. predictor.releaseModel();
  228. predictor = null;
  229. }
  230. }
  231. /**
  232. * 退出线程
  233. */
  234. private void quit() {
  235. if (worker != null) {
  236. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
  237. worker.quitSafely();
  238. } else {
  239. worker.quit();
  240. }
  241. }
  242. }
  243. /**
  244. * 销毁
  245. */
  246. public void onDestroy() {
  247. onUnloadModel();
  248. quit();
  249. ocrPredictor = null;
  250. }
  251. }
  1. package com.yangy.ocr;
  2. import android.graphics.Bitmap;
  3. import java.util.ArrayList;
  4. public abstract class OnImagePredictorListener {
  5. public abstract void success(String result, ArrayList<OCRResultModel> list, Bitmap bitmap);
  6. public void failure(int code, String message) {
  7. }
  8. }

4、修改Predictor类,加入以下两行

 

 5、修改native.cpp文件,将官方的_com_baidu_paddle_lite_demo_ocr_替换成我们自己的包名,如_com_yangy_ocr_,如下截图:

 6、最后一步,删除Module包下build.gradle中下载PaddleLite、OpenCV包的代码,红框部分全部删除,我们不需要 ,PaddleLite和模型包需要自行编译

 7、使用方式,在主App下引入该Module包,短短几行代码就可实现

完毕!!!

这里发布一个自己打的包,引入aar包后,使用如上面最后一图:

1、minSdkVersion 21

2、支持arm64-v8a和armabi-v7a

下载地址

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/771295
推荐阅读
相关标签
  

闽ICP备14008679号