• Android 中集成 TensorFlow Lite图片识别


    c5494e0d0040a885c764744a2cc414f6.png

    在上图通过手机的相机拍摄到的物体识别出具体的名称,这个需要通过TensorFlow 训练的模型引用到项目中;以下就是详细地集成 TensorFlow步骤,请按照以下步骤进行操作:

    1. 在项目的根目录下的 build.gradle 文件中添加 TensorFlow 的 Maven 仓库。在 repositories 部分添加以下行:

    1. allprojects {
    2. repositories {
    3. // 其他仓库...
    4. maven {
    5. url 'https://google.bintray.com/tensorflow'
    6. }
    7. }
    8. }
    1. 在应用的 build.gradle 文件中添加 TensorFlow Lite 的依赖。在 dependencies 部分添加以下行:

    implementation 'org.tensorflow:tensorflow-lite:2.5.0'
    1. 将 TensorFlow Lite 模型文件添加到你的 Android 项目中。将模型文件(.tflite)复制到 app/src/main/assets 目录下。如果 assets 目录不存在,可以手动创建。

    2. 创建一个 TFLiteObjectDetectionAPIModel类,用于加载和运行 TensorFlow Lite 模型。以下是一个示例代码:

    import org.tensorflow.lite.Interpreter;
    1. public class TFLiteObjectDetectionAPIModel implements Classifier {
    2. private static final Logger LOGGER = new Logger();
    3. // Only return this many results.
    4. private static final int NUM_DETECTIONS = 10;
    5. // Float model
    6. private static final float IMAGE_MEAN = 128.0f;
    7. private static final float IMAGE_STD = 128.0f;
    8. // Number of threads in the java app
    9. private static final int NUM_THREADS = 4;
    10. private boolean isModelQuantized;
    11. // Config values.
    12. private int inputSize;
    13. // Pre-allocated buffers.
    14. private Vector labels = new Vector();
    15. private int[] intValues;
    16. // outputLocations: array of shape [Batchsize, NUM_DETECTIONS,4]
    17. // contains the location of detected boxes
    18. private float[][][] outputLocations;
    19. // outputClasses: array of shape [Batchsize, NUM_DETECTIONS]
    20. // contains the classes of detected boxes
    21. private float[][] outputClasses;
    22. // outputScores: array of shape [Batchsize, NUM_DETECTIONS]
    23. // contains the scores of detected boxes
    24. private float[][] outputScores;
    25. // numDetections: array of shape [Batchsize]
    26. // contains the number of detected boxes
    27. private float[] numDetections;
    28. private ByteBuffer imgData;
    29. private Interpreter tfLite;
    30. private TFLiteObjectDetectionAPIModel() {}
    31. /** Memory-map the model file in Assets. */
    32. private static MappedByteBuffer loadModelFile(AssetManager assets, String modelFilename)
    33. throws IOException {
    34. AssetFileDescriptor fileDescriptor = assets.openFd(modelFilename);
    35. FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
    36. FileChannel fileChannel = inputStream.getChannel();
    37. long startOffset = fileDescriptor.getStartOffset();
    38. long declaredLength = fileDescriptor.getDeclaredLength();
    39. return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
    40. }
    41. /**
    42. * Initializes a native TensorFlow session for classifying images.
    43. *
    44. * @param assetManager The asset manager to be used to load assets.
    45. * @param modelFilename The filepath of the model GraphDef protocol buffer.
    46. * @param labelFilename The filepath of label file for classes.
    47. * @param inputSize The size of image input
    48. * @param isQuantized Boolean representing model is quantized or not
    49. */
    50. public static Classifier create(
    51. final AssetManager assetManager,
    52. final String modelFilename,
    53. final String labelFilename,
    54. final int inputSize,
    55. final boolean isQuantized)
    56. throws IOException {
    57. final TFLiteObjectDetectionAPIModel d = new TFLiteObjectDetectionAPIModel();
    58. InputStream labelsInput = null;
    59. String actualFilename = labelFilename.split("file:///android_asset/")[1];
    60. labelsInput = assetManager.open(actualFilename);
    61. BufferedReader br = null;
    62. br = new BufferedReader(new InputStreamReader(labelsInput));
    63. String line;
    64. while ((line = br.readLine()) != null) {
    65. LOGGER.w(line);
    66. d.labels.add(line);
    67. }
    68. br.close();
    69. d.inputSize = inputSize;
    70. try {
    71. d.tfLite = new Interpreter(loadModelFile(assetManager, modelFilename));
    72. } catch (Exception e) {
    73. throw new RuntimeException(e);
    74. }
    75. d.isModelQuantized = isQuantized;
    76. // Pre-allocate buffers.
    77. int numBytesPerChannel;
    78. if (isQuantized) {
    79. numBytesPerChannel = 1; // Quantized
    80. } else {
    81. numBytesPerChannel = 4; // Floating point
    82. }
    83. d.imgData = ByteBuffer.allocateDirect(1 * d.inputSize * d.inputSize * 3 * numBytesPerChannel);
    84. d.imgData.order(ByteOrder.nativeOrder());
    85. d.intValues = new int[d.inputSize * d.inputSize];
    86. d.tfLite.setNumThreads(NUM_THREADS);
    87. d.outputLocations = new float[1][NUM_DETECTIONS][4];
    88. d.outputClasses = new float[1][NUM_DETECTIONS];
    89. d.outputScores = new float[1][NUM_DETECTIONS];
    90. d.numDetections = new float[1];
    91. return d;
    92. }
    93. @Override
    94. public List recognizeImage(final Bitmap bitmap) {
    95. // Log this method so that it can be analyzed with systrace.
    96. Trace.beginSection("recognizeImage");
    97. Trace.beginSection("preprocessBitmap");
    98. // Preprocess the image data from 0-255 int to normalized float based
    99. // on the provided parameters.
    100. bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
    101. imgData.rewind();
    102. for (int i = 0; i < inputSize; ++i) {
    103. for (int j = 0; j < inputSize; ++j) {
    104. int pixelValue = intValues[i * inputSize + j];
    105. if (isModelQuantized) {
    106. // Quantized model
    107. imgData.put((byte) ((pixelValue >> 16) & 0xFF));
    108. imgData.put((byte) ((pixelValue >> 8) & 0xFF));
    109. imgData.put((byte) (pixelValue & 0xFF));
    110. } else { // Float model
    111. imgData.putFloat((((pixelValue >> 16) & 0xFF) - IMAGE_MEAN) / IMAGE_STD);
    112. imgData.putFloat((((pixelValue >> 8) & 0xFF) - IMAGE_MEAN) / IMAGE_STD);
    113. imgData.putFloat(((pixelValue & 0xFF) - IMAGE_MEAN) / IMAGE_STD);
    114. }
    115. }
    116. }
    117. Trace.endSection(); // preprocessBitmap
    118. // Copy the input data into TensorFlow.
    119. Trace.beginSection("feed");
    120. outputLocations = new float[1][NUM_DETECTIONS][4];
    121. outputClasses = new float[1][NUM_DETECTIONS];
    122. outputScores = new float[1][NUM_DETECTIONS];
    123. numDetections = new float[1];
    124. Object[] inputArray = {imgData};
    125. Map outputMap = new HashMap<>();
    126. outputMap.put(0, outputLocations);
    127. outputMap.put(1, outputClasses);
    128. outputMap.put(2, outputScores);
    129. outputMap.put(3, numDetections);
    130. Trace.endSection();
    131. // Run the inference call.
    132. Trace.beginSection("run");
    133. tfLite.runForMultipleInputsOutputs(inputArray, outputMap);
    134. Trace.endSection();
    135. // Show the best detections.
    136. // after scaling them back to the input size.
    137. final ArrayList recognitions = new ArrayList<>(NUM_DETECTIONS);
    138. for (int i = 0; i < NUM_DETECTIONS; ++i) {
    139. final RectF detection =
    140. new RectF(
    141. outputLocations[0][i][1] * inputSize,
    142. outputLocations[0][i][0] * inputSize,
    143. outputLocations[0][i][3] * inputSize,
    144. outputLocations[0][i][2] * inputSize);
    145. // SSD Mobilenet V1 Model assumes class 0 is background class
    146. // in label file and class labels start from 1 to number_of_classes+1,
    147. // while outputClasses correspond to class index from 0 to number_of_classes
    148. int labelOffset = 1;
    149. recognitions.add(
    150. new Recognition(
    151. "" + i,
    152. labels.get((int) outputClasses[0][i] + labelOffset),
    153. outputScores[0][i],
    154. detection));
    155. }
    156. Trace.endSection(); // "recognizeImage"
    157. return recognitions;
    158. }
    159. @Override
    160. public void enableStatLogging(final boolean logStats) {}
    161. @Override
    162. public String getStatString() {
    163. return "";
    164. }
    165. @Override
    166. public void close() {}
    167. public void setNumThreads(int num_threads) {
    168. if (tfLite != null) tfLite.setNumThreads(num_threads);
    169. }
    170. @Override
    171. public void setUseNNAPI(boolean isChecked) {
    172. if (tfLite != null) tfLite.setUseNNAPI(isChecked);
    173. }
    174. }

    确保替换 modelPath 参数为你的模型文件在 assets 目录中的路径。

    1. 在你的应用程序中使用 TFLiteObjectDetectionAPIModel 类进行推理。以下是一个简单的示例:

    1. @Override
    2. public void onPreviewSizeChosen(final Size size, final int rotation) {
    3. final float textSizePx =
    4. TypedValue.applyDimension(
    5. TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, getResources().getDisplayMetrics());
    6. borderedText = new BorderedText(textSizePx);
    7. borderedText.setTypeface(Typeface.MONOSPACE);
    8. tracker = new MultiBoxTracker(this);
    9. int cropSize = TF_OD_API_INPUT_SIZE;
    10. try {
    11. detector =
    12. TFLiteObjectDetectionAPIModel.create(
    13. getAssets(),
    14. TF_OD_API_MODEL_FILE,
    15. TF_OD_API_LABELS_FILE,
    16. TF_OD_API_INPUT_SIZE,
    17. TF_OD_API_IS_QUANTIZED);
    18. cropSize = TF_OD_API_INPUT_SIZE;
    19. } catch (final IOException e) {
    20. e.printStackTrace();
    21. LOGGER.e(e, "Exception initializing classifier!");
    22. Toast toast =
    23. Toast.makeText(
    24. getApplicationContext(), "Classifier could not be initialized", Toast.LENGTH_SHORT);
    25. toast.show();
    26. finish();
    27. }
    1. // 解析输出数据
    2. // ...

    根据你的模型和任务,你可能需要根据模型的规范和文档来解析输出数据。

    cc8d5bde50aea06a58a14a2b5b0820b9.png

    输出解析文本数据

    需要项目源码私聊

  • 相关阅读:
    低代码平台
    静态HTML CSS个人网页作业源代码 (人物介绍)
    pytorch中nn.DataParallel多次使用
    python 装饰器@
    基于51单片机的倒车雷达声光报警系统proteus仿真原理图PCB
    关于SQL中json类型字段优化查询
    基于智能分析网关与EasyCVR技术的考场智能化视频监管方案
    适配器模式 ( Adapter Pattern )(6)
    systemverilog中输入输出系统任务和函数(一)——显示相关的任务
    LeetCode 周赛上分之旅 #33 摩尔投票派上用场
  • 原文地址:https://blog.csdn.net/qxf865618770/article/details/132867726