MindSpore部署图像分割示例程序
MindSpore部署圖像分割示例程序
本端側圖像分割Android示例程序使用Java實現,Java層主要通過Android Camera 2 API實現攝像頭獲取圖像幀,進行相應的圖像處理,之后調用Java API 完成模型推理。
此處詳細說明示例程序的Java層圖像處理及模型推理實現,Java層運用Android Camera 2 API實現開啟設備攝像頭以及圖像幀處理等功能,需讀者具備一定的Android開發基礎知識。
示例程序結構
app
├── src/main
│ ├── assets # 資源文件
| | └── deeplabv3.ms # 存放模型文件
│ |
│ ├── java # java層應用代碼
│ │ └── com.mindspore.imagesegmentation
│ │ ├── help # 圖像處理及MindSpore Java調用相關實現
│ │ │ └── ImageUtils # 圖像預處理
│ │ │ └── ModelTrackingResult # 推理數據后處理
│ │ │ └── TrackingMobile # 模型加載、構建計算圖和推理
│ │ └── BitmapUtils # 圖像處理
│ │ └── MainActivity # 交互主頁面
│ │ └── OnBackgroundImageListener # 獲取相冊圖像
│ │ └── StyleRecycleViewAdapter # 獲取相冊圖像
│ │
│ ├── res # 存放Android相關的資源文件
│ └── AndroidManifest.xml # Android配置文件
│
├── CMakeList.txt # cmake編譯入口文件
│
├── build.gradle # 其他Android配置文件
├── download.gradle # 工程依賴文件下載
└── …
配置MindSpore Lite依賴項
Android 調用MindSpore Java API時,需要相關庫文件支持。可通過MindSpore Lite源碼編譯生成mindspore-lite-{version}-minddata-{os}-{device}.tar.gz庫文件包并解壓縮(包含libmindspore-lite.so庫文件和相關頭文件),在本例中需使用生成帶圖像預處理模塊的編譯命令。
version:輸出件版本號,與所編譯的分支代碼對應的版本一致。
device:當前分為cpu(內置CPU算子)和gpu(內置CPU和GPU算子)。
os:輸出件應部署的操作系統。
本示例中,build過程由download.gradle文件自動下載MindSpore Lite 版本文件,并放置在app/src/main/cpp/目錄下。
若自動下載失敗,請手動下載相關庫文件,解壓并放在對應位置:
mindspore-lite-1.0.1-runtime-arm64-cpu.tar.gz 下載鏈接
在app的build.gradle文件中配置CMake編譯支持,以及arm64-v8a的編譯支持,如下所示:
android{
defaultConfig{
externalNativeBuild{
cmake{
arguments “-DANDROID_STL=c++_shared”
}
}
ndk{abiFilters 'arm64-v8a'}
}
}
在app/CMakeLists.txt文件中建立.so庫文件鏈接,如下所示。
============== Set MindSpore Dependencies. =============
include_directories(CMAKESOURCEDIR/src/main/cpp)includedirectories({CMAKE_SOURCE_DIR}/src/main/cpp) include_directories(CMAKES?OURCED?IR/src/main/cpp)included?irectories({CMAKE_SOURCE_DIR}/src/main/cpp/MINDSPORELITEVERSION/thirdparty/flatbuffers/include)includedirectories({MINDSPORELITE_VERSION}/third_party/flatbuffers/include) include_directories(MINDSPORELITEV?ERSION/thirdp?arty/flatbuffers/include)included?irectories({CMAKE_SOURCE_DIR}/src/main/cpp/MINDSPORELITEVERSION)includedirectories({MINDSPORELITE_VERSION}) include_directories(MINDSPORELITEV?ERSION)included?irectories({CMAKE_SOURCE_DIR}/src/main/cpp/MINDSPORELITEVERSION/include)includedirectories({MINDSPORELITE_VERSION}/include) include_directories(MINDSPORELITEV?ERSION/include)included?irectories({CMAKE_SOURCE_DIR}/src/main/cpp/MINDSPORELITEVERSION/include/ir/dtype)includedirectories({MINDSPORELITE_VERSION}/include/ir/dtype) include_directories(MINDSPORELITEV?ERSION/include/ir/dtype)included?irectories({CMAKE_SOURCE_DIR}/src/main/cpp/${MINDSPORELITE_VERSION}/include/schema)
add_library(mindspore-lite SHARED IMPORTED )
add_library(minddata-lite SHARED IMPORTED )
set_target_properties(mindspore-lite PROPERTIES IMPORTED_LOCATION
CMAKESOURCEDIR/src/main/cpp/{CMAKE_SOURCE_DIR}/src/main/cpp/CMAKES?OURCED?IR/src/main/cpp/{MINDSPORELITE_VERSION}/lib/libmindspore-lite.so)
set_target_properties(minddata-lite PROPERTIES IMPORTED_LOCATION
CMAKESOURCEDIR/src/main/cpp/{CMAKE_SOURCE_DIR}/src/main/cpp/CMAKES?OURCED?IR/src/main/cpp/{MINDSPORELITE_VERSION}/lib/libminddata-lite.so)
--------------- MindSpore Lite set End. --------------------
Link target library.
target_link_libraries(
…
# — mindspore —
minddata-lite
mindspore-lite
…
)
下載及部署模型文件
從MindSpore Model Hub中下載模型文件,本示例程序中使用的終端圖像分割模型文件為deeplabv3.ms,同樣通過download.gradle腳本在APP構建時自動下載,并放置在app/src/main/assets工程目錄下。
若下載失敗請手動下載模型文件,deeplabv3.ms 下載鏈接。
編寫端側推理代碼
調用MindSpore Lite Java API實現端測推理。
推理代碼流程如下,完整代碼請參見src/java/TrackingMobile.java。
- 加載MindSpore Lite模型文件,構建上下文、會話以及用于推理的計算圖。
o 加載模型文件:創建并配置用于模型推理的上下文 - // Create context and load the .ms model named ‘IMAGESEGMENTATIONMODEL’
- model = new Model();
- if (!model.loadModel(Context, IMAGESEGMENTATIONMODEL)) {
- Log.e(TAG, “Load Model failed”);
- return;
}
o 創建會話
// Create and init config.
msConfig = new MSConfig();
if (!msConfig.init(DeviceType.DT_CPU, 2, CpuBindMode.MID_CPU)) {
Log.e(TAG, “Init context failed”);
return;
}
// Create the MindSpore lite session.
session = new LiteSession();
if (!session.init(msConfig)) {
Log.e(TAG, “Create session failed”);
msConfig.free();
return;
}
msConfig.free();
o 構建計算圖
if (!session.compileGraph(model)) {
Log.e(TAG, “Compile graph failed”);
model.freeBuffer();
return;
}
// Note: when use model.freeBuffer(), the model can not be compile graph again.
model.freeBuffer();
7. 將輸入圖片轉換為傳入MindSpore模型的Tensor格式。
8. List inputs = session.getInputs();
9. if (inputs.size() != 1) {
10. Log.e(TAG, “inputs.size() != 1”);
11. return null;
12. }
13.
14. // bitmap is the picture used to infer.
15. float resource_height = bitmap.getHeight();
16. float resource_weight = bitmap.getWidth();
17. ByteBuffer contentArray = bitmapToByteBuffer(bitmap, imageSize, imageSize, IMAGE_MEAN, IMAGE_STD);
18.
19. MSTensor inTensor = inputs.get(0);
inTensor.setData(contentArray);
20. 對輸入Tensor按照模型進行推理,獲取輸出Tensor,并進行后處理。
o 圖執行,端側推理。
21. // After the model and image tensor data is loaded, run inference.
22. if (!session.runGraph()) {
23. Log.e(TAG, “Run graph failed”);
24. return null;
}
o 獲取輸出數據。
// Get output tensor values, the model only outputs one tensor.
List tensorNames = session.getOutputTensorNames();
MSTensor output = session.getOutputByTensorName(tensorNames.front());
if (output == null) {
Log.e(TAG, "Can not find output " + tensorName);
return null;
}
o 輸出數據的后續處理。
// Show output as pictures.
float[] results = output.getFloatData();
ByteBuffer bytebuffer_results = floatArrayToByteArray(results);
Bitmap dstBitmap = convertBytebufferMaskToBitmap(bytebuffer_results, imageSize, imageSize, bitmap, dstBitmap, segmentColors);
dstBitmap = scaleBitmapAndKeepRatio(dstBitmap, (int) resource_height, (int) resource_weight);
25. 圖片處理及輸出數據后處理請參考如下代碼。
26. Bitmap scaleBitmapAndKeepRatio(Bitmap targetBmp, int reqHeightInPixels, int reqWidthInPixels) {
27. if (targetBmp.getHeight() == reqHeightInPixels && targetBmp.getWidth() == reqWidthInPixels) {
28. return targetBmp;
29. }
30.
31. Matrix matrix = new Matrix();
32. matrix.setRectToRect(new RectF(0f, 0f, targetBmp.getWidth(), targetBmp.getHeight()),
33. new RectF(0f, 0f, reqWidthInPixels, reqHeightInPixels), Matrix.ScaleToFit.FILL;
34.
35. return Bitmap.createBitmap(targetBmp, 0, 0, targetBmp.getWidth(), targetBmp.getHeight(), matrix, true);
36. }
37.
38. ByteBuffer bitmapToByteBuffer(Bitmap bitmapIn, int width, int height, float mean, float std) {
39. Bitmap bitmap = scaleBitmapAndKeepRatio(bitmapIn, width, height);
40. ByteBuffer inputImage = ByteBuffer.allocateDirect(1 * width * height * 3 * 4);
41. inputImage.order(ByteOrder.nativeOrder());
42. inputImage.rewind();
43. int[] intValues = new int[width * height];
44. bitmap.getPixels(intValues, 0, width, 0, 0, width, height);
45. int pixel = 0;
46. for (int y = 0; y < height; y++) {
47. for (int x = 0; x < width; x++) {
48. int value = intValues[pixel++];
49. inputImage.putFloat(((float) (value >> 16 & 255) - mean) / std);
50. inputImage.putFloat(((float) (value >> 8 & 255) - mean) / std);
51. inputImage.putFloat(((float) (value & 255) - mean) / std);
52. }
53. }
54. inputImage.rewind();
55. return inputImage;
56. }
57.
58. ByteBuffer floatArrayToByteArray(float[] floats) {
59. ByteBuffer buffer = ByteBuffer.allocate(4 * floats.length);
60. FloatBuffer floatBuffer = buffer.asFloatBuffer();
61. floatBuffer.put(floats);
62. return buffer;
63. }
64.
65. Bitmap convertBytebufferMaskToBitmap(ByteBuffer inputBuffer, int imageWidth, int imageHeight, Bitmap backgroundImage, int[] colors) {
66. Bitmap.Config conf = Bitmap.Config.ARGB_8888;
67. Bitmap dstBitmap = Bitmap.createBitmap(imageWidth, imageHeight, conf);
68. Bitmap scaledBackgroundImage = scaleBitmapAndKeepRatio(backgroundImage, imageWidth, imageHeight);
69. int[][] mSegmentBits = new int[imageWidth][imageHeight];
70. inputBuffer.rewind();
71. for (int y = 0; y < imageHeight; y++) {
72. for (int x = 0; x < imageWidth; x++) {
73. float maxVal = 0f;
74. mSegmentBits[x][y] = 0;
75. // NUM_CLASSES is the number of labels, the value here is 21.
76. for (int i = 0; i < NUM_CLASSES; i++) {
77. float value = inputBuffer.getFloat((y * imageWidth * NUM_CLASSES + x * NUM_CLASSES + i) * 4);
78. if (i == 0 || value > maxVal) {
79. maxVal = value;
80. // Check whether a pixel belongs to a person whose label is 15.
81. if (i == 15) {
82. mSegmentBits[x][y] = i;
83. } else {
84. mSegmentBits[x][y] = 0;
85. }
86. }
87. }
88. itemsFound.add(mSegmentBits[x][y]);
89.
90. int newPixelColor = ColorUtils.compositeColors(
91. colors[mSegmentBits[x][y] == 0 ? 0 : 1],
92. scaledBackgroundImage.getPixel(x, y)
93. );
94. dstBitmap.setPixel(x, y, mSegmentBits[x][y] == 0 ? colors[0] : scaledBackgroundImage.getPixel(x, y));
95. }
96. }
97. return dstBitmap;
}
總結
以上是生活随笔為你收集整理的MindSpore部署图像分割示例程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MindSpore模型推理
- 下一篇: HiCar技术概述