Upload 45 files
Browse files- .gitattributes +10 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/README.md +56 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp/CMakeLists.txt +32 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp/dog.jpg +3 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp/run_test.cpp +392 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/models/midas_v2_w8a8.qnn216.ctx.bin +3 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/dog.jpg +3 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/run_test.py +111 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/transforms.py +234 -0
- model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/utils.py +104 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/README.md +56 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp/CMakeLists.txt +32 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp/dog.jpg +3 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp/run_test.cpp +392 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/models/midas_v2_w8a16.qnn216.ctx.bin +3 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/dog.jpg +3 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/run_test.py +111 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/transforms.py +234 -0
- model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/utils.py +104 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/README.md +56 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp/CMakeLists.txt +32 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp/dog.jpg +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp/run_test.cpp +392 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/models/midas_v2_fp16.qnn216.ctx.bin +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/dog.jpg +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/run_test.py +111 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/transforms.py +234 -0
- model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/utils.py +104 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/README.md +56 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp/CMakeLists.txt +32 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp/dog.jpg +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp/run_test.cpp +392 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/models/midas_v2_w8a8.qnn216.ctx.bin +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/dog.jpg +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/run_test.py +111 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/transforms.py +234 -0
- model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/utils.py +104 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/README.md +57 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp/CMakeLists.txt +32 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp/dog.jpg +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp/run_test.cpp +392 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/models/midas_v2_w8a16.qnn216.ctx.bin +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/dog.jpg +3 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/run_test.py +111 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/transforms.py +234 -0
- model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/utils.py +104 -0
.gitattributes
CHANGED
@@ -33,3 +33,13 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
37 |
+
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
38 |
+
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
39 |
+
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
40 |
+
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
41 |
+
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
42 |
+
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
43 |
+
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
44 |
+
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
45 |
+
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## Model Information
|
2 |
+
|
3 |
+
### Source model
|
4 |
+
- Input shape: 1x3x256x256
|
5 |
+
- Number of parameters: 20.33M
|
6 |
+
- Model size: 82.17M
|
7 |
+
- Output shape: 1x1x256x256
|
8 |
+
|
9 |
+
Source model repository: [midas](https://github.com/isl-org/MiDaS/tree/master)
|
10 |
+
|
11 |
+
### Converted model
|
12 |
+
|
13 |
+
- Precision: INT8
|
14 |
+
- Backend: QNN2.16
|
15 |
+
- Target Device: FV01 QCS6490
|
16 |
+
|
17 |
+
## Inference with AidLite SDK
|
18 |
+
|
19 |
+
### SDK installation
|
20 |
+
Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
|
21 |
+
|
22 |
+
- Install AidLite SDK
|
23 |
+
|
24 |
+
```bash
|
25 |
+
# Install the appropriate version of the aidlite sdk
|
26 |
+
sudo aid-pkg update
|
27 |
+
sudo aid-pkg install aidlite-sdk
|
28 |
+
# Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
|
29 |
+
sudo aid-pkg install aidlite-{QNN VERSION}
|
30 |
+
```
|
31 |
+
|
32 |
+
- Verify AidLite SDK
|
33 |
+
|
34 |
+
```bash
|
35 |
+
# aidlite sdk c++ check
|
36 |
+
python3 -c "import aidlite ; print(aidlite.get_library_version())"
|
37 |
+
|
38 |
+
# aidlite sdk python check
|
39 |
+
python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
|
40 |
+
```
|
41 |
+
|
42 |
+
### Run Demo
|
43 |
+
#### python
|
44 |
+
```bash
|
45 |
+
cd model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite
|
46 |
+
python3 python/run_test.py --target_model ./models/midas_v2_w8a8.qnn216.ctx.bin --imgs ./python/dog.jpg --invoke_nums 10
|
47 |
+
```
|
48 |
+
|
49 |
+
#### c++
|
50 |
+
```bash
|
51 |
+
cd midas_v2/model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp
|
52 |
+
mkdir build && cd build
|
53 |
+
cmake ..
|
54 |
+
make
|
55 |
+
./run_test
|
56 |
+
```
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp/CMakeLists.txt
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
cmake_minimum_required (VERSION 3.5)
|
2 |
+
project("run_test")
|
3 |
+
|
4 |
+
find_package(OpenCV REQUIRED)
|
5 |
+
|
6 |
+
message(STATUS "oPENCV Library status:")
|
7 |
+
message(STATUS ">version:${OpenCV_VERSION}")
|
8 |
+
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
|
9 |
+
|
10 |
+
set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
|
11 |
+
|
12 |
+
include_directories(
|
13 |
+
/usr/local/include
|
14 |
+
/usr/include/opencv4
|
15 |
+
)
|
16 |
+
|
17 |
+
link_directories(
|
18 |
+
/usr/local/lib/
|
19 |
+
)
|
20 |
+
|
21 |
+
file(GLOB SRC_LISTS
|
22 |
+
${CMAKE_CURRENT_SOURCE_DIR}/run_test.cpp
|
23 |
+
)
|
24 |
+
|
25 |
+
add_executable(run_test ${SRC_LISTS})
|
26 |
+
|
27 |
+
target_link_libraries(run_test
|
28 |
+
aidlite
|
29 |
+
${OpenCV_LIBS}
|
30 |
+
pthread
|
31 |
+
jsoncpp
|
32 |
+
)
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/cpp/run_test.cpp
ADDED
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <iostream>
|
2 |
+
#include <fstream>
|
3 |
+
#include <opencv2/opencv.hpp>
|
4 |
+
#include <aidlux/aidlite/aidlite.hpp>
|
5 |
+
#include <vector>
|
6 |
+
#include <numeric>
|
7 |
+
#include <cmath>
|
8 |
+
#include <jsoncpp/json/json.h>
|
9 |
+
|
10 |
+
using namespace cv;
|
11 |
+
using namespace std;
|
12 |
+
using namespace Aidlux::Aidlite;
|
13 |
+
|
14 |
+
const int net_w = 256;
|
15 |
+
const int net_h = 256;
|
16 |
+
|
17 |
+
const std::vector<float> mean_vals = {0.485f, 0.456f, 0.406f};
|
18 |
+
const std::vector<float> std_vals = {0.229f, 0.224f, 0.225f};
|
19 |
+
|
20 |
+
|
21 |
+
struct Args {
|
22 |
+
std::string target_model = "../../models/midas_v2_w8a8.qnn216.ctx.bin";
|
23 |
+
std::string imgs = "../dog.jpg";
|
24 |
+
int invoke_nums = 10;
|
25 |
+
std::string model_type = "QNN";
|
26 |
+
};
|
27 |
+
|
28 |
+
|
29 |
+
Args parse_args(int argc, char* argv[]) {
|
30 |
+
Args args;
|
31 |
+
for (int i = 1; i < argc; ++i) {
|
32 |
+
std::string arg = argv[i];
|
33 |
+
if (arg == "--target_model" && i + 1 < argc) {
|
34 |
+
args.target_model = argv[++i];
|
35 |
+
} else if (arg == "--imgs" && i + 1 < argc) {
|
36 |
+
args.imgs = argv[++i];
|
37 |
+
} else if (arg == "--invoke_nums" && i + 1 < argc) {
|
38 |
+
args.invoke_nums = std::stoi(argv[++i]);
|
39 |
+
} else if (arg == "--model_type" && i + 1 < argc) {
|
40 |
+
args.model_type = argv[++i];
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return args;
|
44 |
+
}
|
45 |
+
|
46 |
+
std::string to_lower(const std::string& str) {
|
47 |
+
std::string lower_str = str;
|
48 |
+
std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
|
49 |
+
return std::tolower(c);
|
50 |
+
});
|
51 |
+
return lower_str;
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
|
56 |
+
|
57 |
+
int current_coordinate[4] = {0, 0, 0, 0};
|
58 |
+
for(int a = 0; a < src_dims[0]; ++a){
|
59 |
+
current_coordinate[0] = a;
|
60 |
+
for(int b = 0; b < src_dims[1]; ++b){
|
61 |
+
current_coordinate[1] = b;
|
62 |
+
for(int c = 0; c < src_dims[2]; ++c){
|
63 |
+
current_coordinate[2] = c;
|
64 |
+
for(int d = 0; d < src_dims[3]; ++d){
|
65 |
+
current_coordinate[3] = d;
|
66 |
+
|
67 |
+
int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
|
68 |
+
current_coordinate[1]*src_dims[2]*src_dims[3] +
|
69 |
+
current_coordinate[2]*src_dims[3] +
|
70 |
+
current_coordinate[3];
|
71 |
+
|
72 |
+
int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
73 |
+
current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
74 |
+
current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
75 |
+
current_coordinate[tsp_dims[3]];
|
76 |
+
|
77 |
+
dest[new_index] = src[old_index];
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
return EXIT_SUCCESS;
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
// 替代 np.nan_to_num
|
88 |
+
void sanitizeDepthMap(cv::Mat& depth) {
|
89 |
+
for (int y = 0; y < depth.rows; ++y) {
|
90 |
+
float* row = depth.ptr<float>(y);
|
91 |
+
for (int x = 0; x < depth.cols; ++x) {
|
92 |
+
float val = row[x];
|
93 |
+
if (!std::isfinite(val)) {
|
94 |
+
row[x] = 0.0f;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
// 等效于 Python write_depth
|
101 |
+
void write_depth(const std::string& path, const cv::Mat& input_depth, bool grayscale = false, int bits = 1) {
|
102 |
+
CV_Assert(input_depth.type() == CV_32FC1);
|
103 |
+
|
104 |
+
// 拷贝 + 处理非法值
|
105 |
+
cv::Mat depth = input_depth.clone();
|
106 |
+
sanitizeDepthMap(depth);
|
107 |
+
|
108 |
+
double minVal, maxVal;
|
109 |
+
cv::minMaxLoc(depth, &minVal, &maxVal);
|
110 |
+
|
111 |
+
double max_val = (1 << (8 * bits)) - 1;
|
112 |
+
cv::Mat out;
|
113 |
+
|
114 |
+
if (maxVal - minVal > std::numeric_limits<float>::epsilon()) {
|
115 |
+
// 归一化并映射到位深范围
|
116 |
+
out = (depth - minVal) * (max_val / (maxVal - minVal));
|
117 |
+
} else {
|
118 |
+
out = cv::Mat::zeros(depth.size(), CV_32F);
|
119 |
+
}
|
120 |
+
|
121 |
+
if (!grayscale) {
|
122 |
+
out.convertTo(out, CV_8UC1);
|
123 |
+
cv::applyColorMap(out, out, cv::COLORMAP_INFERNO);
|
124 |
+
}
|
125 |
+
|
126 |
+
if (bits == 1) {
|
127 |
+
out.convertTo(out, CV_8U);
|
128 |
+
} else if (bits == 2) {
|
129 |
+
out.convertTo(out, CV_16U);
|
130 |
+
}
|
131 |
+
|
132 |
+
cv::imwrite(path, out);
|
133 |
+
}
|
134 |
+
|
135 |
+
// 等效于 Python write_pfm
|
136 |
+
void write_pfm(const std::string& path, const cv::Mat& image, float scale = 1.0f) {
|
137 |
+
CV_Assert(image.type() == CV_32FC1 || image.type() == CV_32FC3);
|
138 |
+
|
139 |
+
std::ofstream file(path, std::ios::binary);
|
140 |
+
if (!file.is_open()) {
|
141 |
+
std::cerr << "Failed to open file for writing PFM: " << path << std::endl;
|
142 |
+
return;
|
143 |
+
}
|
144 |
+
|
145 |
+
int width = image.cols;
|
146 |
+
int height = image.rows;
|
147 |
+
int channels = image.channels();
|
148 |
+
bool color = (channels == 3);
|
149 |
+
|
150 |
+
file << (color ? "PF" : "Pf") << "\n";
|
151 |
+
file << width << " " << height << "\n";
|
152 |
+
|
153 |
+
// Endianness: negative = little-endian
|
154 |
+
uint16_t endian_test = 0x1;
|
155 |
+
bool is_little_endian = *(reinterpret_cast<uint8_t*>(&endian_test)) == 0x1;
|
156 |
+
if (is_little_endian) {
|
157 |
+
scale = -scale;
|
158 |
+
}
|
159 |
+
|
160 |
+
file << scale << "\n";
|
161 |
+
|
162 |
+
// Flip vertically (OpenCV top-left origin -> PFM bottom-left origin)
|
163 |
+
cv::Mat flipped;
|
164 |
+
cv::flip(image, flipped, 0);
|
165 |
+
|
166 |
+
// Write raw data
|
167 |
+
file.write(reinterpret_cast<const char*>(flipped.data), flipped.total() * channels * sizeof(float));
|
168 |
+
file.close();
|
169 |
+
}
|
170 |
+
|
171 |
+
|
172 |
+
// ======================= Normalize =======================
|
173 |
+
void normalize(cv::Mat& image) {
|
174 |
+
CV_Assert(image.type() == CV_32FC3);
|
175 |
+
int rows = image.rows;
|
176 |
+
int cols = image.cols;
|
177 |
+
|
178 |
+
for (int y = 0; y < rows; ++y) {
|
179 |
+
cv::Vec3f* row = image.ptr<cv::Vec3f>(y);
|
180 |
+
for (int x = 0; x < cols; ++x) {
|
181 |
+
for (int c = 0; c < 3; ++c) {
|
182 |
+
row[x][c] = (row[x][c] - mean_vals[c]) / std_vals[c];
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
cv::Mat hwc_to_chw(const cv::Mat& image) {
|
189 |
+
std::vector<cv::Mat> channels(3);
|
190 |
+
cv::split(image, channels);
|
191 |
+
|
192 |
+
cv::Mat chw(3, image.rows * image.cols, CV_32F);
|
193 |
+
for (int c = 0; c < 3; ++c) {
|
194 |
+
memcpy(chw.ptr(c), channels[c].data, image.rows * image.cols * sizeof(float));
|
195 |
+
}
|
196 |
+
|
197 |
+
return chw;
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
bool first_execution = true;
|
202 |
+
cv::Mat img_process(const cv::Mat image_bgr, cv::Size& org_size_out) {
|
203 |
+
first_execution = false;
|
204 |
+
|
205 |
+
cv::Mat image_rgb;
|
206 |
+
cv::cvtColor(image_bgr, image_rgb, cv::COLOR_BGR2RGB);
|
207 |
+
image_rgb.convertTo(image_rgb, CV_32FC3, 1.0 / 255.0);
|
208 |
+
|
209 |
+
// 2. Save original size
|
210 |
+
org_size_out = image_rgb.size(); // H x W
|
211 |
+
|
212 |
+
// 3. Resize to 256x256 using cubic interpolation
|
213 |
+
cv::resize(image_rgb, image_rgb, cv::Size(net_w, net_h), 0, 0, cv::INTER_CUBIC);
|
214 |
+
|
215 |
+
// 4. Normalize using mean/std
|
216 |
+
normalize(image_rgb);
|
217 |
+
|
218 |
+
// 5. Convert HWC to CHW
|
219 |
+
cv::Mat chw = hwc_to_chw(image_rgb);
|
220 |
+
|
221 |
+
// 6. Add batch dimension: [1, C, H, W] → reshape to 1x3xHxW style float array
|
222 |
+
cv::Mat input_tensor(1, 3 * net_h * net_w, CV_32F);
|
223 |
+
memcpy(input_tensor.ptr<float>(), chw.data, 3 * net_h * net_w * sizeof(float));
|
224 |
+
|
225 |
+
std::cout << "Input resized to " << net_w << "x" << net_h << " before entering the encoder" << std::endl;
|
226 |
+
|
227 |
+
return input_tensor;
|
228 |
+
}
|
229 |
+
|
230 |
+
|
231 |
+
float* matToFloatPtr(const cv::Mat& input_mat, bool normalize = true) {
|
232 |
+
// 检查连续性
|
233 |
+
cv::Mat mat = input_mat;
|
234 |
+
if (!mat.isContinuous()) {
|
235 |
+
mat = mat.clone();
|
236 |
+
}
|
237 |
+
|
238 |
+
// 分配内存
|
239 |
+
int total_pixels = mat.rows * mat.cols;
|
240 |
+
int channels = mat.channels();
|
241 |
+
float* float_data = new float[total_pixels * channels];
|
242 |
+
|
243 |
+
// 根据数据类型转换
|
244 |
+
if (mat.type() == CV_8UC1 || mat.type() == CV_8UC3) {
|
245 |
+
uchar* ptr = mat.ptr<uchar>(0);
|
246 |
+
for (int i = 0; i < total_pixels * channels; ++i) {
|
247 |
+
float_data[i] = normalize ? (static_cast<float>(ptr[i]) / 255.0f) : ptr[i];
|
248 |
+
}
|
249 |
+
} else if (mat.type() == CV_32FC1 || mat.type() == CV_32FC3) {
|
250 |
+
float* ptr = mat.ptr<float>(0);
|
251 |
+
std::memcpy(float_data, ptr, total_pixels * channels * sizeof(float));
|
252 |
+
} else {
|
253 |
+
delete[] float_data;
|
254 |
+
return nullptr; // 不支持的类型
|
255 |
+
}
|
256 |
+
|
257 |
+
return float_data;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
int invoke(const Args& args) {
|
262 |
+
std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
|
263 |
+
<< "Image Path: " << args.imgs << "\n"
|
264 |
+
<< "Inference Nums: " << args.invoke_nums << "\n"
|
265 |
+
<< "Model Type: " << args.model_type << "\n";
|
266 |
+
Model* model = Model::create_instance(args.target_model);
|
267 |
+
if(model == nullptr){
|
268 |
+
printf("Create model failed !\n");
|
269 |
+
return EXIT_FAILURE;
|
270 |
+
}
|
271 |
+
Config* config = Config::create_instance();
|
272 |
+
if(config == nullptr){
|
273 |
+
printf("Create config failed !\n");
|
274 |
+
return EXIT_FAILURE;
|
275 |
+
}
|
276 |
+
config->implement_type = ImplementType::TYPE_LOCAL;
|
277 |
+
std::string model_type_lower = to_lower(args.model_type);
|
278 |
+
if (model_type_lower == "qnn"){
|
279 |
+
config->framework_type = FrameworkType::TYPE_QNN;
|
280 |
+
} else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
|
281 |
+
config->framework_type = FrameworkType::TYPE_SNPE2;
|
282 |
+
}
|
283 |
+
config->accelerate_type = AccelerateType::TYPE_DSP;
|
284 |
+
config->is_quantify_model = 1;
|
285 |
+
|
286 |
+
unsigned int model_h = 256;
|
287 |
+
unsigned int model_w = 256;
|
288 |
+
std::vector<std::vector<uint32_t>> input_shapes = {{1,model_h,model_w,3}};
|
289 |
+
std::vector<std::vector<uint32_t>> output_shapes = {{1,model_h,model_w,1}};
|
290 |
+
model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
|
291 |
+
std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
|
292 |
+
if(fast_interpreter == nullptr){
|
293 |
+
printf("build_interpretper_from_model_and_config failed !\n");
|
294 |
+
return EXIT_FAILURE;
|
295 |
+
}
|
296 |
+
int result = fast_interpreter->init();
|
297 |
+
if(result != EXIT_SUCCESS){
|
298 |
+
printf("interpreter->init() failed !\n");
|
299 |
+
return EXIT_FAILURE;
|
300 |
+
}
|
301 |
+
// load model
|
302 |
+
fast_interpreter->load_model();
|
303 |
+
if(result != EXIT_SUCCESS){
|
304 |
+
printf("interpreter->load_model() failed !\n");
|
305 |
+
return EXIT_FAILURE;
|
306 |
+
}
|
307 |
+
printf("detect model load success!\n");
|
308 |
+
|
309 |
+
cv::Mat frame = cv::imread(args.imgs);
|
310 |
+
if (frame.empty()) {
|
311 |
+
printf("detect image load failed!\n");
|
312 |
+
return 1;
|
313 |
+
}
|
314 |
+
printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
|
315 |
+
cv::Mat input_data;
|
316 |
+
cv::Mat frame_clone = frame.clone();
|
317 |
+
int h = frame_clone.rows;
|
318 |
+
int w = frame_clone.cols;
|
319 |
+
cv::Size org_size(w, h);
|
320 |
+
cv::Size org_size0(256, 256);
|
321 |
+
|
322 |
+
cv::Mat input_tensor = img_process(frame_clone, org_size0);
|
323 |
+
float* float_data = matToFloatPtr(input_tensor);
|
324 |
+
unsigned int src_dims[4] = {1, 3, 256, 256};
|
325 |
+
unsigned int tsp_dims[4] = {0,2,3,1};
|
326 |
+
unsigned int stride_data_num = 1*256*256*3;
|
327 |
+
float* format_data = new float[stride_data_num];
|
328 |
+
transpose(float_data, src_dims, tsp_dims, format_data);
|
329 |
+
cv::Mat origin_buffer(3,256*256, CV_32F, format_data);
|
330 |
+
|
331 |
+
float *outdata0 = nullptr;
|
332 |
+
std::vector<float> invoke_time;
|
333 |
+
for (int i = 0; i < args.invoke_nums; ++i) {
|
334 |
+
result = fast_interpreter->set_input_tensor(0, origin_buffer.data);
|
335 |
+
if(result != EXIT_SUCCESS){
|
336 |
+
printf("interpreter->set_input_tensor() failed !\n");
|
337 |
+
return EXIT_FAILURE;
|
338 |
+
}
|
339 |
+
auto t1 = std::chrono::high_resolution_clock::now();
|
340 |
+
result = fast_interpreter->invoke();
|
341 |
+
auto t2 = std::chrono::high_resolution_clock::now();
|
342 |
+
std::chrono::duration<double> cost_time = t2 - t1;
|
343 |
+
invoke_time.push_back(cost_time.count() * 1000);
|
344 |
+
if(result != EXIT_SUCCESS){
|
345 |
+
printf("interpreter->invoke() failed !\n");
|
346 |
+
return EXIT_FAILURE;
|
347 |
+
}
|
348 |
+
uint32_t out_data_0 = 0;
|
349 |
+
result = fast_interpreter->get_output_tensor(0, (void**)&outdata0, &out_data_0);
|
350 |
+
if(result != EXIT_SUCCESS){
|
351 |
+
printf("interpreter->get_output_tensor() 1 failed !\n");
|
352 |
+
return EXIT_FAILURE;
|
353 |
+
}
|
354 |
+
|
355 |
+
}
|
356 |
+
|
357 |
+
float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
|
358 |
+
float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
|
359 |
+
float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
|
360 |
+
float var_invoketime = 0.0f;
|
361 |
+
for (auto time : invoke_time) {
|
362 |
+
var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
|
363 |
+
}
|
364 |
+
var_invoketime /= args.invoke_nums;
|
365 |
+
printf("=======================================\n");
|
366 |
+
printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
|
367 |
+
args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
|
368 |
+
printf("=======================================\n");
|
369 |
+
|
370 |
+
// post process
|
371 |
+
cv::Mat out_buffer(1,256*256, CV_32F, outdata0);
|
372 |
+
cv::Mat prediction_2d(256, 256, CV_32F, (void*)out_buffer.ptr<float>());
|
373 |
+
cv::Mat resized;
|
374 |
+
cv::resize(prediction_2d, resized, org_size, 0, 0, cv::INTER_CUBIC);
|
375 |
+
|
376 |
+
// 保存为图像
|
377 |
+
write_depth("depth_output.jpg", resized, false, 1);
|
378 |
+
|
379 |
+
// 保存为 PFM
|
380 |
+
write_pfm("depth_output.pfm", resized);
|
381 |
+
|
382 |
+
|
383 |
+
|
384 |
+
fast_interpreter->destory();
|
385 |
+
return 0;
|
386 |
+
}
|
387 |
+
|
388 |
+
|
389 |
+
int main(int argc, char* argv[]) {
|
390 |
+
Args args = parse_args(argc, argv);
|
391 |
+
return invoke(args);
|
392 |
+
}
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/models/midas_v2_w8a8.qnn216.ctx.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:1abbd2fc95f87af48b1b609368d9dbaac7136a3aeb8a9c791ea3907da79550f8
|
3 |
+
size 27611136
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/run_test.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
from utils import write_pfm,write_depth,img_process
|
6 |
+
import aidlite
|
7 |
+
import time
|
8 |
+
import argparse
|
9 |
+
|
10 |
+
def out_process(prediction,target_size):
|
11 |
+
prediction = torch.nn.functional.interpolate(
|
12 |
+
prediction,
|
13 |
+
size=target_size,
|
14 |
+
mode="bicubic",
|
15 |
+
align_corners=False,
|
16 |
+
)
|
17 |
+
prediction = prediction.squeeze().detach().numpy()
|
18 |
+
return prediction
|
19 |
+
|
20 |
+
class run_qnn:
|
21 |
+
def __init__(self,qnn_path):
|
22 |
+
super().__init__()
|
23 |
+
self.model = aidlite.Model.create_instance(qnn_path)
|
24 |
+
if self.model is None:
|
25 |
+
print("Create model failed !")
|
26 |
+
return
|
27 |
+
|
28 |
+
self.config = aidlite.Config.create_instance()
|
29 |
+
if self.config is None:
|
30 |
+
print("build_interpretper_from_model_and_config failed !")
|
31 |
+
return
|
32 |
+
|
33 |
+
self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
|
34 |
+
self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
|
35 |
+
self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
|
36 |
+
# self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
|
37 |
+
self.config.is_quantify_model = 1
|
38 |
+
|
39 |
+
self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
|
40 |
+
if self.interpreter is None:
|
41 |
+
print("build_interpretper_from_model_and_config failed !")
|
42 |
+
return
|
43 |
+
input_shapes = [[1,256,256,3]]
|
44 |
+
output_shapes = [[1,256,256,1]]
|
45 |
+
self.model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
|
46 |
+
output_shapes, aidlite.DataType.TYPE_FLOAT32)
|
47 |
+
|
48 |
+
if self.interpreter is None:
|
49 |
+
print("build_interpretper_from_model_and_config failed !")
|
50 |
+
result = self.interpreter.init()
|
51 |
+
if result != 0:
|
52 |
+
print(f"interpreter init failed !")
|
53 |
+
result = self.interpreter.load_model()
|
54 |
+
if result != 0:
|
55 |
+
print("interpreter load model failed !")
|
56 |
+
|
57 |
+
print(" model load success!")
|
58 |
+
|
59 |
+
def __call__(self, input,invoke_nums):
|
60 |
+
self.interpreter.set_input_tensor(0,input)
|
61 |
+
invoke_time=[]
|
62 |
+
for i in range(invoke_nums):
|
63 |
+
result = self.interpreter.set_input_tensor(0, input.data)
|
64 |
+
if result != 0:
|
65 |
+
print("interpreter set_input_tensor() failed")
|
66 |
+
t1=time.time()
|
67 |
+
result = self.interpreter.invoke()
|
68 |
+
cost_time = (time.time()-t1)*1000
|
69 |
+
invoke_time.append(cost_time)
|
70 |
+
|
71 |
+
max_invoke_time = max(invoke_time)
|
72 |
+
min_invoke_time = min(invoke_time)
|
73 |
+
mean_invoke_time = sum(invoke_time)/invoke_nums
|
74 |
+
var_invoketime=np.var(invoke_time)
|
75 |
+
print("====================================")
|
76 |
+
print(f"QNN invoke time:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
|
77 |
+
print("====================================")
|
78 |
+
features_0 = self.interpreter.get_output_tensor(0).reshape(1,256,256,1).transpose(0,3,1,2)
|
79 |
+
return features_0
|
80 |
+
|
81 |
+
|
82 |
+
|
83 |
+
def run(args):
|
84 |
+
img_path = args.imgs
|
85 |
+
qnn_path = args.target_model
|
86 |
+
invoke_num=args.invoke_nums
|
87 |
+
print("Start processing...")
|
88 |
+
img_input,org_size = img_process(img_path)
|
89 |
+
|
90 |
+
qnn_model =run_qnn(qnn_path)
|
91 |
+
prediction_qnn = qnn_model(img_input.numpy().transpose(0,2,3,1),invoke_num)
|
92 |
+
prediction_qnn = torch.tensor(prediction_qnn)
|
93 |
+
qnn_process = out_process(prediction_qnn,org_size)
|
94 |
+
|
95 |
+
write_depth("./python/results.jpg", qnn_process, grayscale=False, bits=1)
|
96 |
+
write_pfm("./python/results.pfm", qnn_process.astype(np.float32))
|
97 |
+
print("Finished")
|
98 |
+
|
99 |
+
def parser_args():
|
100 |
+
parser = argparse.ArgumentParser(description="Run model benchmarks")
|
101 |
+
parser.add_argument('--target_model',type=str,default='./models/midas_v2_w8a8.qnn216.ctx.bin',help="Inference model path")
|
102 |
+
parser.add_argument('--imgs',type=str,default='./python/dog.jpg',help="Predict images path")
|
103 |
+
parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
|
104 |
+
parser.add_argument('--model_type',type=str,default='QNN',help="Run backend")
|
105 |
+
args = parser.parse_args()
|
106 |
+
return args
|
107 |
+
|
108 |
+
|
109 |
+
if __name__ =="__main__":
|
110 |
+
args = parser_args()
|
111 |
+
run(args)
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/transforms.py
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import math
|
4 |
+
|
5 |
+
|
6 |
+
def apply_min_size(sample, size, image_interpolation_method=cv2.INTER_AREA):
|
7 |
+
"""Rezise the sample to ensure the given size. Keeps aspect ratio.
|
8 |
+
|
9 |
+
Args:
|
10 |
+
sample (dict): sample
|
11 |
+
size (tuple): image size
|
12 |
+
|
13 |
+
Returns:
|
14 |
+
tuple: new size
|
15 |
+
"""
|
16 |
+
shape = list(sample["disparity"].shape)
|
17 |
+
|
18 |
+
if shape[0] >= size[0] and shape[1] >= size[1]:
|
19 |
+
return sample
|
20 |
+
|
21 |
+
scale = [0, 0]
|
22 |
+
scale[0] = size[0] / shape[0]
|
23 |
+
scale[1] = size[1] / shape[1]
|
24 |
+
|
25 |
+
scale = max(scale)
|
26 |
+
|
27 |
+
shape[0] = math.ceil(scale * shape[0])
|
28 |
+
shape[1] = math.ceil(scale * shape[1])
|
29 |
+
|
30 |
+
# resize
|
31 |
+
sample["image"] = cv2.resize(
|
32 |
+
sample["image"], tuple(shape[::-1]), interpolation=image_interpolation_method
|
33 |
+
)
|
34 |
+
|
35 |
+
sample["disparity"] = cv2.resize(
|
36 |
+
sample["disparity"], tuple(shape[::-1]), interpolation=cv2.INTER_NEAREST
|
37 |
+
)
|
38 |
+
sample["mask"] = cv2.resize(
|
39 |
+
sample["mask"].astype(np.float32),
|
40 |
+
tuple(shape[::-1]),
|
41 |
+
interpolation=cv2.INTER_NEAREST,
|
42 |
+
)
|
43 |
+
sample["mask"] = sample["mask"].astype(bool)
|
44 |
+
|
45 |
+
return tuple(shape)
|
46 |
+
|
47 |
+
|
48 |
+
class Resize(object):
|
49 |
+
"""Resize sample to given size (width, height).
|
50 |
+
"""
|
51 |
+
|
52 |
+
def __init__(
|
53 |
+
self,
|
54 |
+
width,
|
55 |
+
height,
|
56 |
+
resize_target=True,
|
57 |
+
keep_aspect_ratio=False,
|
58 |
+
ensure_multiple_of=1,
|
59 |
+
resize_method="lower_bound",
|
60 |
+
image_interpolation_method=cv2.INTER_AREA,
|
61 |
+
):
|
62 |
+
"""Init.
|
63 |
+
|
64 |
+
Args:
|
65 |
+
width (int): desired output width
|
66 |
+
height (int): desired output height
|
67 |
+
resize_target (bool, optional):
|
68 |
+
True: Resize the full sample (image, mask, target).
|
69 |
+
False: Resize image only.
|
70 |
+
Defaults to True.
|
71 |
+
keep_aspect_ratio (bool, optional):
|
72 |
+
True: Keep the aspect ratio of the input sample.
|
73 |
+
Output sample might not have the given width and height, and
|
74 |
+
resize behaviour depends on the parameter 'resize_method'.
|
75 |
+
Defaults to False.
|
76 |
+
ensure_multiple_of (int, optional):
|
77 |
+
Output width and height is constrained to be multiple of this parameter.
|
78 |
+
Defaults to 1.
|
79 |
+
resize_method (str, optional):
|
80 |
+
"lower_bound": Output will be at least as large as the given size.
|
81 |
+
"upper_bound": Output will be at max as large as the given size. (Output size might be smaller than given size.)
|
82 |
+
"minimal": Scale as least as possible. (Output size might be smaller than given size.)
|
83 |
+
Defaults to "lower_bound".
|
84 |
+
"""
|
85 |
+
self.__width = width
|
86 |
+
self.__height = height
|
87 |
+
|
88 |
+
self.__resize_target = resize_target
|
89 |
+
self.__keep_aspect_ratio = keep_aspect_ratio
|
90 |
+
self.__multiple_of = ensure_multiple_of
|
91 |
+
self.__resize_method = resize_method
|
92 |
+
self.__image_interpolation_method = image_interpolation_method
|
93 |
+
|
94 |
+
def constrain_to_multiple_of(self, x, min_val=0, max_val=None):
|
95 |
+
y = (np.round(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
96 |
+
|
97 |
+
if max_val is not None and y > max_val:
|
98 |
+
y = (np.floor(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
99 |
+
|
100 |
+
if y < min_val:
|
101 |
+
y = (np.ceil(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
102 |
+
|
103 |
+
return y
|
104 |
+
|
105 |
+
def get_size(self, width, height):
|
106 |
+
# determine new height and width
|
107 |
+
scale_height = self.__height / height
|
108 |
+
scale_width = self.__width / width
|
109 |
+
|
110 |
+
if self.__keep_aspect_ratio:
|
111 |
+
if self.__resize_method == "lower_bound":
|
112 |
+
# scale such that output size is lower bound
|
113 |
+
if scale_width > scale_height:
|
114 |
+
# fit width
|
115 |
+
scale_height = scale_width
|
116 |
+
else:
|
117 |
+
# fit height
|
118 |
+
scale_width = scale_height
|
119 |
+
elif self.__resize_method == "upper_bound":
|
120 |
+
# scale such that output size is upper bound
|
121 |
+
if scale_width < scale_height:
|
122 |
+
# fit width
|
123 |
+
scale_height = scale_width
|
124 |
+
else:
|
125 |
+
# fit height
|
126 |
+
scale_width = scale_height
|
127 |
+
elif self.__resize_method == "minimal":
|
128 |
+
# scale as least as possbile
|
129 |
+
if abs(1 - scale_width) < abs(1 - scale_height):
|
130 |
+
# fit width
|
131 |
+
scale_height = scale_width
|
132 |
+
else:
|
133 |
+
# fit height
|
134 |
+
scale_width = scale_height
|
135 |
+
else:
|
136 |
+
raise ValueError(
|
137 |
+
f"resize_method {self.__resize_method} not implemented"
|
138 |
+
)
|
139 |
+
|
140 |
+
if self.__resize_method == "lower_bound":
|
141 |
+
new_height = self.constrain_to_multiple_of(
|
142 |
+
scale_height * height, min_val=self.__height
|
143 |
+
)
|
144 |
+
new_width = self.constrain_to_multiple_of(
|
145 |
+
scale_width * width, min_val=self.__width
|
146 |
+
)
|
147 |
+
elif self.__resize_method == "upper_bound":
|
148 |
+
new_height = self.constrain_to_multiple_of(
|
149 |
+
scale_height * height, max_val=self.__height
|
150 |
+
)
|
151 |
+
new_width = self.constrain_to_multiple_of(
|
152 |
+
scale_width * width, max_val=self.__width
|
153 |
+
)
|
154 |
+
elif self.__resize_method == "minimal":
|
155 |
+
new_height = self.constrain_to_multiple_of(scale_height * height)
|
156 |
+
new_width = self.constrain_to_multiple_of(scale_width * width)
|
157 |
+
else:
|
158 |
+
raise ValueError(f"resize_method {self.__resize_method} not implemented")
|
159 |
+
|
160 |
+
return (new_width, new_height)
|
161 |
+
|
162 |
+
def __call__(self, sample):
|
163 |
+
width, height = self.get_size(
|
164 |
+
sample["image"].shape[1], sample["image"].shape[0]
|
165 |
+
)
|
166 |
+
|
167 |
+
# resize sample
|
168 |
+
sample["image"] = cv2.resize(
|
169 |
+
sample["image"],
|
170 |
+
(width, height),
|
171 |
+
interpolation=self.__image_interpolation_method,
|
172 |
+
)
|
173 |
+
|
174 |
+
if self.__resize_target:
|
175 |
+
if "disparity" in sample:
|
176 |
+
sample["disparity"] = cv2.resize(
|
177 |
+
sample["disparity"],
|
178 |
+
(width, height),
|
179 |
+
interpolation=cv2.INTER_NEAREST,
|
180 |
+
)
|
181 |
+
|
182 |
+
if "depth" in sample:
|
183 |
+
sample["depth"] = cv2.resize(
|
184 |
+
sample["depth"], (width, height), interpolation=cv2.INTER_NEAREST
|
185 |
+
)
|
186 |
+
|
187 |
+
sample["mask"] = cv2.resize(
|
188 |
+
sample["mask"].astype(np.float32),
|
189 |
+
(width, height),
|
190 |
+
interpolation=cv2.INTER_NEAREST,
|
191 |
+
)
|
192 |
+
sample["mask"] = sample["mask"].astype(bool)
|
193 |
+
|
194 |
+
return sample
|
195 |
+
|
196 |
+
|
197 |
+
class NormalizeImage(object):
|
198 |
+
"""Normlize image by given mean and std.
|
199 |
+
"""
|
200 |
+
|
201 |
+
def __init__(self, mean, std):
|
202 |
+
self.__mean = mean
|
203 |
+
self.__std = std
|
204 |
+
|
205 |
+
def __call__(self, sample):
|
206 |
+
sample["image"] = (sample["image"] - self.__mean) / self.__std
|
207 |
+
|
208 |
+
return sample
|
209 |
+
|
210 |
+
|
211 |
+
class PrepareForNet(object):
|
212 |
+
"""Prepare sample for usage as network input.
|
213 |
+
"""
|
214 |
+
|
215 |
+
def __init__(self):
|
216 |
+
pass
|
217 |
+
|
218 |
+
def __call__(self, sample):
|
219 |
+
image = np.transpose(sample["image"], (2, 0, 1))
|
220 |
+
sample["image"] = np.ascontiguousarray(image).astype(np.float32)
|
221 |
+
|
222 |
+
if "mask" in sample:
|
223 |
+
sample["mask"] = sample["mask"].astype(np.float32)
|
224 |
+
sample["mask"] = np.ascontiguousarray(sample["mask"])
|
225 |
+
|
226 |
+
if "disparity" in sample:
|
227 |
+
disparity = sample["disparity"].astype(np.float32)
|
228 |
+
sample["disparity"] = np.ascontiguousarray(disparity)
|
229 |
+
|
230 |
+
if "depth" in sample:
|
231 |
+
depth = sample["depth"].astype(np.float32)
|
232 |
+
sample["depth"] = np.ascontiguousarray(depth)
|
233 |
+
|
234 |
+
return sample
|
model_farm_midas_v2_qcs6490_qnn2.16_int8_aidlite/python/utils.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
|
6 |
+
from transforms import Resize, NormalizeImage, PrepareForNet
|
7 |
+
|
8 |
+
from torchvision.transforms import Compose
|
9 |
+
import sys
|
10 |
+
first_execution = True
|
11 |
+
def img_process(img_path):
|
12 |
+
global first_execution
|
13 |
+
first_execution = False
|
14 |
+
net_w, net_h = 256, 256
|
15 |
+
resize_mode = "upper_bound"
|
16 |
+
normalization = NormalizeImage(
|
17 |
+
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
|
18 |
+
)
|
19 |
+
transform = Compose(
|
20 |
+
[
|
21 |
+
Resize(
|
22 |
+
net_w,
|
23 |
+
net_h,
|
24 |
+
resize_target=None,
|
25 |
+
keep_aspect_ratio=False,
|
26 |
+
ensure_multiple_of=32,
|
27 |
+
resize_method=resize_mode,
|
28 |
+
image_interpolation_method=cv2.INTER_CUBIC,
|
29 |
+
),
|
30 |
+
normalization,
|
31 |
+
PrepareForNet(),
|
32 |
+
]
|
33 |
+
)
|
34 |
+
# image = utils.read_image(img_path) # in [0, 1]
|
35 |
+
image = cv2.imread(img_path)
|
36 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) / 255.0
|
37 |
+
org_size= image.shape[:2]
|
38 |
+
image = transform({"image": image})["image"]
|
39 |
+
sample = torch.from_numpy(image).to("cpu").unsqueeze(0)
|
40 |
+
height, width = sample.shape[2:]
|
41 |
+
print(f"Input resized to {width}x{height} before entering the encoder")
|
42 |
+
|
43 |
+
return sample,org_size
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
def write_depth(path, depth, grayscale=False, bits=1):
|
48 |
+
if not grayscale:
|
49 |
+
bits = 1
|
50 |
+
|
51 |
+
if not np.isfinite(depth).all():
|
52 |
+
depth=np.nan_to_num(depth, nan=0.0, posinf=0.0, neginf=0.0)
|
53 |
+
print("WARNING: Non-finite depth values present")
|
54 |
+
|
55 |
+
depth_min = depth.min()
|
56 |
+
depth_max = depth.max()
|
57 |
+
|
58 |
+
max_val = (2**(8*bits))-1
|
59 |
+
|
60 |
+
if depth_max - depth_min > np.finfo("float").eps:
|
61 |
+
out = max_val * (depth - depth_min) / (depth_max - depth_min)
|
62 |
+
else:
|
63 |
+
out = np.zeros(depth.shape, dtype=depth.dtype)
|
64 |
+
|
65 |
+
# print("out :",out.shape,out)
|
66 |
+
if not grayscale:
|
67 |
+
out = cv2.applyColorMap(np.uint8(out), cv2.COLORMAP_INFERNO)
|
68 |
+
|
69 |
+
if bits == 1:
|
70 |
+
cv2.imwrite(path , out.astype("uint8"))
|
71 |
+
elif bits == 2:
|
72 |
+
cv2.imwrite(path , out.astype("uint16"))
|
73 |
+
|
74 |
+
return
|
75 |
+
|
76 |
+
def write_pfm(path, image, scale=1):
|
77 |
+
with open(path, "wb") as file:
|
78 |
+
color = None
|
79 |
+
|
80 |
+
if image.dtype.name != "float32":
|
81 |
+
raise Exception("Image dtype must be float32.")
|
82 |
+
|
83 |
+
image = np.flipud(image)
|
84 |
+
|
85 |
+
if len(image.shape) == 3 and image.shape[2] == 3: # color image
|
86 |
+
color = True
|
87 |
+
elif (
|
88 |
+
len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1
|
89 |
+
): # greyscale
|
90 |
+
color = False
|
91 |
+
else:
|
92 |
+
raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")
|
93 |
+
|
94 |
+
file.write("PF\n" if color else "Pf\n".encode())
|
95 |
+
file.write("%d %d\n".encode() % (image.shape[1], image.shape[0]))
|
96 |
+
|
97 |
+
endian = image.dtype.byteorder
|
98 |
+
|
99 |
+
if endian == "<" or endian == "=" and sys.byteorder == "little":
|
100 |
+
scale = -scale
|
101 |
+
|
102 |
+
file.write("%f\n".encode() % scale)
|
103 |
+
|
104 |
+
image.tofile(file)
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## Model Information
|
2 |
+
|
3 |
+
### Source model
|
4 |
+
- Input shape: 1x3x256x256
|
5 |
+
- Number of parameters: 20.33M
|
6 |
+
- Model size: 82.17M
|
7 |
+
- Output shape: 1x1x256x256
|
8 |
+
|
9 |
+
Source model repository: [midas](https://github.com/isl-org/MiDaS/tree/master)
|
10 |
+
|
11 |
+
### Converted model
|
12 |
+
|
13 |
+
- Precision: INT8
|
14 |
+
- Backend: QNN2.16
|
15 |
+
- Target Device: FV01 QCS6490
|
16 |
+
|
17 |
+
## Inference with AidLite SDK
|
18 |
+
|
19 |
+
### SDK installation
|
20 |
+
Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
|
21 |
+
|
22 |
+
- Install AidLite SDK
|
23 |
+
|
24 |
+
```bash
|
25 |
+
# Install the appropriate version of the aidlite sdk
|
26 |
+
sudo aid-pkg update
|
27 |
+
sudo aid-pkg install aidlite-sdk
|
28 |
+
# Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
|
29 |
+
sudo aid-pkg install aidlite-{QNN VERSION}
|
30 |
+
```
|
31 |
+
|
32 |
+
- Verify AidLite SDK
|
33 |
+
|
34 |
+
```bash
|
35 |
+
# aidlite sdk c++ check
|
36 |
+
python3 -c "import aidlite ; print(aidlite.get_library_version())"
|
37 |
+
|
38 |
+
# aidlite sdk python check
|
39 |
+
python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
|
40 |
+
```
|
41 |
+
|
42 |
+
### Run Demo
|
43 |
+
#### python
|
44 |
+
```bash
|
45 |
+
cd model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite
|
46 |
+
python3 python/run_test.py --target_model ./models/midas_v2_w8a16.qnn216.ctx.bin --imgs ./python/dog.jpg --invoke_nums 10
|
47 |
+
```
|
48 |
+
|
49 |
+
#### c++
|
50 |
+
```bash
|
51 |
+
cd midas_v2/model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp
|
52 |
+
mkdir build && cd build
|
53 |
+
cmake ..
|
54 |
+
make
|
55 |
+
./run_test
|
56 |
+
```
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp/CMakeLists.txt
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
cmake_minimum_required (VERSION 3.5)
|
2 |
+
project("run_test")
|
3 |
+
|
4 |
+
find_package(OpenCV REQUIRED)
|
5 |
+
|
6 |
+
message(STATUS "oPENCV Library status:")
|
7 |
+
message(STATUS ">version:${OpenCV_VERSION}")
|
8 |
+
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
|
9 |
+
|
10 |
+
set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
|
11 |
+
|
12 |
+
include_directories(
|
13 |
+
/usr/local/include
|
14 |
+
/usr/include/opencv4
|
15 |
+
)
|
16 |
+
|
17 |
+
link_directories(
|
18 |
+
/usr/local/lib/
|
19 |
+
)
|
20 |
+
|
21 |
+
file(GLOB SRC_LISTS
|
22 |
+
${CMAKE_CURRENT_SOURCE_DIR}/run_test.cpp
|
23 |
+
)
|
24 |
+
|
25 |
+
add_executable(run_test ${SRC_LISTS})
|
26 |
+
|
27 |
+
target_link_libraries(run_test
|
28 |
+
aidlite
|
29 |
+
${OpenCV_LIBS}
|
30 |
+
pthread
|
31 |
+
jsoncpp
|
32 |
+
)
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/cpp/run_test.cpp
ADDED
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <iostream>
|
2 |
+
#include <fstream>
|
3 |
+
#include <opencv2/opencv.hpp>
|
4 |
+
#include <aidlux/aidlite/aidlite.hpp>
|
5 |
+
#include <vector>
|
6 |
+
#include <numeric>
|
7 |
+
#include <cmath>
|
8 |
+
#include <jsoncpp/json/json.h>
|
9 |
+
|
10 |
+
using namespace cv;
|
11 |
+
using namespace std;
|
12 |
+
using namespace Aidlux::Aidlite;
|
13 |
+
|
14 |
+
const int net_w = 256;
|
15 |
+
const int net_h = 256;
|
16 |
+
|
17 |
+
const std::vector<float> mean_vals = {0.485f, 0.456f, 0.406f};
|
18 |
+
const std::vector<float> std_vals = {0.229f, 0.224f, 0.225f};
|
19 |
+
|
20 |
+
|
21 |
+
struct Args {
|
22 |
+
std::string target_model = "../../models/midas_v2_w8a16.qnn216.ctx.bin";
|
23 |
+
std::string imgs = "../dog.jpg";
|
24 |
+
int invoke_nums = 10;
|
25 |
+
std::string model_type = "QNN";
|
26 |
+
};
|
27 |
+
|
28 |
+
|
29 |
+
Args parse_args(int argc, char* argv[]) {
|
30 |
+
Args args;
|
31 |
+
for (int i = 1; i < argc; ++i) {
|
32 |
+
std::string arg = argv[i];
|
33 |
+
if (arg == "--target_model" && i + 1 < argc) {
|
34 |
+
args.target_model = argv[++i];
|
35 |
+
} else if (arg == "--imgs" && i + 1 < argc) {
|
36 |
+
args.imgs = argv[++i];
|
37 |
+
} else if (arg == "--invoke_nums" && i + 1 < argc) {
|
38 |
+
args.invoke_nums = std::stoi(argv[++i]);
|
39 |
+
} else if (arg == "--model_type" && i + 1 < argc) {
|
40 |
+
args.model_type = argv[++i];
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return args;
|
44 |
+
}
|
45 |
+
|
46 |
+
std::string to_lower(const std::string& str) {
|
47 |
+
std::string lower_str = str;
|
48 |
+
std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
|
49 |
+
return std::tolower(c);
|
50 |
+
});
|
51 |
+
return lower_str;
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
|
56 |
+
|
57 |
+
int current_coordinate[4] = {0, 0, 0, 0};
|
58 |
+
for(int a = 0; a < src_dims[0]; ++a){
|
59 |
+
current_coordinate[0] = a;
|
60 |
+
for(int b = 0; b < src_dims[1]; ++b){
|
61 |
+
current_coordinate[1] = b;
|
62 |
+
for(int c = 0; c < src_dims[2]; ++c){
|
63 |
+
current_coordinate[2] = c;
|
64 |
+
for(int d = 0; d < src_dims[3]; ++d){
|
65 |
+
current_coordinate[3] = d;
|
66 |
+
|
67 |
+
int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
|
68 |
+
current_coordinate[1]*src_dims[2]*src_dims[3] +
|
69 |
+
current_coordinate[2]*src_dims[3] +
|
70 |
+
current_coordinate[3];
|
71 |
+
|
72 |
+
int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
73 |
+
current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
74 |
+
current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
75 |
+
current_coordinate[tsp_dims[3]];
|
76 |
+
|
77 |
+
dest[new_index] = src[old_index];
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
return EXIT_SUCCESS;
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
// 替代 np.nan_to_num
|
88 |
+
void sanitizeDepthMap(cv::Mat& depth) {
|
89 |
+
for (int y = 0; y < depth.rows; ++y) {
|
90 |
+
float* row = depth.ptr<float>(y);
|
91 |
+
for (int x = 0; x < depth.cols; ++x) {
|
92 |
+
float val = row[x];
|
93 |
+
if (!std::isfinite(val)) {
|
94 |
+
row[x] = 0.0f;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
// 等效于 Python write_depth
|
101 |
+
void write_depth(const std::string& path, const cv::Mat& input_depth, bool grayscale = false, int bits = 1) {
|
102 |
+
CV_Assert(input_depth.type() == CV_32FC1);
|
103 |
+
|
104 |
+
// 拷贝 + 处理非法值
|
105 |
+
cv::Mat depth = input_depth.clone();
|
106 |
+
sanitizeDepthMap(depth);
|
107 |
+
|
108 |
+
double minVal, maxVal;
|
109 |
+
cv::minMaxLoc(depth, &minVal, &maxVal);
|
110 |
+
|
111 |
+
double max_val = (1 << (8 * bits)) - 1;
|
112 |
+
cv::Mat out;
|
113 |
+
|
114 |
+
if (maxVal - minVal > std::numeric_limits<float>::epsilon()) {
|
115 |
+
// 归一化并映射到位深范围
|
116 |
+
out = (depth - minVal) * (max_val / (maxVal - minVal));
|
117 |
+
} else {
|
118 |
+
out = cv::Mat::zeros(depth.size(), CV_32F);
|
119 |
+
}
|
120 |
+
|
121 |
+
if (!grayscale) {
|
122 |
+
out.convertTo(out, CV_8UC1);
|
123 |
+
cv::applyColorMap(out, out, cv::COLORMAP_INFERNO);
|
124 |
+
}
|
125 |
+
|
126 |
+
if (bits == 1) {
|
127 |
+
out.convertTo(out, CV_8U);
|
128 |
+
} else if (bits == 2) {
|
129 |
+
out.convertTo(out, CV_16U);
|
130 |
+
}
|
131 |
+
|
132 |
+
cv::imwrite(path, out);
|
133 |
+
}
|
134 |
+
|
135 |
+
// 等效于 Python write_pfm
|
136 |
+
void write_pfm(const std::string& path, const cv::Mat& image, float scale = 1.0f) {
|
137 |
+
CV_Assert(image.type() == CV_32FC1 || image.type() == CV_32FC3);
|
138 |
+
|
139 |
+
std::ofstream file(path, std::ios::binary);
|
140 |
+
if (!file.is_open()) {
|
141 |
+
std::cerr << "Failed to open file for writing PFM: " << path << std::endl;
|
142 |
+
return;
|
143 |
+
}
|
144 |
+
|
145 |
+
int width = image.cols;
|
146 |
+
int height = image.rows;
|
147 |
+
int channels = image.channels();
|
148 |
+
bool color = (channels == 3);
|
149 |
+
|
150 |
+
file << (color ? "PF" : "Pf") << "\n";
|
151 |
+
file << width << " " << height << "\n";
|
152 |
+
|
153 |
+
// Endianness: negative = little-endian
|
154 |
+
uint16_t endian_test = 0x1;
|
155 |
+
bool is_little_endian = *(reinterpret_cast<uint8_t*>(&endian_test)) == 0x1;
|
156 |
+
if (is_little_endian) {
|
157 |
+
scale = -scale;
|
158 |
+
}
|
159 |
+
|
160 |
+
file << scale << "\n";
|
161 |
+
|
162 |
+
// Flip vertically (OpenCV top-left origin -> PFM bottom-left origin)
|
163 |
+
cv::Mat flipped;
|
164 |
+
cv::flip(image, flipped, 0);
|
165 |
+
|
166 |
+
// Write raw data
|
167 |
+
file.write(reinterpret_cast<const char*>(flipped.data), flipped.total() * channels * sizeof(float));
|
168 |
+
file.close();
|
169 |
+
}
|
170 |
+
|
171 |
+
|
172 |
+
// ======================= Normalize =======================
|
173 |
+
void normalize(cv::Mat& image) {
|
174 |
+
CV_Assert(image.type() == CV_32FC3);
|
175 |
+
int rows = image.rows;
|
176 |
+
int cols = image.cols;
|
177 |
+
|
178 |
+
for (int y = 0; y < rows; ++y) {
|
179 |
+
cv::Vec3f* row = image.ptr<cv::Vec3f>(y);
|
180 |
+
for (int x = 0; x < cols; ++x) {
|
181 |
+
for (int c = 0; c < 3; ++c) {
|
182 |
+
row[x][c] = (row[x][c] - mean_vals[c]) / std_vals[c];
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
cv::Mat hwc_to_chw(const cv::Mat& image) {
|
189 |
+
std::vector<cv::Mat> channels(3);
|
190 |
+
cv::split(image, channels);
|
191 |
+
|
192 |
+
cv::Mat chw(3, image.rows * image.cols, CV_32F);
|
193 |
+
for (int c = 0; c < 3; ++c) {
|
194 |
+
memcpy(chw.ptr(c), channels[c].data, image.rows * image.cols * sizeof(float));
|
195 |
+
}
|
196 |
+
|
197 |
+
return chw;
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
bool first_execution = true;
|
202 |
+
cv::Mat img_process(const cv::Mat image_bgr, cv::Size& org_size_out) {
|
203 |
+
first_execution = false;
|
204 |
+
|
205 |
+
cv::Mat image_rgb;
|
206 |
+
cv::cvtColor(image_bgr, image_rgb, cv::COLOR_BGR2RGB);
|
207 |
+
image_rgb.convertTo(image_rgb, CV_32FC3, 1.0 / 255.0);
|
208 |
+
|
209 |
+
// 2. Save original size
|
210 |
+
org_size_out = image_rgb.size(); // H x W
|
211 |
+
|
212 |
+
// 3. Resize to 256x256 using cubic interpolation
|
213 |
+
cv::resize(image_rgb, image_rgb, cv::Size(net_w, net_h), 0, 0, cv::INTER_CUBIC);
|
214 |
+
|
215 |
+
// 4. Normalize using mean/std
|
216 |
+
normalize(image_rgb);
|
217 |
+
|
218 |
+
// 5. Convert HWC to CHW
|
219 |
+
cv::Mat chw = hwc_to_chw(image_rgb);
|
220 |
+
|
221 |
+
// 6. Add batch dimension: [1, C, H, W] → reshape to 1x3xHxW style float array
|
222 |
+
cv::Mat input_tensor(1, 3 * net_h * net_w, CV_32F);
|
223 |
+
memcpy(input_tensor.ptr<float>(), chw.data, 3 * net_h * net_w * sizeof(float));
|
224 |
+
|
225 |
+
std::cout << "Input resized to " << net_w << "x" << net_h << " before entering the encoder" << std::endl;
|
226 |
+
|
227 |
+
return input_tensor;
|
228 |
+
}
|
229 |
+
|
230 |
+
|
231 |
+
float* matToFloatPtr(const cv::Mat& input_mat, bool normalize = true) {
|
232 |
+
// 检查连续性
|
233 |
+
cv::Mat mat = input_mat;
|
234 |
+
if (!mat.isContinuous()) {
|
235 |
+
mat = mat.clone();
|
236 |
+
}
|
237 |
+
|
238 |
+
// 分配内存
|
239 |
+
int total_pixels = mat.rows * mat.cols;
|
240 |
+
int channels = mat.channels();
|
241 |
+
float* float_data = new float[total_pixels * channels];
|
242 |
+
|
243 |
+
// 根据数据类型转换
|
244 |
+
if (mat.type() == CV_8UC1 || mat.type() == CV_8UC3) {
|
245 |
+
uchar* ptr = mat.ptr<uchar>(0);
|
246 |
+
for (int i = 0; i < total_pixels * channels; ++i) {
|
247 |
+
float_data[i] = normalize ? (static_cast<float>(ptr[i]) / 255.0f) : ptr[i];
|
248 |
+
}
|
249 |
+
} else if (mat.type() == CV_32FC1 || mat.type() == CV_32FC3) {
|
250 |
+
float* ptr = mat.ptr<float>(0);
|
251 |
+
std::memcpy(float_data, ptr, total_pixels * channels * sizeof(float));
|
252 |
+
} else {
|
253 |
+
delete[] float_data;
|
254 |
+
return nullptr; // 不支持的类型
|
255 |
+
}
|
256 |
+
|
257 |
+
return float_data;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
int invoke(const Args& args) {
|
262 |
+
std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
|
263 |
+
<< "Image Path: " << args.imgs << "\n"
|
264 |
+
<< "Inference Nums: " << args.invoke_nums << "\n"
|
265 |
+
<< "Model Type: " << args.model_type << "\n";
|
266 |
+
Model* model = Model::create_instance(args.target_model);
|
267 |
+
if(model == nullptr){
|
268 |
+
printf("Create model failed !\n");
|
269 |
+
return EXIT_FAILURE;
|
270 |
+
}
|
271 |
+
Config* config = Config::create_instance();
|
272 |
+
if(config == nullptr){
|
273 |
+
printf("Create config failed !\n");
|
274 |
+
return EXIT_FAILURE;
|
275 |
+
}
|
276 |
+
config->implement_type = ImplementType::TYPE_LOCAL;
|
277 |
+
std::string model_type_lower = to_lower(args.model_type);
|
278 |
+
if (model_type_lower == "qnn"){
|
279 |
+
config->framework_type = FrameworkType::TYPE_QNN;
|
280 |
+
} else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
|
281 |
+
config->framework_type = FrameworkType::TYPE_SNPE2;
|
282 |
+
}
|
283 |
+
config->accelerate_type = AccelerateType::TYPE_DSP;
|
284 |
+
config->is_quantify_model = 1;
|
285 |
+
|
286 |
+
unsigned int model_h = 256;
|
287 |
+
unsigned int model_w = 256;
|
288 |
+
std::vector<std::vector<uint32_t>> input_shapes = {{1,model_h,model_w,3}};
|
289 |
+
std::vector<std::vector<uint32_t>> output_shapes = {{1,model_h,model_w,1}};
|
290 |
+
model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
|
291 |
+
std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
|
292 |
+
if(fast_interpreter == nullptr){
|
293 |
+
printf("build_interpretper_from_model_and_config failed !\n");
|
294 |
+
return EXIT_FAILURE;
|
295 |
+
}
|
296 |
+
int result = fast_interpreter->init();
|
297 |
+
if(result != EXIT_SUCCESS){
|
298 |
+
printf("interpreter->init() failed !\n");
|
299 |
+
return EXIT_FAILURE;
|
300 |
+
}
|
301 |
+
// load model
|
302 |
+
fast_interpreter->load_model();
|
303 |
+
if(result != EXIT_SUCCESS){
|
304 |
+
printf("interpreter->load_model() failed !\n");
|
305 |
+
return EXIT_FAILURE;
|
306 |
+
}
|
307 |
+
printf("detect model load success!\n");
|
308 |
+
|
309 |
+
cv::Mat frame = cv::imread(args.imgs);
|
310 |
+
if (frame.empty()) {
|
311 |
+
printf("detect image load failed!\n");
|
312 |
+
return 1;
|
313 |
+
}
|
314 |
+
printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
|
315 |
+
cv::Mat input_data;
|
316 |
+
cv::Mat frame_clone = frame.clone();
|
317 |
+
int h = frame_clone.rows;
|
318 |
+
int w = frame_clone.cols;
|
319 |
+
cv::Size org_size(w, h);
|
320 |
+
cv::Size org_size0(256, 256);
|
321 |
+
|
322 |
+
cv::Mat input_tensor = img_process(frame_clone, org_size0);
|
323 |
+
float* float_data = matToFloatPtr(input_tensor);
|
324 |
+
unsigned int src_dims[4] = {1, 3, 256, 256};
|
325 |
+
unsigned int tsp_dims[4] = {0,2,3,1};
|
326 |
+
unsigned int stride_data_num = 1*256*256*3;
|
327 |
+
float* format_data = new float[stride_data_num];
|
328 |
+
transpose(float_data, src_dims, tsp_dims, format_data);
|
329 |
+
cv::Mat origin_buffer(3,256*256, CV_32F, format_data);
|
330 |
+
|
331 |
+
float *outdata0 = nullptr;
|
332 |
+
std::vector<float> invoke_time;
|
333 |
+
for (int i = 0; i < args.invoke_nums; ++i) {
|
334 |
+
result = fast_interpreter->set_input_tensor(0, origin_buffer.data);
|
335 |
+
if(result != EXIT_SUCCESS){
|
336 |
+
printf("interpreter->set_input_tensor() failed !\n");
|
337 |
+
return EXIT_FAILURE;
|
338 |
+
}
|
339 |
+
auto t1 = std::chrono::high_resolution_clock::now();
|
340 |
+
result = fast_interpreter->invoke();
|
341 |
+
auto t2 = std::chrono::high_resolution_clock::now();
|
342 |
+
std::chrono::duration<double> cost_time = t2 - t1;
|
343 |
+
invoke_time.push_back(cost_time.count() * 1000);
|
344 |
+
if(result != EXIT_SUCCESS){
|
345 |
+
printf("interpreter->invoke() failed !\n");
|
346 |
+
return EXIT_FAILURE;
|
347 |
+
}
|
348 |
+
uint32_t out_data_0 = 0;
|
349 |
+
result = fast_interpreter->get_output_tensor(0, (void**)&outdata0, &out_data_0);
|
350 |
+
if(result != EXIT_SUCCESS){
|
351 |
+
printf("interpreter->get_output_tensor() 1 failed !\n");
|
352 |
+
return EXIT_FAILURE;
|
353 |
+
}
|
354 |
+
|
355 |
+
}
|
356 |
+
|
357 |
+
float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
|
358 |
+
float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
|
359 |
+
float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
|
360 |
+
float var_invoketime = 0.0f;
|
361 |
+
for (auto time : invoke_time) {
|
362 |
+
var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
|
363 |
+
}
|
364 |
+
var_invoketime /= args.invoke_nums;
|
365 |
+
printf("=======================================\n");
|
366 |
+
printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
|
367 |
+
args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
|
368 |
+
printf("=======================================\n");
|
369 |
+
|
370 |
+
// post process
|
371 |
+
cv::Mat out_buffer(1,256*256, CV_32F, outdata0);
|
372 |
+
cv::Mat prediction_2d(256, 256, CV_32F, (void*)out_buffer.ptr<float>());
|
373 |
+
cv::Mat resized;
|
374 |
+
cv::resize(prediction_2d, resized, org_size, 0, 0, cv::INTER_CUBIC);
|
375 |
+
|
376 |
+
// 保存为图像
|
377 |
+
write_depth("depth_output.jpg", resized, false, 1);
|
378 |
+
|
379 |
+
// 保存为 PFM
|
380 |
+
write_pfm("depth_output.pfm", resized);
|
381 |
+
|
382 |
+
|
383 |
+
|
384 |
+
fast_interpreter->destory();
|
385 |
+
return 0;
|
386 |
+
}
|
387 |
+
|
388 |
+
|
389 |
+
int main(int argc, char* argv[]) {
|
390 |
+
Args args = parse_args(argc, argv);
|
391 |
+
return invoke(args);
|
392 |
+
}
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/models/midas_v2_w8a16.qnn216.ctx.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:cc4f6a5cdfb55ede7cfde5298734fc33221d440fe410b726bc9fdaca2ff6a667
|
3 |
+
size 27836416
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/run_test.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
from utils import write_pfm,write_depth,img_process
|
6 |
+
import aidlite
|
7 |
+
import time
|
8 |
+
import argparse
|
9 |
+
|
10 |
+
def out_process(prediction,target_size):
|
11 |
+
prediction = torch.nn.functional.interpolate(
|
12 |
+
prediction,
|
13 |
+
size=target_size,
|
14 |
+
mode="bicubic",
|
15 |
+
align_corners=False,
|
16 |
+
)
|
17 |
+
prediction = prediction.squeeze().detach().numpy()
|
18 |
+
return prediction
|
19 |
+
|
20 |
+
class run_qnn:
|
21 |
+
def __init__(self,qnn_path):
|
22 |
+
super().__init__()
|
23 |
+
self.model = aidlite.Model.create_instance(qnn_path)
|
24 |
+
if self.model is None:
|
25 |
+
print("Create model failed !")
|
26 |
+
return
|
27 |
+
|
28 |
+
self.config = aidlite.Config.create_instance()
|
29 |
+
if self.config is None:
|
30 |
+
print("build_interpretper_from_model_and_config failed !")
|
31 |
+
return
|
32 |
+
|
33 |
+
self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
|
34 |
+
self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
|
35 |
+
self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
|
36 |
+
# self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
|
37 |
+
self.config.is_quantify_model = 1
|
38 |
+
|
39 |
+
self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
|
40 |
+
if self.interpreter is None:
|
41 |
+
print("build_interpretper_from_model_and_config failed !")
|
42 |
+
return
|
43 |
+
input_shapes = [[1,256,256,3]]
|
44 |
+
output_shapes = [[1,256,256,1]]
|
45 |
+
self.model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
|
46 |
+
output_shapes, aidlite.DataType.TYPE_FLOAT32)
|
47 |
+
|
48 |
+
if self.interpreter is None:
|
49 |
+
print("build_interpretper_from_model_and_config failed !")
|
50 |
+
result = self.interpreter.init()
|
51 |
+
if result != 0:
|
52 |
+
print(f"interpreter init failed !")
|
53 |
+
result = self.interpreter.load_model()
|
54 |
+
if result != 0:
|
55 |
+
print("interpreter load model failed !")
|
56 |
+
|
57 |
+
print(" model load success!")
|
58 |
+
|
59 |
+
def __call__(self, input,invoke_nums):
|
60 |
+
self.interpreter.set_input_tensor(0,input)
|
61 |
+
invoke_time=[]
|
62 |
+
for i in range(invoke_nums):
|
63 |
+
result = self.interpreter.set_input_tensor(0, input.data)
|
64 |
+
if result != 0:
|
65 |
+
print("interpreter set_input_tensor() failed")
|
66 |
+
t1=time.time()
|
67 |
+
result = self.interpreter.invoke()
|
68 |
+
cost_time = (time.time()-t1)*1000
|
69 |
+
invoke_time.append(cost_time)
|
70 |
+
|
71 |
+
max_invoke_time = max(invoke_time)
|
72 |
+
min_invoke_time = min(invoke_time)
|
73 |
+
mean_invoke_time = sum(invoke_time)/invoke_nums
|
74 |
+
var_invoketime=np.var(invoke_time)
|
75 |
+
print("====================================")
|
76 |
+
print(f"QNN invoke time:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
|
77 |
+
print("====================================")
|
78 |
+
features_0 = self.interpreter.get_output_tensor(0).reshape(1,256,256,1).transpose(0,3,1,2)
|
79 |
+
return features_0
|
80 |
+
|
81 |
+
|
82 |
+
|
83 |
+
def run(args):
|
84 |
+
img_path = args.imgs
|
85 |
+
qnn_path = args.target_model
|
86 |
+
invoke_num=args.invoke_nums
|
87 |
+
print("Start processing...")
|
88 |
+
img_input,org_size = img_process(img_path)
|
89 |
+
|
90 |
+
qnn_model =run_qnn(qnn_path)
|
91 |
+
prediction_qnn = qnn_model(img_input.numpy().transpose(0,2,3,1),invoke_num)
|
92 |
+
prediction_qnn = torch.tensor(prediction_qnn)
|
93 |
+
qnn_process = out_process(prediction_qnn,org_size)
|
94 |
+
|
95 |
+
write_depth("./python/results.jpg", qnn_process, grayscale=False, bits=1)
|
96 |
+
write_pfm("./python/results.pfm", qnn_process.astype(np.float32))
|
97 |
+
print("Finished")
|
98 |
+
|
99 |
+
def parser_args():
|
100 |
+
parser = argparse.ArgumentParser(description="Run model benchmarks")
|
101 |
+
parser.add_argument('--target_model',type=str,default='./models/midas_v2_w8a16.qnn216.ctx.bin',help="Inference model path")
|
102 |
+
parser.add_argument('--imgs',type=str,default='./python/dog.jpg',help="Predict images path")
|
103 |
+
parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
|
104 |
+
parser.add_argument('--model_type',type=str,default='QNN',help="Run backend")
|
105 |
+
args = parser.parse_args()
|
106 |
+
return args
|
107 |
+
|
108 |
+
|
109 |
+
if __name__ =="__main__":
|
110 |
+
args = parser_args()
|
111 |
+
run(args)
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/transforms.py
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import math
|
4 |
+
|
5 |
+
|
6 |
+
def apply_min_size(sample, size, image_interpolation_method=cv2.INTER_AREA):
|
7 |
+
"""Rezise the sample to ensure the given size. Keeps aspect ratio.
|
8 |
+
|
9 |
+
Args:
|
10 |
+
sample (dict): sample
|
11 |
+
size (tuple): image size
|
12 |
+
|
13 |
+
Returns:
|
14 |
+
tuple: new size
|
15 |
+
"""
|
16 |
+
shape = list(sample["disparity"].shape)
|
17 |
+
|
18 |
+
if shape[0] >= size[0] and shape[1] >= size[1]:
|
19 |
+
return sample
|
20 |
+
|
21 |
+
scale = [0, 0]
|
22 |
+
scale[0] = size[0] / shape[0]
|
23 |
+
scale[1] = size[1] / shape[1]
|
24 |
+
|
25 |
+
scale = max(scale)
|
26 |
+
|
27 |
+
shape[0] = math.ceil(scale * shape[0])
|
28 |
+
shape[1] = math.ceil(scale * shape[1])
|
29 |
+
|
30 |
+
# resize
|
31 |
+
sample["image"] = cv2.resize(
|
32 |
+
sample["image"], tuple(shape[::-1]), interpolation=image_interpolation_method
|
33 |
+
)
|
34 |
+
|
35 |
+
sample["disparity"] = cv2.resize(
|
36 |
+
sample["disparity"], tuple(shape[::-1]), interpolation=cv2.INTER_NEAREST
|
37 |
+
)
|
38 |
+
sample["mask"] = cv2.resize(
|
39 |
+
sample["mask"].astype(np.float32),
|
40 |
+
tuple(shape[::-1]),
|
41 |
+
interpolation=cv2.INTER_NEAREST,
|
42 |
+
)
|
43 |
+
sample["mask"] = sample["mask"].astype(bool)
|
44 |
+
|
45 |
+
return tuple(shape)
|
46 |
+
|
47 |
+
|
48 |
+
class Resize(object):
|
49 |
+
"""Resize sample to given size (width, height).
|
50 |
+
"""
|
51 |
+
|
52 |
+
def __init__(
|
53 |
+
self,
|
54 |
+
width,
|
55 |
+
height,
|
56 |
+
resize_target=True,
|
57 |
+
keep_aspect_ratio=False,
|
58 |
+
ensure_multiple_of=1,
|
59 |
+
resize_method="lower_bound",
|
60 |
+
image_interpolation_method=cv2.INTER_AREA,
|
61 |
+
):
|
62 |
+
"""Init.
|
63 |
+
|
64 |
+
Args:
|
65 |
+
width (int): desired output width
|
66 |
+
height (int): desired output height
|
67 |
+
resize_target (bool, optional):
|
68 |
+
True: Resize the full sample (image, mask, target).
|
69 |
+
False: Resize image only.
|
70 |
+
Defaults to True.
|
71 |
+
keep_aspect_ratio (bool, optional):
|
72 |
+
True: Keep the aspect ratio of the input sample.
|
73 |
+
Output sample might not have the given width and height, and
|
74 |
+
resize behaviour depends on the parameter 'resize_method'.
|
75 |
+
Defaults to False.
|
76 |
+
ensure_multiple_of (int, optional):
|
77 |
+
Output width and height is constrained to be multiple of this parameter.
|
78 |
+
Defaults to 1.
|
79 |
+
resize_method (str, optional):
|
80 |
+
"lower_bound": Output will be at least as large as the given size.
|
81 |
+
"upper_bound": Output will be at max as large as the given size. (Output size might be smaller than given size.)
|
82 |
+
"minimal": Scale as least as possible. (Output size might be smaller than given size.)
|
83 |
+
Defaults to "lower_bound".
|
84 |
+
"""
|
85 |
+
self.__width = width
|
86 |
+
self.__height = height
|
87 |
+
|
88 |
+
self.__resize_target = resize_target
|
89 |
+
self.__keep_aspect_ratio = keep_aspect_ratio
|
90 |
+
self.__multiple_of = ensure_multiple_of
|
91 |
+
self.__resize_method = resize_method
|
92 |
+
self.__image_interpolation_method = image_interpolation_method
|
93 |
+
|
94 |
+
def constrain_to_multiple_of(self, x, min_val=0, max_val=None):
|
95 |
+
y = (np.round(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
96 |
+
|
97 |
+
if max_val is not None and y > max_val:
|
98 |
+
y = (np.floor(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
99 |
+
|
100 |
+
if y < min_val:
|
101 |
+
y = (np.ceil(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
102 |
+
|
103 |
+
return y
|
104 |
+
|
105 |
+
def get_size(self, width, height):
|
106 |
+
# determine new height and width
|
107 |
+
scale_height = self.__height / height
|
108 |
+
scale_width = self.__width / width
|
109 |
+
|
110 |
+
if self.__keep_aspect_ratio:
|
111 |
+
if self.__resize_method == "lower_bound":
|
112 |
+
# scale such that output size is lower bound
|
113 |
+
if scale_width > scale_height:
|
114 |
+
# fit width
|
115 |
+
scale_height = scale_width
|
116 |
+
else:
|
117 |
+
# fit height
|
118 |
+
scale_width = scale_height
|
119 |
+
elif self.__resize_method == "upper_bound":
|
120 |
+
# scale such that output size is upper bound
|
121 |
+
if scale_width < scale_height:
|
122 |
+
# fit width
|
123 |
+
scale_height = scale_width
|
124 |
+
else:
|
125 |
+
# fit height
|
126 |
+
scale_width = scale_height
|
127 |
+
elif self.__resize_method == "minimal":
|
128 |
+
# scale as least as possbile
|
129 |
+
if abs(1 - scale_width) < abs(1 - scale_height):
|
130 |
+
# fit width
|
131 |
+
scale_height = scale_width
|
132 |
+
else:
|
133 |
+
# fit height
|
134 |
+
scale_width = scale_height
|
135 |
+
else:
|
136 |
+
raise ValueError(
|
137 |
+
f"resize_method {self.__resize_method} not implemented"
|
138 |
+
)
|
139 |
+
|
140 |
+
if self.__resize_method == "lower_bound":
|
141 |
+
new_height = self.constrain_to_multiple_of(
|
142 |
+
scale_height * height, min_val=self.__height
|
143 |
+
)
|
144 |
+
new_width = self.constrain_to_multiple_of(
|
145 |
+
scale_width * width, min_val=self.__width
|
146 |
+
)
|
147 |
+
elif self.__resize_method == "upper_bound":
|
148 |
+
new_height = self.constrain_to_multiple_of(
|
149 |
+
scale_height * height, max_val=self.__height
|
150 |
+
)
|
151 |
+
new_width = self.constrain_to_multiple_of(
|
152 |
+
scale_width * width, max_val=self.__width
|
153 |
+
)
|
154 |
+
elif self.__resize_method == "minimal":
|
155 |
+
new_height = self.constrain_to_multiple_of(scale_height * height)
|
156 |
+
new_width = self.constrain_to_multiple_of(scale_width * width)
|
157 |
+
else:
|
158 |
+
raise ValueError(f"resize_method {self.__resize_method} not implemented")
|
159 |
+
|
160 |
+
return (new_width, new_height)
|
161 |
+
|
162 |
+
def __call__(self, sample):
|
163 |
+
width, height = self.get_size(
|
164 |
+
sample["image"].shape[1], sample["image"].shape[0]
|
165 |
+
)
|
166 |
+
|
167 |
+
# resize sample
|
168 |
+
sample["image"] = cv2.resize(
|
169 |
+
sample["image"],
|
170 |
+
(width, height),
|
171 |
+
interpolation=self.__image_interpolation_method,
|
172 |
+
)
|
173 |
+
|
174 |
+
if self.__resize_target:
|
175 |
+
if "disparity" in sample:
|
176 |
+
sample["disparity"] = cv2.resize(
|
177 |
+
sample["disparity"],
|
178 |
+
(width, height),
|
179 |
+
interpolation=cv2.INTER_NEAREST,
|
180 |
+
)
|
181 |
+
|
182 |
+
if "depth" in sample:
|
183 |
+
sample["depth"] = cv2.resize(
|
184 |
+
sample["depth"], (width, height), interpolation=cv2.INTER_NEAREST
|
185 |
+
)
|
186 |
+
|
187 |
+
sample["mask"] = cv2.resize(
|
188 |
+
sample["mask"].astype(np.float32),
|
189 |
+
(width, height),
|
190 |
+
interpolation=cv2.INTER_NEAREST,
|
191 |
+
)
|
192 |
+
sample["mask"] = sample["mask"].astype(bool)
|
193 |
+
|
194 |
+
return sample
|
195 |
+
|
196 |
+
|
197 |
+
class NormalizeImage(object):
|
198 |
+
"""Normlize image by given mean and std.
|
199 |
+
"""
|
200 |
+
|
201 |
+
def __init__(self, mean, std):
|
202 |
+
self.__mean = mean
|
203 |
+
self.__std = std
|
204 |
+
|
205 |
+
def __call__(self, sample):
|
206 |
+
sample["image"] = (sample["image"] - self.__mean) / self.__std
|
207 |
+
|
208 |
+
return sample
|
209 |
+
|
210 |
+
|
211 |
+
class PrepareForNet(object):
|
212 |
+
"""Prepare sample for usage as network input.
|
213 |
+
"""
|
214 |
+
|
215 |
+
def __init__(self):
|
216 |
+
pass
|
217 |
+
|
218 |
+
def __call__(self, sample):
|
219 |
+
image = np.transpose(sample["image"], (2, 0, 1))
|
220 |
+
sample["image"] = np.ascontiguousarray(image).astype(np.float32)
|
221 |
+
|
222 |
+
if "mask" in sample:
|
223 |
+
sample["mask"] = sample["mask"].astype(np.float32)
|
224 |
+
sample["mask"] = np.ascontiguousarray(sample["mask"])
|
225 |
+
|
226 |
+
if "disparity" in sample:
|
227 |
+
disparity = sample["disparity"].astype(np.float32)
|
228 |
+
sample["disparity"] = np.ascontiguousarray(disparity)
|
229 |
+
|
230 |
+
if "depth" in sample:
|
231 |
+
depth = sample["depth"].astype(np.float32)
|
232 |
+
sample["depth"] = np.ascontiguousarray(depth)
|
233 |
+
|
234 |
+
return sample
|
model_farm_midas_v2_qcs6490_qnn2.16_w8a16_aidlite/python/utils.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
|
6 |
+
from transforms import Resize, NormalizeImage, PrepareForNet
|
7 |
+
|
8 |
+
from torchvision.transforms import Compose
|
9 |
+
import sys
|
10 |
+
first_execution = True
|
11 |
+
def img_process(img_path):
|
12 |
+
global first_execution
|
13 |
+
first_execution = False
|
14 |
+
net_w, net_h = 256, 256
|
15 |
+
resize_mode = "upper_bound"
|
16 |
+
normalization = NormalizeImage(
|
17 |
+
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
|
18 |
+
)
|
19 |
+
transform = Compose(
|
20 |
+
[
|
21 |
+
Resize(
|
22 |
+
net_w,
|
23 |
+
net_h,
|
24 |
+
resize_target=None,
|
25 |
+
keep_aspect_ratio=False,
|
26 |
+
ensure_multiple_of=32,
|
27 |
+
resize_method=resize_mode,
|
28 |
+
image_interpolation_method=cv2.INTER_CUBIC,
|
29 |
+
),
|
30 |
+
normalization,
|
31 |
+
PrepareForNet(),
|
32 |
+
]
|
33 |
+
)
|
34 |
+
# image = utils.read_image(img_path) # in [0, 1]
|
35 |
+
image = cv2.imread(img_path)
|
36 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) / 255.0
|
37 |
+
org_size= image.shape[:2]
|
38 |
+
image = transform({"image": image})["image"]
|
39 |
+
sample = torch.from_numpy(image).to("cpu").unsqueeze(0)
|
40 |
+
height, width = sample.shape[2:]
|
41 |
+
print(f"Input resized to {width}x{height} before entering the encoder")
|
42 |
+
|
43 |
+
return sample,org_size
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
def write_depth(path, depth, grayscale=False, bits=1):
|
48 |
+
if not grayscale:
|
49 |
+
bits = 1
|
50 |
+
|
51 |
+
if not np.isfinite(depth).all():
|
52 |
+
depth=np.nan_to_num(depth, nan=0.0, posinf=0.0, neginf=0.0)
|
53 |
+
print("WARNING: Non-finite depth values present")
|
54 |
+
|
55 |
+
depth_min = depth.min()
|
56 |
+
depth_max = depth.max()
|
57 |
+
|
58 |
+
max_val = (2**(8*bits))-1
|
59 |
+
|
60 |
+
if depth_max - depth_min > np.finfo("float").eps:
|
61 |
+
out = max_val * (depth - depth_min) / (depth_max - depth_min)
|
62 |
+
else:
|
63 |
+
out = np.zeros(depth.shape, dtype=depth.dtype)
|
64 |
+
|
65 |
+
# print("out :",out.shape,out)
|
66 |
+
if not grayscale:
|
67 |
+
out = cv2.applyColorMap(np.uint8(out), cv2.COLORMAP_INFERNO)
|
68 |
+
|
69 |
+
if bits == 1:
|
70 |
+
cv2.imwrite(path , out.astype("uint8"))
|
71 |
+
elif bits == 2:
|
72 |
+
cv2.imwrite(path , out.astype("uint16"))
|
73 |
+
|
74 |
+
return
|
75 |
+
|
76 |
+
def write_pfm(path, image, scale=1):
|
77 |
+
with open(path, "wb") as file:
|
78 |
+
color = None
|
79 |
+
|
80 |
+
if image.dtype.name != "float32":
|
81 |
+
raise Exception("Image dtype must be float32.")
|
82 |
+
|
83 |
+
image = np.flipud(image)
|
84 |
+
|
85 |
+
if len(image.shape) == 3 and image.shape[2] == 3: # color image
|
86 |
+
color = True
|
87 |
+
elif (
|
88 |
+
len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1
|
89 |
+
): # greyscale
|
90 |
+
color = False
|
91 |
+
else:
|
92 |
+
raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")
|
93 |
+
|
94 |
+
file.write("PF\n" if color else "Pf\n".encode())
|
95 |
+
file.write("%d %d\n".encode() % (image.shape[1], image.shape[0]))
|
96 |
+
|
97 |
+
endian = image.dtype.byteorder
|
98 |
+
|
99 |
+
if endian == "<" or endian == "=" and sys.byteorder == "little":
|
100 |
+
scale = -scale
|
101 |
+
|
102 |
+
file.write("%f\n".encode() % scale)
|
103 |
+
|
104 |
+
image.tofile(file)
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## Model Information
|
2 |
+
|
3 |
+
### Source model
|
4 |
+
- Input shape: 1x3x256x256
|
5 |
+
- Number of parameters: 20.33M
|
6 |
+
- Model size: 82.17M
|
7 |
+
- Output shape: 1x1x256x256
|
8 |
+
|
9 |
+
Source model repository: [midas](https://github.com/isl-org/MiDaS/tree/master)
|
10 |
+
|
11 |
+
### Converted model
|
12 |
+
|
13 |
+
- Precision: FP16
|
14 |
+
- Backend: QNN2.16
|
15 |
+
- Target Device: SNM972 QCS8550
|
16 |
+
|
17 |
+
## Inference with AidLite SDK
|
18 |
+
|
19 |
+
### SDK installation
|
20 |
+
Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
|
21 |
+
|
22 |
+
- Install AidLite SDK
|
23 |
+
|
24 |
+
```bash
|
25 |
+
# Install the appropriate version of the aidlite sdk
|
26 |
+
sudo aid-pkg update
|
27 |
+
sudo aid-pkg install aidlite-sdk
|
28 |
+
# Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
|
29 |
+
sudo aid-pkg install aidlite-{QNN VERSION}
|
30 |
+
```
|
31 |
+
|
32 |
+
- Verify AidLite SDK
|
33 |
+
|
34 |
+
```bash
|
35 |
+
# aidlite sdk c++ check
|
36 |
+
python3 -c "import aidlite ; print(aidlite.get_library_version())"
|
37 |
+
|
38 |
+
# aidlite sdk python check
|
39 |
+
python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
|
40 |
+
```
|
41 |
+
|
42 |
+
### Run Demo
|
43 |
+
#### python
|
44 |
+
```bash
|
45 |
+
cd model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite
|
46 |
+
python3 python/run_test.py --target_model ./models/midas_v2_fp16.qnn216.ctx.bin --imgs ./python/dog.jpg --invoke_nums 10
|
47 |
+
```
|
48 |
+
|
49 |
+
#### c++
|
50 |
+
```bash
|
51 |
+
cd midas_v2/model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp
|
52 |
+
mkdir build && cd build
|
53 |
+
cmake ..
|
54 |
+
make
|
55 |
+
./run_test
|
56 |
+
```
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp/CMakeLists.txt
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
cmake_minimum_required (VERSION 3.5)
|
2 |
+
project("run_test")
|
3 |
+
|
4 |
+
find_package(OpenCV REQUIRED)
|
5 |
+
|
6 |
+
message(STATUS "oPENCV Library status:")
|
7 |
+
message(STATUS ">version:${OpenCV_VERSION}")
|
8 |
+
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
|
9 |
+
|
10 |
+
set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
|
11 |
+
|
12 |
+
include_directories(
|
13 |
+
/usr/local/include
|
14 |
+
/usr/include/opencv4
|
15 |
+
)
|
16 |
+
|
17 |
+
link_directories(
|
18 |
+
/usr/local/lib/
|
19 |
+
)
|
20 |
+
|
21 |
+
file(GLOB SRC_LISTS
|
22 |
+
${CMAKE_CURRENT_SOURCE_DIR}/run_test.cpp
|
23 |
+
)
|
24 |
+
|
25 |
+
add_executable(run_test ${SRC_LISTS})
|
26 |
+
|
27 |
+
target_link_libraries(run_test
|
28 |
+
aidlite
|
29 |
+
${OpenCV_LIBS}
|
30 |
+
pthread
|
31 |
+
jsoncpp
|
32 |
+
)
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/cpp/run_test.cpp
ADDED
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <iostream>
|
2 |
+
#include <fstream>
|
3 |
+
#include <opencv2/opencv.hpp>
|
4 |
+
#include <aidlux/aidlite/aidlite.hpp>
|
5 |
+
#include <vector>
|
6 |
+
#include <numeric>
|
7 |
+
#include <cmath>
|
8 |
+
#include <jsoncpp/json/json.h>
|
9 |
+
|
10 |
+
using namespace cv;
|
11 |
+
using namespace std;
|
12 |
+
using namespace Aidlux::Aidlite;
|
13 |
+
|
14 |
+
const int net_w = 256;
|
15 |
+
const int net_h = 256;
|
16 |
+
|
17 |
+
const std::vector<float> mean_vals = {0.485f, 0.456f, 0.406f};
|
18 |
+
const std::vector<float> std_vals = {0.229f, 0.224f, 0.225f};
|
19 |
+
|
20 |
+
|
21 |
+
struct Args {
|
22 |
+
std::string target_model = "../../models/midas_v2_fp16.qnn216.ctx.bin";
|
23 |
+
std::string imgs = "../dog.jpg";
|
24 |
+
int invoke_nums = 10;
|
25 |
+
std::string model_type = "QNN";
|
26 |
+
};
|
27 |
+
|
28 |
+
|
29 |
+
Args parse_args(int argc, char* argv[]) {
|
30 |
+
Args args;
|
31 |
+
for (int i = 1; i < argc; ++i) {
|
32 |
+
std::string arg = argv[i];
|
33 |
+
if (arg == "--target_model" && i + 1 < argc) {
|
34 |
+
args.target_model = argv[++i];
|
35 |
+
} else if (arg == "--imgs" && i + 1 < argc) {
|
36 |
+
args.imgs = argv[++i];
|
37 |
+
} else if (arg == "--invoke_nums" && i + 1 < argc) {
|
38 |
+
args.invoke_nums = std::stoi(argv[++i]);
|
39 |
+
} else if (arg == "--model_type" && i + 1 < argc) {
|
40 |
+
args.model_type = argv[++i];
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return args;
|
44 |
+
}
|
45 |
+
|
46 |
+
std::string to_lower(const std::string& str) {
|
47 |
+
std::string lower_str = str;
|
48 |
+
std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
|
49 |
+
return std::tolower(c);
|
50 |
+
});
|
51 |
+
return lower_str;
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
|
56 |
+
|
57 |
+
int current_coordinate[4] = {0, 0, 0, 0};
|
58 |
+
for(int a = 0; a < src_dims[0]; ++a){
|
59 |
+
current_coordinate[0] = a;
|
60 |
+
for(int b = 0; b < src_dims[1]; ++b){
|
61 |
+
current_coordinate[1] = b;
|
62 |
+
for(int c = 0; c < src_dims[2]; ++c){
|
63 |
+
current_coordinate[2] = c;
|
64 |
+
for(int d = 0; d < src_dims[3]; ++d){
|
65 |
+
current_coordinate[3] = d;
|
66 |
+
|
67 |
+
int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
|
68 |
+
current_coordinate[1]*src_dims[2]*src_dims[3] +
|
69 |
+
current_coordinate[2]*src_dims[3] +
|
70 |
+
current_coordinate[3];
|
71 |
+
|
72 |
+
int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
73 |
+
current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
74 |
+
current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
75 |
+
current_coordinate[tsp_dims[3]];
|
76 |
+
|
77 |
+
dest[new_index] = src[old_index];
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
return EXIT_SUCCESS;
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
// 替代 np.nan_to_num
|
88 |
+
void sanitizeDepthMap(cv::Mat& depth) {
|
89 |
+
for (int y = 0; y < depth.rows; ++y) {
|
90 |
+
float* row = depth.ptr<float>(y);
|
91 |
+
for (int x = 0; x < depth.cols; ++x) {
|
92 |
+
float val = row[x];
|
93 |
+
if (!std::isfinite(val)) {
|
94 |
+
row[x] = 0.0f;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
// 等效于 Python write_depth
|
101 |
+
void write_depth(const std::string& path, const cv::Mat& input_depth, bool grayscale = false, int bits = 1) {
|
102 |
+
CV_Assert(input_depth.type() == CV_32FC1);
|
103 |
+
|
104 |
+
// 拷贝 + 处理非法值
|
105 |
+
cv::Mat depth = input_depth.clone();
|
106 |
+
sanitizeDepthMap(depth);
|
107 |
+
|
108 |
+
double minVal, maxVal;
|
109 |
+
cv::minMaxLoc(depth, &minVal, &maxVal);
|
110 |
+
|
111 |
+
double max_val = (1 << (8 * bits)) - 1;
|
112 |
+
cv::Mat out;
|
113 |
+
|
114 |
+
if (maxVal - minVal > std::numeric_limits<float>::epsilon()) {
|
115 |
+
// 归一化并映射到位深范围
|
116 |
+
out = (depth - minVal) * (max_val / (maxVal - minVal));
|
117 |
+
} else {
|
118 |
+
out = cv::Mat::zeros(depth.size(), CV_32F);
|
119 |
+
}
|
120 |
+
|
121 |
+
if (!grayscale) {
|
122 |
+
out.convertTo(out, CV_8UC1);
|
123 |
+
cv::applyColorMap(out, out, cv::COLORMAP_INFERNO);
|
124 |
+
}
|
125 |
+
|
126 |
+
if (bits == 1) {
|
127 |
+
out.convertTo(out, CV_8U);
|
128 |
+
} else if (bits == 2) {
|
129 |
+
out.convertTo(out, CV_16U);
|
130 |
+
}
|
131 |
+
|
132 |
+
cv::imwrite(path, out);
|
133 |
+
}
|
134 |
+
|
135 |
+
// 等效于 Python write_pfm
|
136 |
+
void write_pfm(const std::string& path, const cv::Mat& image, float scale = 1.0f) {
|
137 |
+
CV_Assert(image.type() == CV_32FC1 || image.type() == CV_32FC3);
|
138 |
+
|
139 |
+
std::ofstream file(path, std::ios::binary);
|
140 |
+
if (!file.is_open()) {
|
141 |
+
std::cerr << "Failed to open file for writing PFM: " << path << std::endl;
|
142 |
+
return;
|
143 |
+
}
|
144 |
+
|
145 |
+
int width = image.cols;
|
146 |
+
int height = image.rows;
|
147 |
+
int channels = image.channels();
|
148 |
+
bool color = (channels == 3);
|
149 |
+
|
150 |
+
file << (color ? "PF" : "Pf") << "\n";
|
151 |
+
file << width << " " << height << "\n";
|
152 |
+
|
153 |
+
// Endianness: negative = little-endian
|
154 |
+
uint16_t endian_test = 0x1;
|
155 |
+
bool is_little_endian = *(reinterpret_cast<uint8_t*>(&endian_test)) == 0x1;
|
156 |
+
if (is_little_endian) {
|
157 |
+
scale = -scale;
|
158 |
+
}
|
159 |
+
|
160 |
+
file << scale << "\n";
|
161 |
+
|
162 |
+
// Flip vertically (OpenCV top-left origin -> PFM bottom-left origin)
|
163 |
+
cv::Mat flipped;
|
164 |
+
cv::flip(image, flipped, 0);
|
165 |
+
|
166 |
+
// Write raw data
|
167 |
+
file.write(reinterpret_cast<const char*>(flipped.data), flipped.total() * channels * sizeof(float));
|
168 |
+
file.close();
|
169 |
+
}
|
170 |
+
|
171 |
+
|
172 |
+
// ======================= Normalize =======================
|
173 |
+
void normalize(cv::Mat& image) {
|
174 |
+
CV_Assert(image.type() == CV_32FC3);
|
175 |
+
int rows = image.rows;
|
176 |
+
int cols = image.cols;
|
177 |
+
|
178 |
+
for (int y = 0; y < rows; ++y) {
|
179 |
+
cv::Vec3f* row = image.ptr<cv::Vec3f>(y);
|
180 |
+
for (int x = 0; x < cols; ++x) {
|
181 |
+
for (int c = 0; c < 3; ++c) {
|
182 |
+
row[x][c] = (row[x][c] - mean_vals[c]) / std_vals[c];
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
cv::Mat hwc_to_chw(const cv::Mat& image) {
|
189 |
+
std::vector<cv::Mat> channels(3);
|
190 |
+
cv::split(image, channels);
|
191 |
+
|
192 |
+
cv::Mat chw(3, image.rows * image.cols, CV_32F);
|
193 |
+
for (int c = 0; c < 3; ++c) {
|
194 |
+
memcpy(chw.ptr(c), channels[c].data, image.rows * image.cols * sizeof(float));
|
195 |
+
}
|
196 |
+
|
197 |
+
return chw;
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
bool first_execution = true;
|
202 |
+
cv::Mat img_process(const cv::Mat image_bgr, cv::Size& org_size_out) {
|
203 |
+
first_execution = false;
|
204 |
+
|
205 |
+
cv::Mat image_rgb;
|
206 |
+
cv::cvtColor(image_bgr, image_rgb, cv::COLOR_BGR2RGB);
|
207 |
+
image_rgb.convertTo(image_rgb, CV_32FC3, 1.0 / 255.0);
|
208 |
+
|
209 |
+
// 2. Save original size
|
210 |
+
org_size_out = image_rgb.size(); // H x W
|
211 |
+
|
212 |
+
// 3. Resize to 256x256 using cubic interpolation
|
213 |
+
cv::resize(image_rgb, image_rgb, cv::Size(net_w, net_h), 0, 0, cv::INTER_CUBIC);
|
214 |
+
|
215 |
+
// 4. Normalize using mean/std
|
216 |
+
normalize(image_rgb);
|
217 |
+
|
218 |
+
// 5. Convert HWC to CHW
|
219 |
+
cv::Mat chw = hwc_to_chw(image_rgb);
|
220 |
+
|
221 |
+
// 6. Add batch dimension: [1, C, H, W] → reshape to 1x3xHxW style float array
|
222 |
+
cv::Mat input_tensor(1, 3 * net_h * net_w, CV_32F);
|
223 |
+
memcpy(input_tensor.ptr<float>(), chw.data, 3 * net_h * net_w * sizeof(float));
|
224 |
+
|
225 |
+
std::cout << "Input resized to " << net_w << "x" << net_h << " before entering the encoder" << std::endl;
|
226 |
+
|
227 |
+
return input_tensor;
|
228 |
+
}
|
229 |
+
|
230 |
+
|
231 |
+
float* matToFloatPtr(const cv::Mat& input_mat, bool normalize = true) {
|
232 |
+
// 检查连续性
|
233 |
+
cv::Mat mat = input_mat;
|
234 |
+
if (!mat.isContinuous()) {
|
235 |
+
mat = mat.clone();
|
236 |
+
}
|
237 |
+
|
238 |
+
// 分配内存
|
239 |
+
int total_pixels = mat.rows * mat.cols;
|
240 |
+
int channels = mat.channels();
|
241 |
+
float* float_data = new float[total_pixels * channels];
|
242 |
+
|
243 |
+
// 根据数据类型转换
|
244 |
+
if (mat.type() == CV_8UC1 || mat.type() == CV_8UC3) {
|
245 |
+
uchar* ptr = mat.ptr<uchar>(0);
|
246 |
+
for (int i = 0; i < total_pixels * channels; ++i) {
|
247 |
+
float_data[i] = normalize ? (static_cast<float>(ptr[i]) / 255.0f) : ptr[i];
|
248 |
+
}
|
249 |
+
} else if (mat.type() == CV_32FC1 || mat.type() == CV_32FC3) {
|
250 |
+
float* ptr = mat.ptr<float>(0);
|
251 |
+
std::memcpy(float_data, ptr, total_pixels * channels * sizeof(float));
|
252 |
+
} else {
|
253 |
+
delete[] float_data;
|
254 |
+
return nullptr; // 不支持的类型
|
255 |
+
}
|
256 |
+
|
257 |
+
return float_data;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
int invoke(const Args& args) {
|
262 |
+
std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
|
263 |
+
<< "Image Path: " << args.imgs << "\n"
|
264 |
+
<< "Inference Nums: " << args.invoke_nums << "\n"
|
265 |
+
<< "Model Type: " << args.model_type << "\n";
|
266 |
+
Model* model = Model::create_instance(args.target_model);
|
267 |
+
if(model == nullptr){
|
268 |
+
printf("Create model failed !\n");
|
269 |
+
return EXIT_FAILURE;
|
270 |
+
}
|
271 |
+
Config* config = Config::create_instance();
|
272 |
+
if(config == nullptr){
|
273 |
+
printf("Create config failed !\n");
|
274 |
+
return EXIT_FAILURE;
|
275 |
+
}
|
276 |
+
config->implement_type = ImplementType::TYPE_LOCAL;
|
277 |
+
std::string model_type_lower = to_lower(args.model_type);
|
278 |
+
if (model_type_lower == "qnn"){
|
279 |
+
config->framework_type = FrameworkType::TYPE_QNN;
|
280 |
+
} else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
|
281 |
+
config->framework_type = FrameworkType::TYPE_SNPE2;
|
282 |
+
}
|
283 |
+
config->accelerate_type = AccelerateType::TYPE_DSP;
|
284 |
+
config->is_quantify_model = 1;
|
285 |
+
|
286 |
+
unsigned int model_h = 256;
|
287 |
+
unsigned int model_w = 256;
|
288 |
+
std::vector<std::vector<uint32_t>> input_shapes = {{1,model_h,model_w,3}};
|
289 |
+
std::vector<std::vector<uint32_t>> output_shapes = {{1,model_h,model_w,1}};
|
290 |
+
model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
|
291 |
+
std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
|
292 |
+
if(fast_interpreter == nullptr){
|
293 |
+
printf("build_interpretper_from_model_and_config failed !\n");
|
294 |
+
return EXIT_FAILURE;
|
295 |
+
}
|
296 |
+
int result = fast_interpreter->init();
|
297 |
+
if(result != EXIT_SUCCESS){
|
298 |
+
printf("interpreter->init() failed !\n");
|
299 |
+
return EXIT_FAILURE;
|
300 |
+
}
|
301 |
+
// load model
|
302 |
+
fast_interpreter->load_model();
|
303 |
+
if(result != EXIT_SUCCESS){
|
304 |
+
printf("interpreter->load_model() failed !\n");
|
305 |
+
return EXIT_FAILURE;
|
306 |
+
}
|
307 |
+
printf("detect model load success!\n");
|
308 |
+
|
309 |
+
cv::Mat frame = cv::imread(args.imgs);
|
310 |
+
if (frame.empty()) {
|
311 |
+
printf("detect image load failed!\n");
|
312 |
+
return 1;
|
313 |
+
}
|
314 |
+
printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
|
315 |
+
cv::Mat input_data;
|
316 |
+
cv::Mat frame_clone = frame.clone();
|
317 |
+
int h = frame_clone.rows;
|
318 |
+
int w = frame_clone.cols;
|
319 |
+
cv::Size org_size(w, h);
|
320 |
+
cv::Size org_size0(256, 256);
|
321 |
+
|
322 |
+
cv::Mat input_tensor = img_process(frame_clone, org_size0);
|
323 |
+
float* float_data = matToFloatPtr(input_tensor);
|
324 |
+
unsigned int src_dims[4] = {1, 3, 256, 256};
|
325 |
+
unsigned int tsp_dims[4] = {0,2,3,1};
|
326 |
+
unsigned int stride_data_num = 1*256*256*3;
|
327 |
+
float* format_data = new float[stride_data_num];
|
328 |
+
transpose(float_data, src_dims, tsp_dims, format_data);
|
329 |
+
cv::Mat origin_buffer(3,256*256, CV_32F, format_data);
|
330 |
+
|
331 |
+
float *outdata0 = nullptr;
|
332 |
+
std::vector<float> invoke_time;
|
333 |
+
for (int i = 0; i < args.invoke_nums; ++i) {
|
334 |
+
result = fast_interpreter->set_input_tensor(0, origin_buffer.data);
|
335 |
+
if(result != EXIT_SUCCESS){
|
336 |
+
printf("interpreter->set_input_tensor() failed !\n");
|
337 |
+
return EXIT_FAILURE;
|
338 |
+
}
|
339 |
+
auto t1 = std::chrono::high_resolution_clock::now();
|
340 |
+
result = fast_interpreter->invoke();
|
341 |
+
auto t2 = std::chrono::high_resolution_clock::now();
|
342 |
+
std::chrono::duration<double> cost_time = t2 - t1;
|
343 |
+
invoke_time.push_back(cost_time.count() * 1000);
|
344 |
+
if(result != EXIT_SUCCESS){
|
345 |
+
printf("interpreter->invoke() failed !\n");
|
346 |
+
return EXIT_FAILURE;
|
347 |
+
}
|
348 |
+
uint32_t out_data_0 = 0;
|
349 |
+
result = fast_interpreter->get_output_tensor(0, (void**)&outdata0, &out_data_0);
|
350 |
+
if(result != EXIT_SUCCESS){
|
351 |
+
printf("interpreter->get_output_tensor() 1 failed !\n");
|
352 |
+
return EXIT_FAILURE;
|
353 |
+
}
|
354 |
+
|
355 |
+
}
|
356 |
+
|
357 |
+
float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
|
358 |
+
float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
|
359 |
+
float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
|
360 |
+
float var_invoketime = 0.0f;
|
361 |
+
for (auto time : invoke_time) {
|
362 |
+
var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
|
363 |
+
}
|
364 |
+
var_invoketime /= args.invoke_nums;
|
365 |
+
printf("=======================================\n");
|
366 |
+
printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
|
367 |
+
args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
|
368 |
+
printf("=======================================\n");
|
369 |
+
|
370 |
+
// post process
|
371 |
+
cv::Mat out_buffer(1,256*256, CV_32F, outdata0);
|
372 |
+
cv::Mat prediction_2d(256, 256, CV_32F, (void*)out_buffer.ptr<float>());
|
373 |
+
cv::Mat resized;
|
374 |
+
cv::resize(prediction_2d, resized, org_size, 0, 0, cv::INTER_CUBIC);
|
375 |
+
|
376 |
+
// 保存为图像
|
377 |
+
write_depth("depth_output.jpg", resized, false, 1);
|
378 |
+
|
379 |
+
// 保存为 PFM
|
380 |
+
write_pfm("depth_output.pfm", resized);
|
381 |
+
|
382 |
+
|
383 |
+
|
384 |
+
fast_interpreter->destory();
|
385 |
+
return 0;
|
386 |
+
}
|
387 |
+
|
388 |
+
|
389 |
+
int main(int argc, char* argv[]) {
|
390 |
+
Args args = parse_args(argc, argv);
|
391 |
+
return invoke(args);
|
392 |
+
}
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/models/midas_v2_fp16.qnn216.ctx.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:02f972176f66995cd0e7e3da5cab3467911acd2ccf0f64612d2755a7884798cc
|
3 |
+
size 37268200
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/run_test.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
from utils import write_pfm,write_depth,img_process
|
6 |
+
import aidlite
|
7 |
+
import time
|
8 |
+
import argparse
|
9 |
+
|
10 |
+
def out_process(prediction,target_size):
|
11 |
+
prediction = torch.nn.functional.interpolate(
|
12 |
+
prediction,
|
13 |
+
size=target_size,
|
14 |
+
mode="bicubic",
|
15 |
+
align_corners=False,
|
16 |
+
)
|
17 |
+
prediction = prediction.squeeze().detach().numpy()
|
18 |
+
return prediction
|
19 |
+
|
20 |
+
class run_qnn:
|
21 |
+
def __init__(self,qnn_path):
|
22 |
+
super().__init__()
|
23 |
+
self.model = aidlite.Model.create_instance(qnn_path)
|
24 |
+
if self.model is None:
|
25 |
+
print("Create model failed !")
|
26 |
+
return
|
27 |
+
|
28 |
+
self.config = aidlite.Config.create_instance()
|
29 |
+
if self.config is None:
|
30 |
+
print("build_interpretper_from_model_and_config failed !")
|
31 |
+
return
|
32 |
+
|
33 |
+
self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
|
34 |
+
self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
|
35 |
+
self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
|
36 |
+
# self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
|
37 |
+
self.config.is_quantify_model = 1
|
38 |
+
|
39 |
+
self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
|
40 |
+
if self.interpreter is None:
|
41 |
+
print("build_interpretper_from_model_and_config failed !")
|
42 |
+
return
|
43 |
+
input_shapes = [[1,256,256,3]]
|
44 |
+
output_shapes = [[1,256,256,1]]
|
45 |
+
self.model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
|
46 |
+
output_shapes, aidlite.DataType.TYPE_FLOAT32)
|
47 |
+
|
48 |
+
if self.interpreter is None:
|
49 |
+
print("build_interpretper_from_model_and_config failed !")
|
50 |
+
result = self.interpreter.init()
|
51 |
+
if result != 0:
|
52 |
+
print(f"interpreter init failed !")
|
53 |
+
result = self.interpreter.load_model()
|
54 |
+
if result != 0:
|
55 |
+
print("interpreter load model failed !")
|
56 |
+
|
57 |
+
print(" model load success!")
|
58 |
+
|
59 |
+
def __call__(self, input,invoke_nums):
|
60 |
+
self.interpreter.set_input_tensor(0,input)
|
61 |
+
invoke_time=[]
|
62 |
+
for i in range(invoke_nums):
|
63 |
+
result = self.interpreter.set_input_tensor(0, input.data)
|
64 |
+
if result != 0:
|
65 |
+
print("interpreter set_input_tensor() failed")
|
66 |
+
t1=time.time()
|
67 |
+
result = self.interpreter.invoke()
|
68 |
+
cost_time = (time.time()-t1)*1000
|
69 |
+
invoke_time.append(cost_time)
|
70 |
+
|
71 |
+
max_invoke_time = max(invoke_time)
|
72 |
+
min_invoke_time = min(invoke_time)
|
73 |
+
mean_invoke_time = sum(invoke_time)/invoke_nums
|
74 |
+
var_invoketime=np.var(invoke_time)
|
75 |
+
print("====================================")
|
76 |
+
print(f"QNN invoke time:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
|
77 |
+
print("====================================")
|
78 |
+
features_0 = self.interpreter.get_output_tensor(0).reshape(1,256,256,1).transpose(0,3,1,2)
|
79 |
+
return features_0
|
80 |
+
|
81 |
+
|
82 |
+
|
83 |
+
def run(args):
|
84 |
+
img_path = args.imgs
|
85 |
+
qnn_path = args.target_model
|
86 |
+
invoke_num=args.invoke_nums
|
87 |
+
print("Start processing...")
|
88 |
+
img_input,org_size = img_process(img_path)
|
89 |
+
|
90 |
+
qnn_model =run_qnn(qnn_path)
|
91 |
+
prediction_qnn = qnn_model(img_input.numpy().transpose(0,2,3,1),invoke_num)
|
92 |
+
prediction_qnn = torch.tensor(prediction_qnn)
|
93 |
+
qnn_process = out_process(prediction_qnn,org_size)
|
94 |
+
|
95 |
+
write_depth("./python/results.jpg", qnn_process, grayscale=False, bits=1)
|
96 |
+
write_pfm("./python/results.pfm", qnn_process.astype(np.float32))
|
97 |
+
print("Finished")
|
98 |
+
|
99 |
+
def parser_args():
|
100 |
+
parser = argparse.ArgumentParser(description="Run model benchmarks")
|
101 |
+
parser.add_argument('--target_model',type=str,default='./models/midas_v2_fp16.qnn216.ctx.bin',help="Inference model path")
|
102 |
+
parser.add_argument('--imgs',type=str,default='./python/dog.jpg',help="Predict images path")
|
103 |
+
parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
|
104 |
+
parser.add_argument('--model_type',type=str,default='QNN',help="Run backend")
|
105 |
+
args = parser.parse_args()
|
106 |
+
return args
|
107 |
+
|
108 |
+
|
109 |
+
if __name__ =="__main__":
|
110 |
+
args = parser_args()
|
111 |
+
run(args)
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/transforms.py
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import math
|
4 |
+
|
5 |
+
|
6 |
+
def apply_min_size(sample, size, image_interpolation_method=cv2.INTER_AREA):
|
7 |
+
"""Rezise the sample to ensure the given size. Keeps aspect ratio.
|
8 |
+
|
9 |
+
Args:
|
10 |
+
sample (dict): sample
|
11 |
+
size (tuple): image size
|
12 |
+
|
13 |
+
Returns:
|
14 |
+
tuple: new size
|
15 |
+
"""
|
16 |
+
shape = list(sample["disparity"].shape)
|
17 |
+
|
18 |
+
if shape[0] >= size[0] and shape[1] >= size[1]:
|
19 |
+
return sample
|
20 |
+
|
21 |
+
scale = [0, 0]
|
22 |
+
scale[0] = size[0] / shape[0]
|
23 |
+
scale[1] = size[1] / shape[1]
|
24 |
+
|
25 |
+
scale = max(scale)
|
26 |
+
|
27 |
+
shape[0] = math.ceil(scale * shape[0])
|
28 |
+
shape[1] = math.ceil(scale * shape[1])
|
29 |
+
|
30 |
+
# resize
|
31 |
+
sample["image"] = cv2.resize(
|
32 |
+
sample["image"], tuple(shape[::-1]), interpolation=image_interpolation_method
|
33 |
+
)
|
34 |
+
|
35 |
+
sample["disparity"] = cv2.resize(
|
36 |
+
sample["disparity"], tuple(shape[::-1]), interpolation=cv2.INTER_NEAREST
|
37 |
+
)
|
38 |
+
sample["mask"] = cv2.resize(
|
39 |
+
sample["mask"].astype(np.float32),
|
40 |
+
tuple(shape[::-1]),
|
41 |
+
interpolation=cv2.INTER_NEAREST,
|
42 |
+
)
|
43 |
+
sample["mask"] = sample["mask"].astype(bool)
|
44 |
+
|
45 |
+
return tuple(shape)
|
46 |
+
|
47 |
+
|
48 |
+
class Resize(object):
|
49 |
+
"""Resize sample to given size (width, height).
|
50 |
+
"""
|
51 |
+
|
52 |
+
def __init__(
|
53 |
+
self,
|
54 |
+
width,
|
55 |
+
height,
|
56 |
+
resize_target=True,
|
57 |
+
keep_aspect_ratio=False,
|
58 |
+
ensure_multiple_of=1,
|
59 |
+
resize_method="lower_bound",
|
60 |
+
image_interpolation_method=cv2.INTER_AREA,
|
61 |
+
):
|
62 |
+
"""Init.
|
63 |
+
|
64 |
+
Args:
|
65 |
+
width (int): desired output width
|
66 |
+
height (int): desired output height
|
67 |
+
resize_target (bool, optional):
|
68 |
+
True: Resize the full sample (image, mask, target).
|
69 |
+
False: Resize image only.
|
70 |
+
Defaults to True.
|
71 |
+
keep_aspect_ratio (bool, optional):
|
72 |
+
True: Keep the aspect ratio of the input sample.
|
73 |
+
Output sample might not have the given width and height, and
|
74 |
+
resize behaviour depends on the parameter 'resize_method'.
|
75 |
+
Defaults to False.
|
76 |
+
ensure_multiple_of (int, optional):
|
77 |
+
Output width and height is constrained to be multiple of this parameter.
|
78 |
+
Defaults to 1.
|
79 |
+
resize_method (str, optional):
|
80 |
+
"lower_bound": Output will be at least as large as the given size.
|
81 |
+
"upper_bound": Output will be at max as large as the given size. (Output size might be smaller than given size.)
|
82 |
+
"minimal": Scale as least as possible. (Output size might be smaller than given size.)
|
83 |
+
Defaults to "lower_bound".
|
84 |
+
"""
|
85 |
+
self.__width = width
|
86 |
+
self.__height = height
|
87 |
+
|
88 |
+
self.__resize_target = resize_target
|
89 |
+
self.__keep_aspect_ratio = keep_aspect_ratio
|
90 |
+
self.__multiple_of = ensure_multiple_of
|
91 |
+
self.__resize_method = resize_method
|
92 |
+
self.__image_interpolation_method = image_interpolation_method
|
93 |
+
|
94 |
+
def constrain_to_multiple_of(self, x, min_val=0, max_val=None):
|
95 |
+
y = (np.round(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
96 |
+
|
97 |
+
if max_val is not None and y > max_val:
|
98 |
+
y = (np.floor(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
99 |
+
|
100 |
+
if y < min_val:
|
101 |
+
y = (np.ceil(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
102 |
+
|
103 |
+
return y
|
104 |
+
|
105 |
+
def get_size(self, width, height):
|
106 |
+
# determine new height and width
|
107 |
+
scale_height = self.__height / height
|
108 |
+
scale_width = self.__width / width
|
109 |
+
|
110 |
+
if self.__keep_aspect_ratio:
|
111 |
+
if self.__resize_method == "lower_bound":
|
112 |
+
# scale such that output size is lower bound
|
113 |
+
if scale_width > scale_height:
|
114 |
+
# fit width
|
115 |
+
scale_height = scale_width
|
116 |
+
else:
|
117 |
+
# fit height
|
118 |
+
scale_width = scale_height
|
119 |
+
elif self.__resize_method == "upper_bound":
|
120 |
+
# scale such that output size is upper bound
|
121 |
+
if scale_width < scale_height:
|
122 |
+
# fit width
|
123 |
+
scale_height = scale_width
|
124 |
+
else:
|
125 |
+
# fit height
|
126 |
+
scale_width = scale_height
|
127 |
+
elif self.__resize_method == "minimal":
|
128 |
+
# scale as least as possbile
|
129 |
+
if abs(1 - scale_width) < abs(1 - scale_height):
|
130 |
+
# fit width
|
131 |
+
scale_height = scale_width
|
132 |
+
else:
|
133 |
+
# fit height
|
134 |
+
scale_width = scale_height
|
135 |
+
else:
|
136 |
+
raise ValueError(
|
137 |
+
f"resize_method {self.__resize_method} not implemented"
|
138 |
+
)
|
139 |
+
|
140 |
+
if self.__resize_method == "lower_bound":
|
141 |
+
new_height = self.constrain_to_multiple_of(
|
142 |
+
scale_height * height, min_val=self.__height
|
143 |
+
)
|
144 |
+
new_width = self.constrain_to_multiple_of(
|
145 |
+
scale_width * width, min_val=self.__width
|
146 |
+
)
|
147 |
+
elif self.__resize_method == "upper_bound":
|
148 |
+
new_height = self.constrain_to_multiple_of(
|
149 |
+
scale_height * height, max_val=self.__height
|
150 |
+
)
|
151 |
+
new_width = self.constrain_to_multiple_of(
|
152 |
+
scale_width * width, max_val=self.__width
|
153 |
+
)
|
154 |
+
elif self.__resize_method == "minimal":
|
155 |
+
new_height = self.constrain_to_multiple_of(scale_height * height)
|
156 |
+
new_width = self.constrain_to_multiple_of(scale_width * width)
|
157 |
+
else:
|
158 |
+
raise ValueError(f"resize_method {self.__resize_method} not implemented")
|
159 |
+
|
160 |
+
return (new_width, new_height)
|
161 |
+
|
162 |
+
def __call__(self, sample):
|
163 |
+
width, height = self.get_size(
|
164 |
+
sample["image"].shape[1], sample["image"].shape[0]
|
165 |
+
)
|
166 |
+
|
167 |
+
# resize sample
|
168 |
+
sample["image"] = cv2.resize(
|
169 |
+
sample["image"],
|
170 |
+
(width, height),
|
171 |
+
interpolation=self.__image_interpolation_method,
|
172 |
+
)
|
173 |
+
|
174 |
+
if self.__resize_target:
|
175 |
+
if "disparity" in sample:
|
176 |
+
sample["disparity"] = cv2.resize(
|
177 |
+
sample["disparity"],
|
178 |
+
(width, height),
|
179 |
+
interpolation=cv2.INTER_NEAREST,
|
180 |
+
)
|
181 |
+
|
182 |
+
if "depth" in sample:
|
183 |
+
sample["depth"] = cv2.resize(
|
184 |
+
sample["depth"], (width, height), interpolation=cv2.INTER_NEAREST
|
185 |
+
)
|
186 |
+
|
187 |
+
sample["mask"] = cv2.resize(
|
188 |
+
sample["mask"].astype(np.float32),
|
189 |
+
(width, height),
|
190 |
+
interpolation=cv2.INTER_NEAREST,
|
191 |
+
)
|
192 |
+
sample["mask"] = sample["mask"].astype(bool)
|
193 |
+
|
194 |
+
return sample
|
195 |
+
|
196 |
+
|
197 |
+
class NormalizeImage(object):
|
198 |
+
"""Normlize image by given mean and std.
|
199 |
+
"""
|
200 |
+
|
201 |
+
def __init__(self, mean, std):
|
202 |
+
self.__mean = mean
|
203 |
+
self.__std = std
|
204 |
+
|
205 |
+
def __call__(self, sample):
|
206 |
+
sample["image"] = (sample["image"] - self.__mean) / self.__std
|
207 |
+
|
208 |
+
return sample
|
209 |
+
|
210 |
+
|
211 |
+
class PrepareForNet(object):
|
212 |
+
"""Prepare sample for usage as network input.
|
213 |
+
"""
|
214 |
+
|
215 |
+
def __init__(self):
|
216 |
+
pass
|
217 |
+
|
218 |
+
def __call__(self, sample):
|
219 |
+
image = np.transpose(sample["image"], (2, 0, 1))
|
220 |
+
sample["image"] = np.ascontiguousarray(image).astype(np.float32)
|
221 |
+
|
222 |
+
if "mask" in sample:
|
223 |
+
sample["mask"] = sample["mask"].astype(np.float32)
|
224 |
+
sample["mask"] = np.ascontiguousarray(sample["mask"])
|
225 |
+
|
226 |
+
if "disparity" in sample:
|
227 |
+
disparity = sample["disparity"].astype(np.float32)
|
228 |
+
sample["disparity"] = np.ascontiguousarray(disparity)
|
229 |
+
|
230 |
+
if "depth" in sample:
|
231 |
+
depth = sample["depth"].astype(np.float32)
|
232 |
+
sample["depth"] = np.ascontiguousarray(depth)
|
233 |
+
|
234 |
+
return sample
|
model_farm_midas_v2_qcs8550_qnn2.16_fp16_aidlite/python/utils.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
|
6 |
+
from transforms import Resize, NormalizeImage, PrepareForNet
|
7 |
+
|
8 |
+
from torchvision.transforms import Compose
|
9 |
+
import sys
|
10 |
+
first_execution = True
|
11 |
+
def img_process(img_path):
|
12 |
+
global first_execution
|
13 |
+
first_execution = False
|
14 |
+
net_w, net_h = 256, 256
|
15 |
+
resize_mode = "upper_bound"
|
16 |
+
normalization = NormalizeImage(
|
17 |
+
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
|
18 |
+
)
|
19 |
+
transform = Compose(
|
20 |
+
[
|
21 |
+
Resize(
|
22 |
+
net_w,
|
23 |
+
net_h,
|
24 |
+
resize_target=None,
|
25 |
+
keep_aspect_ratio=False,
|
26 |
+
ensure_multiple_of=32,
|
27 |
+
resize_method=resize_mode,
|
28 |
+
image_interpolation_method=cv2.INTER_CUBIC,
|
29 |
+
),
|
30 |
+
normalization,
|
31 |
+
PrepareForNet(),
|
32 |
+
]
|
33 |
+
)
|
34 |
+
# image = utils.read_image(img_path) # in [0, 1]
|
35 |
+
image = cv2.imread(img_path)
|
36 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) / 255.0
|
37 |
+
org_size= image.shape[:2]
|
38 |
+
image = transform({"image": image})["image"]
|
39 |
+
sample = torch.from_numpy(image).to("cpu").unsqueeze(0)
|
40 |
+
height, width = sample.shape[2:]
|
41 |
+
print(f"Input resized to {width}x{height} before entering the encoder")
|
42 |
+
|
43 |
+
return sample,org_size
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
def write_depth(path, depth, grayscale=False, bits=1):
|
48 |
+
if not grayscale:
|
49 |
+
bits = 1
|
50 |
+
|
51 |
+
if not np.isfinite(depth).all():
|
52 |
+
depth=np.nan_to_num(depth, nan=0.0, posinf=0.0, neginf=0.0)
|
53 |
+
print("WARNING: Non-finite depth values present")
|
54 |
+
|
55 |
+
depth_min = depth.min()
|
56 |
+
depth_max = depth.max()
|
57 |
+
|
58 |
+
max_val = (2**(8*bits))-1
|
59 |
+
|
60 |
+
if depth_max - depth_min > np.finfo("float").eps:
|
61 |
+
out = max_val * (depth - depth_min) / (depth_max - depth_min)
|
62 |
+
else:
|
63 |
+
out = np.zeros(depth.shape, dtype=depth.dtype)
|
64 |
+
|
65 |
+
# print("out :",out.shape,out)
|
66 |
+
if not grayscale:
|
67 |
+
out = cv2.applyColorMap(np.uint8(out), cv2.COLORMAP_INFERNO)
|
68 |
+
|
69 |
+
if bits == 1:
|
70 |
+
cv2.imwrite(path , out.astype("uint8"))
|
71 |
+
elif bits == 2:
|
72 |
+
cv2.imwrite(path , out.astype("uint16"))
|
73 |
+
|
74 |
+
return
|
75 |
+
|
76 |
+
def write_pfm(path, image, scale=1):
|
77 |
+
with open(path, "wb") as file:
|
78 |
+
color = None
|
79 |
+
|
80 |
+
if image.dtype.name != "float32":
|
81 |
+
raise Exception("Image dtype must be float32.")
|
82 |
+
|
83 |
+
image = np.flipud(image)
|
84 |
+
|
85 |
+
if len(image.shape) == 3 and image.shape[2] == 3: # color image
|
86 |
+
color = True
|
87 |
+
elif (
|
88 |
+
len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1
|
89 |
+
): # greyscale
|
90 |
+
color = False
|
91 |
+
else:
|
92 |
+
raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")
|
93 |
+
|
94 |
+
file.write("PF\n" if color else "Pf\n".encode())
|
95 |
+
file.write("%d %d\n".encode() % (image.shape[1], image.shape[0]))
|
96 |
+
|
97 |
+
endian = image.dtype.byteorder
|
98 |
+
|
99 |
+
if endian == "<" or endian == "=" and sys.byteorder == "little":
|
100 |
+
scale = -scale
|
101 |
+
|
102 |
+
file.write("%f\n".encode() % scale)
|
103 |
+
|
104 |
+
image.tofile(file)
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## Model Information
|
2 |
+
|
3 |
+
### Source model
|
4 |
+
- Input shape: 1x3x256x256
|
5 |
+
- Number of parameters: 20.33M
|
6 |
+
- Model size: 82.17M
|
7 |
+
- Output shape: 1x1x256x256
|
8 |
+
|
9 |
+
Source model repository: [midas](https://github.com/isl-org/MiDaS/tree/master)
|
10 |
+
|
11 |
+
### Converted model
|
12 |
+
|
13 |
+
- Precision: INT8
|
14 |
+
- Backend: QNN2.16
|
15 |
+
- Target Device: SNM972 QCS8550
|
16 |
+
|
17 |
+
## Inference with AidLite SDK
|
18 |
+
|
19 |
+
### SDK installation
|
20 |
+
Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
|
21 |
+
|
22 |
+
- Install AidLite SDK
|
23 |
+
|
24 |
+
```bash
|
25 |
+
# Install the appropriate version of the aidlite sdk
|
26 |
+
sudo aid-pkg update
|
27 |
+
sudo aid-pkg install aidlite-sdk
|
28 |
+
# Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
|
29 |
+
sudo aid-pkg install aidlite-{QNN VERSION}
|
30 |
+
```
|
31 |
+
|
32 |
+
- Verify AidLite SDK
|
33 |
+
|
34 |
+
```bash
|
35 |
+
# aidlite sdk c++ check
|
36 |
+
python3 -c "import aidlite ; print(aidlite.get_library_version())"
|
37 |
+
|
38 |
+
# aidlite sdk python check
|
39 |
+
python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
|
40 |
+
```
|
41 |
+
|
42 |
+
### Run Demo
|
43 |
+
#### python
|
44 |
+
```bash
|
45 |
+
cd model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite
|
46 |
+
python3 python/run_test.py --target_model ./models/midas_v2_w8a8.qnn216.ctx.bin --imgs ./python/dog.jpg --invoke_nums 10
|
47 |
+
```
|
48 |
+
|
49 |
+
#### c++
|
50 |
+
```bash
|
51 |
+
cd midas_v2/model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp
|
52 |
+
mkdir build && cd build
|
53 |
+
cmake ..
|
54 |
+
make
|
55 |
+
./run_test
|
56 |
+
```
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp/CMakeLists.txt
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
cmake_minimum_required (VERSION 3.5)
|
2 |
+
project("run_test")
|
3 |
+
|
4 |
+
find_package(OpenCV REQUIRED)
|
5 |
+
|
6 |
+
message(STATUS "oPENCV Library status:")
|
7 |
+
message(STATUS ">version:${OpenCV_VERSION}")
|
8 |
+
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
|
9 |
+
|
10 |
+
set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
|
11 |
+
|
12 |
+
include_directories(
|
13 |
+
/usr/local/include
|
14 |
+
/usr/include/opencv4
|
15 |
+
)
|
16 |
+
|
17 |
+
link_directories(
|
18 |
+
/usr/local/lib/
|
19 |
+
)
|
20 |
+
|
21 |
+
file(GLOB SRC_LISTS
|
22 |
+
${CMAKE_CURRENT_SOURCE_DIR}/run_test.cpp
|
23 |
+
)
|
24 |
+
|
25 |
+
add_executable(run_test ${SRC_LISTS})
|
26 |
+
|
27 |
+
target_link_libraries(run_test
|
28 |
+
aidlite
|
29 |
+
${OpenCV_LIBS}
|
30 |
+
pthread
|
31 |
+
jsoncpp
|
32 |
+
)
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/cpp/run_test.cpp
ADDED
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <iostream>
|
2 |
+
#include <fstream>
|
3 |
+
#include <opencv2/opencv.hpp>
|
4 |
+
#include <aidlux/aidlite/aidlite.hpp>
|
5 |
+
#include <vector>
|
6 |
+
#include <numeric>
|
7 |
+
#include <cmath>
|
8 |
+
#include <jsoncpp/json/json.h>
|
9 |
+
|
10 |
+
using namespace cv;
|
11 |
+
using namespace std;
|
12 |
+
using namespace Aidlux::Aidlite;
|
13 |
+
|
14 |
+
const int net_w = 256;
|
15 |
+
const int net_h = 256;
|
16 |
+
|
17 |
+
const std::vector<float> mean_vals = {0.485f, 0.456f, 0.406f};
|
18 |
+
const std::vector<float> std_vals = {0.229f, 0.224f, 0.225f};
|
19 |
+
|
20 |
+
|
21 |
+
struct Args {
|
22 |
+
std::string target_model = "../../models/midas_v2_w8a8.qnn216.ctx.bin";
|
23 |
+
std::string imgs = "../dog.jpg";
|
24 |
+
int invoke_nums = 10;
|
25 |
+
std::string model_type = "QNN";
|
26 |
+
};
|
27 |
+
|
28 |
+
|
29 |
+
Args parse_args(int argc, char* argv[]) {
|
30 |
+
Args args;
|
31 |
+
for (int i = 1; i < argc; ++i) {
|
32 |
+
std::string arg = argv[i];
|
33 |
+
if (arg == "--target_model" && i + 1 < argc) {
|
34 |
+
args.target_model = argv[++i];
|
35 |
+
} else if (arg == "--imgs" && i + 1 < argc) {
|
36 |
+
args.imgs = argv[++i];
|
37 |
+
} else if (arg == "--invoke_nums" && i + 1 < argc) {
|
38 |
+
args.invoke_nums = std::stoi(argv[++i]);
|
39 |
+
} else if (arg == "--model_type" && i + 1 < argc) {
|
40 |
+
args.model_type = argv[++i];
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return args;
|
44 |
+
}
|
45 |
+
|
46 |
+
std::string to_lower(const std::string& str) {
|
47 |
+
std::string lower_str = str;
|
48 |
+
std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
|
49 |
+
return std::tolower(c);
|
50 |
+
});
|
51 |
+
return lower_str;
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
|
56 |
+
|
57 |
+
int current_coordinate[4] = {0, 0, 0, 0};
|
58 |
+
for(int a = 0; a < src_dims[0]; ++a){
|
59 |
+
current_coordinate[0] = a;
|
60 |
+
for(int b = 0; b < src_dims[1]; ++b){
|
61 |
+
current_coordinate[1] = b;
|
62 |
+
for(int c = 0; c < src_dims[2]; ++c){
|
63 |
+
current_coordinate[2] = c;
|
64 |
+
for(int d = 0; d < src_dims[3]; ++d){
|
65 |
+
current_coordinate[3] = d;
|
66 |
+
|
67 |
+
int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
|
68 |
+
current_coordinate[1]*src_dims[2]*src_dims[3] +
|
69 |
+
current_coordinate[2]*src_dims[3] +
|
70 |
+
current_coordinate[3];
|
71 |
+
|
72 |
+
int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
73 |
+
current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
74 |
+
current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
75 |
+
current_coordinate[tsp_dims[3]];
|
76 |
+
|
77 |
+
dest[new_index] = src[old_index];
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
return EXIT_SUCCESS;
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
// 替代 np.nan_to_num
|
88 |
+
void sanitizeDepthMap(cv::Mat& depth) {
|
89 |
+
for (int y = 0; y < depth.rows; ++y) {
|
90 |
+
float* row = depth.ptr<float>(y);
|
91 |
+
for (int x = 0; x < depth.cols; ++x) {
|
92 |
+
float val = row[x];
|
93 |
+
if (!std::isfinite(val)) {
|
94 |
+
row[x] = 0.0f;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
// 等效于 Python write_depth
|
101 |
+
void write_depth(const std::string& path, const cv::Mat& input_depth, bool grayscale = false, int bits = 1) {
|
102 |
+
CV_Assert(input_depth.type() == CV_32FC1);
|
103 |
+
|
104 |
+
// 拷贝 + 处理非法值
|
105 |
+
cv::Mat depth = input_depth.clone();
|
106 |
+
sanitizeDepthMap(depth);
|
107 |
+
|
108 |
+
double minVal, maxVal;
|
109 |
+
cv::minMaxLoc(depth, &minVal, &maxVal);
|
110 |
+
|
111 |
+
double max_val = (1 << (8 * bits)) - 1;
|
112 |
+
cv::Mat out;
|
113 |
+
|
114 |
+
if (maxVal - minVal > std::numeric_limits<float>::epsilon()) {
|
115 |
+
// 归一化并映射到位深范围
|
116 |
+
out = (depth - minVal) * (max_val / (maxVal - minVal));
|
117 |
+
} else {
|
118 |
+
out = cv::Mat::zeros(depth.size(), CV_32F);
|
119 |
+
}
|
120 |
+
|
121 |
+
if (!grayscale) {
|
122 |
+
out.convertTo(out, CV_8UC1);
|
123 |
+
cv::applyColorMap(out, out, cv::COLORMAP_INFERNO);
|
124 |
+
}
|
125 |
+
|
126 |
+
if (bits == 1) {
|
127 |
+
out.convertTo(out, CV_8U);
|
128 |
+
} else if (bits == 2) {
|
129 |
+
out.convertTo(out, CV_16U);
|
130 |
+
}
|
131 |
+
|
132 |
+
cv::imwrite(path, out);
|
133 |
+
}
|
134 |
+
|
135 |
+
// 等效于 Python write_pfm
|
136 |
+
void write_pfm(const std::string& path, const cv::Mat& image, float scale = 1.0f) {
|
137 |
+
CV_Assert(image.type() == CV_32FC1 || image.type() == CV_32FC3);
|
138 |
+
|
139 |
+
std::ofstream file(path, std::ios::binary);
|
140 |
+
if (!file.is_open()) {
|
141 |
+
std::cerr << "Failed to open file for writing PFM: " << path << std::endl;
|
142 |
+
return;
|
143 |
+
}
|
144 |
+
|
145 |
+
int width = image.cols;
|
146 |
+
int height = image.rows;
|
147 |
+
int channels = image.channels();
|
148 |
+
bool color = (channels == 3);
|
149 |
+
|
150 |
+
file << (color ? "PF" : "Pf") << "\n";
|
151 |
+
file << width << " " << height << "\n";
|
152 |
+
|
153 |
+
// Endianness: negative = little-endian
|
154 |
+
uint16_t endian_test = 0x1;
|
155 |
+
bool is_little_endian = *(reinterpret_cast<uint8_t*>(&endian_test)) == 0x1;
|
156 |
+
if (is_little_endian) {
|
157 |
+
scale = -scale;
|
158 |
+
}
|
159 |
+
|
160 |
+
file << scale << "\n";
|
161 |
+
|
162 |
+
// Flip vertically (OpenCV top-left origin -> PFM bottom-left origin)
|
163 |
+
cv::Mat flipped;
|
164 |
+
cv::flip(image, flipped, 0);
|
165 |
+
|
166 |
+
// Write raw data
|
167 |
+
file.write(reinterpret_cast<const char*>(flipped.data), flipped.total() * channels * sizeof(float));
|
168 |
+
file.close();
|
169 |
+
}
|
170 |
+
|
171 |
+
|
172 |
+
// ======================= Normalize =======================
|
173 |
+
void normalize(cv::Mat& image) {
|
174 |
+
CV_Assert(image.type() == CV_32FC3);
|
175 |
+
int rows = image.rows;
|
176 |
+
int cols = image.cols;
|
177 |
+
|
178 |
+
for (int y = 0; y < rows; ++y) {
|
179 |
+
cv::Vec3f* row = image.ptr<cv::Vec3f>(y);
|
180 |
+
for (int x = 0; x < cols; ++x) {
|
181 |
+
for (int c = 0; c < 3; ++c) {
|
182 |
+
row[x][c] = (row[x][c] - mean_vals[c]) / std_vals[c];
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
cv::Mat hwc_to_chw(const cv::Mat& image) {
|
189 |
+
std::vector<cv::Mat> channels(3);
|
190 |
+
cv::split(image, channels);
|
191 |
+
|
192 |
+
cv::Mat chw(3, image.rows * image.cols, CV_32F);
|
193 |
+
for (int c = 0; c < 3; ++c) {
|
194 |
+
memcpy(chw.ptr(c), channels[c].data, image.rows * image.cols * sizeof(float));
|
195 |
+
}
|
196 |
+
|
197 |
+
return chw;
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
bool first_execution = true;
|
202 |
+
cv::Mat img_process(const cv::Mat image_bgr, cv::Size& org_size_out) {
|
203 |
+
first_execution = false;
|
204 |
+
|
205 |
+
cv::Mat image_rgb;
|
206 |
+
cv::cvtColor(image_bgr, image_rgb, cv::COLOR_BGR2RGB);
|
207 |
+
image_rgb.convertTo(image_rgb, CV_32FC3, 1.0 / 255.0);
|
208 |
+
|
209 |
+
// 2. Save original size
|
210 |
+
org_size_out = image_rgb.size(); // H x W
|
211 |
+
|
212 |
+
// 3. Resize to 256x256 using cubic interpolation
|
213 |
+
cv::resize(image_rgb, image_rgb, cv::Size(net_w, net_h), 0, 0, cv::INTER_CUBIC);
|
214 |
+
|
215 |
+
// 4. Normalize using mean/std
|
216 |
+
normalize(image_rgb);
|
217 |
+
|
218 |
+
// 5. Convert HWC to CHW
|
219 |
+
cv::Mat chw = hwc_to_chw(image_rgb);
|
220 |
+
|
221 |
+
// 6. Add batch dimension: [1, C, H, W] → reshape to 1x3xHxW style float array
|
222 |
+
cv::Mat input_tensor(1, 3 * net_h * net_w, CV_32F);
|
223 |
+
memcpy(input_tensor.ptr<float>(), chw.data, 3 * net_h * net_w * sizeof(float));
|
224 |
+
|
225 |
+
std::cout << "Input resized to " << net_w << "x" << net_h << " before entering the encoder" << std::endl;
|
226 |
+
|
227 |
+
return input_tensor;
|
228 |
+
}
|
229 |
+
|
230 |
+
|
231 |
+
float* matToFloatPtr(const cv::Mat& input_mat, bool normalize = true) {
|
232 |
+
// 检查连续性
|
233 |
+
cv::Mat mat = input_mat;
|
234 |
+
if (!mat.isContinuous()) {
|
235 |
+
mat = mat.clone();
|
236 |
+
}
|
237 |
+
|
238 |
+
// 分配内存
|
239 |
+
int total_pixels = mat.rows * mat.cols;
|
240 |
+
int channels = mat.channels();
|
241 |
+
float* float_data = new float[total_pixels * channels];
|
242 |
+
|
243 |
+
// 根据数据类型转换
|
244 |
+
if (mat.type() == CV_8UC1 || mat.type() == CV_8UC3) {
|
245 |
+
uchar* ptr = mat.ptr<uchar>(0);
|
246 |
+
for (int i = 0; i < total_pixels * channels; ++i) {
|
247 |
+
float_data[i] = normalize ? (static_cast<float>(ptr[i]) / 255.0f) : ptr[i];
|
248 |
+
}
|
249 |
+
} else if (mat.type() == CV_32FC1 || mat.type() == CV_32FC3) {
|
250 |
+
float* ptr = mat.ptr<float>(0);
|
251 |
+
std::memcpy(float_data, ptr, total_pixels * channels * sizeof(float));
|
252 |
+
} else {
|
253 |
+
delete[] float_data;
|
254 |
+
return nullptr; // 不支持的类型
|
255 |
+
}
|
256 |
+
|
257 |
+
return float_data;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
int invoke(const Args& args) {
|
262 |
+
std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
|
263 |
+
<< "Image Path: " << args.imgs << "\n"
|
264 |
+
<< "Inference Nums: " << args.invoke_nums << "\n"
|
265 |
+
<< "Model Type: " << args.model_type << "\n";
|
266 |
+
Model* model = Model::create_instance(args.target_model);
|
267 |
+
if(model == nullptr){
|
268 |
+
printf("Create model failed !\n");
|
269 |
+
return EXIT_FAILURE;
|
270 |
+
}
|
271 |
+
Config* config = Config::create_instance();
|
272 |
+
if(config == nullptr){
|
273 |
+
printf("Create config failed !\n");
|
274 |
+
return EXIT_FAILURE;
|
275 |
+
}
|
276 |
+
config->implement_type = ImplementType::TYPE_LOCAL;
|
277 |
+
std::string model_type_lower = to_lower(args.model_type);
|
278 |
+
if (model_type_lower == "qnn"){
|
279 |
+
config->framework_type = FrameworkType::TYPE_QNN;
|
280 |
+
} else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
|
281 |
+
config->framework_type = FrameworkType::TYPE_SNPE2;
|
282 |
+
}
|
283 |
+
config->accelerate_type = AccelerateType::TYPE_DSP;
|
284 |
+
config->is_quantify_model = 1;
|
285 |
+
|
286 |
+
unsigned int model_h = 256;
|
287 |
+
unsigned int model_w = 256;
|
288 |
+
std::vector<std::vector<uint32_t>> input_shapes = {{1,model_h,model_w,3}};
|
289 |
+
std::vector<std::vector<uint32_t>> output_shapes = {{1,model_h,model_w,1}};
|
290 |
+
model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
|
291 |
+
std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
|
292 |
+
if(fast_interpreter == nullptr){
|
293 |
+
printf("build_interpretper_from_model_and_config failed !\n");
|
294 |
+
return EXIT_FAILURE;
|
295 |
+
}
|
296 |
+
int result = fast_interpreter->init();
|
297 |
+
if(result != EXIT_SUCCESS){
|
298 |
+
printf("interpreter->init() failed !\n");
|
299 |
+
return EXIT_FAILURE;
|
300 |
+
}
|
301 |
+
// load model
|
302 |
+
fast_interpreter->load_model();
|
303 |
+
if(result != EXIT_SUCCESS){
|
304 |
+
printf("interpreter->load_model() failed !\n");
|
305 |
+
return EXIT_FAILURE;
|
306 |
+
}
|
307 |
+
printf("detect model load success!\n");
|
308 |
+
|
309 |
+
cv::Mat frame = cv::imread(args.imgs);
|
310 |
+
if (frame.empty()) {
|
311 |
+
printf("detect image load failed!\n");
|
312 |
+
return 1;
|
313 |
+
}
|
314 |
+
printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
|
315 |
+
cv::Mat input_data;
|
316 |
+
cv::Mat frame_clone = frame.clone();
|
317 |
+
int h = frame_clone.rows;
|
318 |
+
int w = frame_clone.cols;
|
319 |
+
cv::Size org_size(w, h);
|
320 |
+
cv::Size org_size0(256, 256);
|
321 |
+
|
322 |
+
cv::Mat input_tensor = img_process(frame_clone, org_size0);
|
323 |
+
float* float_data = matToFloatPtr(input_tensor);
|
324 |
+
unsigned int src_dims[4] = {1, 3, 256, 256};
|
325 |
+
unsigned int tsp_dims[4] = {0,2,3,1};
|
326 |
+
unsigned int stride_data_num = 1*256*256*3;
|
327 |
+
float* format_data = new float[stride_data_num];
|
328 |
+
transpose(float_data, src_dims, tsp_dims, format_data);
|
329 |
+
cv::Mat origin_buffer(3,256*256, CV_32F, format_data);
|
330 |
+
|
331 |
+
float *outdata0 = nullptr;
|
332 |
+
std::vector<float> invoke_time;
|
333 |
+
for (int i = 0; i < args.invoke_nums; ++i) {
|
334 |
+
result = fast_interpreter->set_input_tensor(0, origin_buffer.data);
|
335 |
+
if(result != EXIT_SUCCESS){
|
336 |
+
printf("interpreter->set_input_tensor() failed !\n");
|
337 |
+
return EXIT_FAILURE;
|
338 |
+
}
|
339 |
+
auto t1 = std::chrono::high_resolution_clock::now();
|
340 |
+
result = fast_interpreter->invoke();
|
341 |
+
auto t2 = std::chrono::high_resolution_clock::now();
|
342 |
+
std::chrono::duration<double> cost_time = t2 - t1;
|
343 |
+
invoke_time.push_back(cost_time.count() * 1000);
|
344 |
+
if(result != EXIT_SUCCESS){
|
345 |
+
printf("interpreter->invoke() failed !\n");
|
346 |
+
return EXIT_FAILURE;
|
347 |
+
}
|
348 |
+
uint32_t out_data_0 = 0;
|
349 |
+
result = fast_interpreter->get_output_tensor(0, (void**)&outdata0, &out_data_0);
|
350 |
+
if(result != EXIT_SUCCESS){
|
351 |
+
printf("interpreter->get_output_tensor() 1 failed !\n");
|
352 |
+
return EXIT_FAILURE;
|
353 |
+
}
|
354 |
+
|
355 |
+
}
|
356 |
+
|
357 |
+
float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
|
358 |
+
float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
|
359 |
+
float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
|
360 |
+
float var_invoketime = 0.0f;
|
361 |
+
for (auto time : invoke_time) {
|
362 |
+
var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
|
363 |
+
}
|
364 |
+
var_invoketime /= args.invoke_nums;
|
365 |
+
printf("=======================================\n");
|
366 |
+
printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
|
367 |
+
args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
|
368 |
+
printf("=======================================\n");
|
369 |
+
|
370 |
+
// post process
|
371 |
+
cv::Mat out_buffer(1,256*256, CV_32F, outdata0);
|
372 |
+
cv::Mat prediction_2d(256, 256, CV_32F, (void*)out_buffer.ptr<float>());
|
373 |
+
cv::Mat resized;
|
374 |
+
cv::resize(prediction_2d, resized, org_size, 0, 0, cv::INTER_CUBIC);
|
375 |
+
|
376 |
+
// 保存为图像
|
377 |
+
write_depth("depth_output.jpg", resized, false, 1);
|
378 |
+
|
379 |
+
// 保存为 PFM
|
380 |
+
write_pfm("depth_output.pfm", resized);
|
381 |
+
|
382 |
+
|
383 |
+
|
384 |
+
fast_interpreter->destory();
|
385 |
+
return 0;
|
386 |
+
}
|
387 |
+
|
388 |
+
|
389 |
+
int main(int argc, char* argv[]) {
|
390 |
+
Args args = parse_args(argc, argv);
|
391 |
+
return invoke(args);
|
392 |
+
}
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/models/midas_v2_w8a8.qnn216.ctx.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d583ca678b740c8075b7f829e4d01ecbcfccf7fc498d549b365508d686d89982
|
3 |
+
size 18853888
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/run_test.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
from utils import write_pfm,write_depth,img_process
|
6 |
+
import aidlite
|
7 |
+
import time
|
8 |
+
import argparse
|
9 |
+
|
10 |
+
def out_process(prediction,target_size):
|
11 |
+
prediction = torch.nn.functional.interpolate(
|
12 |
+
prediction,
|
13 |
+
size=target_size,
|
14 |
+
mode="bicubic",
|
15 |
+
align_corners=False,
|
16 |
+
)
|
17 |
+
prediction = prediction.squeeze().detach().numpy()
|
18 |
+
return prediction
|
19 |
+
|
20 |
+
class run_qnn:
|
21 |
+
def __init__(self,qnn_path):
|
22 |
+
super().__init__()
|
23 |
+
self.model = aidlite.Model.create_instance(qnn_path)
|
24 |
+
if self.model is None:
|
25 |
+
print("Create model failed !")
|
26 |
+
return
|
27 |
+
|
28 |
+
self.config = aidlite.Config.create_instance()
|
29 |
+
if self.config is None:
|
30 |
+
print("build_interpretper_from_model_and_config failed !")
|
31 |
+
return
|
32 |
+
|
33 |
+
self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
|
34 |
+
self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
|
35 |
+
self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
|
36 |
+
# self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
|
37 |
+
self.config.is_quantify_model = 1
|
38 |
+
|
39 |
+
self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
|
40 |
+
if self.interpreter is None:
|
41 |
+
print("build_interpretper_from_model_and_config failed !")
|
42 |
+
return
|
43 |
+
input_shapes = [[1,256,256,3]]
|
44 |
+
output_shapes = [[1,256,256,1]]
|
45 |
+
self.model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
|
46 |
+
output_shapes, aidlite.DataType.TYPE_FLOAT32)
|
47 |
+
|
48 |
+
if self.interpreter is None:
|
49 |
+
print("build_interpretper_from_model_and_config failed !")
|
50 |
+
result = self.interpreter.init()
|
51 |
+
if result != 0:
|
52 |
+
print(f"interpreter init failed !")
|
53 |
+
result = self.interpreter.load_model()
|
54 |
+
if result != 0:
|
55 |
+
print("interpreter load model failed !")
|
56 |
+
|
57 |
+
print(" model load success!")
|
58 |
+
|
59 |
+
def __call__(self, input,invoke_nums):
|
60 |
+
self.interpreter.set_input_tensor(0,input)
|
61 |
+
invoke_time=[]
|
62 |
+
for i in range(invoke_nums):
|
63 |
+
result = self.interpreter.set_input_tensor(0, input.data)
|
64 |
+
if result != 0:
|
65 |
+
print("interpreter set_input_tensor() failed")
|
66 |
+
t1=time.time()
|
67 |
+
result = self.interpreter.invoke()
|
68 |
+
cost_time = (time.time()-t1)*1000
|
69 |
+
invoke_time.append(cost_time)
|
70 |
+
|
71 |
+
max_invoke_time = max(invoke_time)
|
72 |
+
min_invoke_time = min(invoke_time)
|
73 |
+
mean_invoke_time = sum(invoke_time)/invoke_nums
|
74 |
+
var_invoketime=np.var(invoke_time)
|
75 |
+
print("====================================")
|
76 |
+
print(f"QNN invoke time:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
|
77 |
+
print("====================================")
|
78 |
+
features_0 = self.interpreter.get_output_tensor(0).reshape(1,256,256,1).transpose(0,3,1,2)
|
79 |
+
return features_0
|
80 |
+
|
81 |
+
|
82 |
+
|
83 |
+
def run(args):
|
84 |
+
img_path = args.imgs
|
85 |
+
qnn_path = args.target_model
|
86 |
+
invoke_num=args.invoke_nums
|
87 |
+
print("Start processing...")
|
88 |
+
img_input,org_size = img_process(img_path)
|
89 |
+
|
90 |
+
qnn_model =run_qnn(qnn_path)
|
91 |
+
prediction_qnn = qnn_model(img_input.numpy().transpose(0,2,3,1),invoke_num)
|
92 |
+
prediction_qnn = torch.tensor(prediction_qnn)
|
93 |
+
qnn_process = out_process(prediction_qnn,org_size)
|
94 |
+
|
95 |
+
write_depth("./python/results.jpg", qnn_process, grayscale=False, bits=1)
|
96 |
+
write_pfm("./python/results.pfm", qnn_process.astype(np.float32))
|
97 |
+
print("Finished")
|
98 |
+
|
99 |
+
def parser_args():
|
100 |
+
parser = argparse.ArgumentParser(description="Run model benchmarks")
|
101 |
+
parser.add_argument('--target_model',type=str,default='./models/midas_v2_w8a8.qnn216.ctx.bin',help="Inference model path")
|
102 |
+
parser.add_argument('--imgs',type=str,default='./python/dog.jpg',help="Predict images path")
|
103 |
+
parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
|
104 |
+
parser.add_argument('--model_type',type=str,default='QNN',help="Run backend")
|
105 |
+
args = parser.parse_args()
|
106 |
+
return args
|
107 |
+
|
108 |
+
|
109 |
+
if __name__ =="__main__":
|
110 |
+
args = parser_args()
|
111 |
+
run(args)
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/transforms.py
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import math
|
4 |
+
|
5 |
+
|
6 |
+
def apply_min_size(sample, size, image_interpolation_method=cv2.INTER_AREA):
|
7 |
+
"""Rezise the sample to ensure the given size. Keeps aspect ratio.
|
8 |
+
|
9 |
+
Args:
|
10 |
+
sample (dict): sample
|
11 |
+
size (tuple): image size
|
12 |
+
|
13 |
+
Returns:
|
14 |
+
tuple: new size
|
15 |
+
"""
|
16 |
+
shape = list(sample["disparity"].shape)
|
17 |
+
|
18 |
+
if shape[0] >= size[0] and shape[1] >= size[1]:
|
19 |
+
return sample
|
20 |
+
|
21 |
+
scale = [0, 0]
|
22 |
+
scale[0] = size[0] / shape[0]
|
23 |
+
scale[1] = size[1] / shape[1]
|
24 |
+
|
25 |
+
scale = max(scale)
|
26 |
+
|
27 |
+
shape[0] = math.ceil(scale * shape[0])
|
28 |
+
shape[1] = math.ceil(scale * shape[1])
|
29 |
+
|
30 |
+
# resize
|
31 |
+
sample["image"] = cv2.resize(
|
32 |
+
sample["image"], tuple(shape[::-1]), interpolation=image_interpolation_method
|
33 |
+
)
|
34 |
+
|
35 |
+
sample["disparity"] = cv2.resize(
|
36 |
+
sample["disparity"], tuple(shape[::-1]), interpolation=cv2.INTER_NEAREST
|
37 |
+
)
|
38 |
+
sample["mask"] = cv2.resize(
|
39 |
+
sample["mask"].astype(np.float32),
|
40 |
+
tuple(shape[::-1]),
|
41 |
+
interpolation=cv2.INTER_NEAREST,
|
42 |
+
)
|
43 |
+
sample["mask"] = sample["mask"].astype(bool)
|
44 |
+
|
45 |
+
return tuple(shape)
|
46 |
+
|
47 |
+
|
48 |
+
class Resize(object):
|
49 |
+
"""Resize sample to given size (width, height).
|
50 |
+
"""
|
51 |
+
|
52 |
+
def __init__(
|
53 |
+
self,
|
54 |
+
width,
|
55 |
+
height,
|
56 |
+
resize_target=True,
|
57 |
+
keep_aspect_ratio=False,
|
58 |
+
ensure_multiple_of=1,
|
59 |
+
resize_method="lower_bound",
|
60 |
+
image_interpolation_method=cv2.INTER_AREA,
|
61 |
+
):
|
62 |
+
"""Init.
|
63 |
+
|
64 |
+
Args:
|
65 |
+
width (int): desired output width
|
66 |
+
height (int): desired output height
|
67 |
+
resize_target (bool, optional):
|
68 |
+
True: Resize the full sample (image, mask, target).
|
69 |
+
False: Resize image only.
|
70 |
+
Defaults to True.
|
71 |
+
keep_aspect_ratio (bool, optional):
|
72 |
+
True: Keep the aspect ratio of the input sample.
|
73 |
+
Output sample might not have the given width and height, and
|
74 |
+
resize behaviour depends on the parameter 'resize_method'.
|
75 |
+
Defaults to False.
|
76 |
+
ensure_multiple_of (int, optional):
|
77 |
+
Output width and height is constrained to be multiple of this parameter.
|
78 |
+
Defaults to 1.
|
79 |
+
resize_method (str, optional):
|
80 |
+
"lower_bound": Output will be at least as large as the given size.
|
81 |
+
"upper_bound": Output will be at max as large as the given size. (Output size might be smaller than given size.)
|
82 |
+
"minimal": Scale as least as possible. (Output size might be smaller than given size.)
|
83 |
+
Defaults to "lower_bound".
|
84 |
+
"""
|
85 |
+
self.__width = width
|
86 |
+
self.__height = height
|
87 |
+
|
88 |
+
self.__resize_target = resize_target
|
89 |
+
self.__keep_aspect_ratio = keep_aspect_ratio
|
90 |
+
self.__multiple_of = ensure_multiple_of
|
91 |
+
self.__resize_method = resize_method
|
92 |
+
self.__image_interpolation_method = image_interpolation_method
|
93 |
+
|
94 |
+
def constrain_to_multiple_of(self, x, min_val=0, max_val=None):
|
95 |
+
y = (np.round(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
96 |
+
|
97 |
+
if max_val is not None and y > max_val:
|
98 |
+
y = (np.floor(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
99 |
+
|
100 |
+
if y < min_val:
|
101 |
+
y = (np.ceil(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
102 |
+
|
103 |
+
return y
|
104 |
+
|
105 |
+
def get_size(self, width, height):
|
106 |
+
# determine new height and width
|
107 |
+
scale_height = self.__height / height
|
108 |
+
scale_width = self.__width / width
|
109 |
+
|
110 |
+
if self.__keep_aspect_ratio:
|
111 |
+
if self.__resize_method == "lower_bound":
|
112 |
+
# scale such that output size is lower bound
|
113 |
+
if scale_width > scale_height:
|
114 |
+
# fit width
|
115 |
+
scale_height = scale_width
|
116 |
+
else:
|
117 |
+
# fit height
|
118 |
+
scale_width = scale_height
|
119 |
+
elif self.__resize_method == "upper_bound":
|
120 |
+
# scale such that output size is upper bound
|
121 |
+
if scale_width < scale_height:
|
122 |
+
# fit width
|
123 |
+
scale_height = scale_width
|
124 |
+
else:
|
125 |
+
# fit height
|
126 |
+
scale_width = scale_height
|
127 |
+
elif self.__resize_method == "minimal":
|
128 |
+
# scale as least as possbile
|
129 |
+
if abs(1 - scale_width) < abs(1 - scale_height):
|
130 |
+
# fit width
|
131 |
+
scale_height = scale_width
|
132 |
+
else:
|
133 |
+
# fit height
|
134 |
+
scale_width = scale_height
|
135 |
+
else:
|
136 |
+
raise ValueError(
|
137 |
+
f"resize_method {self.__resize_method} not implemented"
|
138 |
+
)
|
139 |
+
|
140 |
+
if self.__resize_method == "lower_bound":
|
141 |
+
new_height = self.constrain_to_multiple_of(
|
142 |
+
scale_height * height, min_val=self.__height
|
143 |
+
)
|
144 |
+
new_width = self.constrain_to_multiple_of(
|
145 |
+
scale_width * width, min_val=self.__width
|
146 |
+
)
|
147 |
+
elif self.__resize_method == "upper_bound":
|
148 |
+
new_height = self.constrain_to_multiple_of(
|
149 |
+
scale_height * height, max_val=self.__height
|
150 |
+
)
|
151 |
+
new_width = self.constrain_to_multiple_of(
|
152 |
+
scale_width * width, max_val=self.__width
|
153 |
+
)
|
154 |
+
elif self.__resize_method == "minimal":
|
155 |
+
new_height = self.constrain_to_multiple_of(scale_height * height)
|
156 |
+
new_width = self.constrain_to_multiple_of(scale_width * width)
|
157 |
+
else:
|
158 |
+
raise ValueError(f"resize_method {self.__resize_method} not implemented")
|
159 |
+
|
160 |
+
return (new_width, new_height)
|
161 |
+
|
162 |
+
def __call__(self, sample):
|
163 |
+
width, height = self.get_size(
|
164 |
+
sample["image"].shape[1], sample["image"].shape[0]
|
165 |
+
)
|
166 |
+
|
167 |
+
# resize sample
|
168 |
+
sample["image"] = cv2.resize(
|
169 |
+
sample["image"],
|
170 |
+
(width, height),
|
171 |
+
interpolation=self.__image_interpolation_method,
|
172 |
+
)
|
173 |
+
|
174 |
+
if self.__resize_target:
|
175 |
+
if "disparity" in sample:
|
176 |
+
sample["disparity"] = cv2.resize(
|
177 |
+
sample["disparity"],
|
178 |
+
(width, height),
|
179 |
+
interpolation=cv2.INTER_NEAREST,
|
180 |
+
)
|
181 |
+
|
182 |
+
if "depth" in sample:
|
183 |
+
sample["depth"] = cv2.resize(
|
184 |
+
sample["depth"], (width, height), interpolation=cv2.INTER_NEAREST
|
185 |
+
)
|
186 |
+
|
187 |
+
sample["mask"] = cv2.resize(
|
188 |
+
sample["mask"].astype(np.float32),
|
189 |
+
(width, height),
|
190 |
+
interpolation=cv2.INTER_NEAREST,
|
191 |
+
)
|
192 |
+
sample["mask"] = sample["mask"].astype(bool)
|
193 |
+
|
194 |
+
return sample
|
195 |
+
|
196 |
+
|
197 |
+
class NormalizeImage(object):
|
198 |
+
"""Normlize image by given mean and std.
|
199 |
+
"""
|
200 |
+
|
201 |
+
def __init__(self, mean, std):
|
202 |
+
self.__mean = mean
|
203 |
+
self.__std = std
|
204 |
+
|
205 |
+
def __call__(self, sample):
|
206 |
+
sample["image"] = (sample["image"] - self.__mean) / self.__std
|
207 |
+
|
208 |
+
return sample
|
209 |
+
|
210 |
+
|
211 |
+
class PrepareForNet(object):
|
212 |
+
"""Prepare sample for usage as network input.
|
213 |
+
"""
|
214 |
+
|
215 |
+
def __init__(self):
|
216 |
+
pass
|
217 |
+
|
218 |
+
def __call__(self, sample):
|
219 |
+
image = np.transpose(sample["image"], (2, 0, 1))
|
220 |
+
sample["image"] = np.ascontiguousarray(image).astype(np.float32)
|
221 |
+
|
222 |
+
if "mask" in sample:
|
223 |
+
sample["mask"] = sample["mask"].astype(np.float32)
|
224 |
+
sample["mask"] = np.ascontiguousarray(sample["mask"])
|
225 |
+
|
226 |
+
if "disparity" in sample:
|
227 |
+
disparity = sample["disparity"].astype(np.float32)
|
228 |
+
sample["disparity"] = np.ascontiguousarray(disparity)
|
229 |
+
|
230 |
+
if "depth" in sample:
|
231 |
+
depth = sample["depth"].astype(np.float32)
|
232 |
+
sample["depth"] = np.ascontiguousarray(depth)
|
233 |
+
|
234 |
+
return sample
|
model_farm_midas_v2_qcs8550_qnn2.16_int8_aidlite/python/utils.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
|
6 |
+
from transforms import Resize, NormalizeImage, PrepareForNet
|
7 |
+
|
8 |
+
from torchvision.transforms import Compose
|
9 |
+
import sys
|
10 |
+
first_execution = True
|
11 |
+
def img_process(img_path):
|
12 |
+
global first_execution
|
13 |
+
first_execution = False
|
14 |
+
net_w, net_h = 256, 256
|
15 |
+
resize_mode = "upper_bound"
|
16 |
+
normalization = NormalizeImage(
|
17 |
+
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
|
18 |
+
)
|
19 |
+
transform = Compose(
|
20 |
+
[
|
21 |
+
Resize(
|
22 |
+
net_w,
|
23 |
+
net_h,
|
24 |
+
resize_target=None,
|
25 |
+
keep_aspect_ratio=False,
|
26 |
+
ensure_multiple_of=32,
|
27 |
+
resize_method=resize_mode,
|
28 |
+
image_interpolation_method=cv2.INTER_CUBIC,
|
29 |
+
),
|
30 |
+
normalization,
|
31 |
+
PrepareForNet(),
|
32 |
+
]
|
33 |
+
)
|
34 |
+
# image = utils.read_image(img_path) # in [0, 1]
|
35 |
+
image = cv2.imread(img_path)
|
36 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) / 255.0
|
37 |
+
org_size= image.shape[:2]
|
38 |
+
image = transform({"image": image})["image"]
|
39 |
+
sample = torch.from_numpy(image).to("cpu").unsqueeze(0)
|
40 |
+
height, width = sample.shape[2:]
|
41 |
+
print(f"Input resized to {width}x{height} before entering the encoder")
|
42 |
+
|
43 |
+
return sample,org_size
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
def write_depth(path, depth, grayscale=False, bits=1):
|
48 |
+
if not grayscale:
|
49 |
+
bits = 1
|
50 |
+
|
51 |
+
if not np.isfinite(depth).all():
|
52 |
+
depth=np.nan_to_num(depth, nan=0.0, posinf=0.0, neginf=0.0)
|
53 |
+
print("WARNING: Non-finite depth values present")
|
54 |
+
|
55 |
+
depth_min = depth.min()
|
56 |
+
depth_max = depth.max()
|
57 |
+
|
58 |
+
max_val = (2**(8*bits))-1
|
59 |
+
|
60 |
+
if depth_max - depth_min > np.finfo("float").eps:
|
61 |
+
out = max_val * (depth - depth_min) / (depth_max - depth_min)
|
62 |
+
else:
|
63 |
+
out = np.zeros(depth.shape, dtype=depth.dtype)
|
64 |
+
|
65 |
+
# print("out :",out.shape,out)
|
66 |
+
if not grayscale:
|
67 |
+
out = cv2.applyColorMap(np.uint8(out), cv2.COLORMAP_INFERNO)
|
68 |
+
|
69 |
+
if bits == 1:
|
70 |
+
cv2.imwrite(path , out.astype("uint8"))
|
71 |
+
elif bits == 2:
|
72 |
+
cv2.imwrite(path , out.astype("uint16"))
|
73 |
+
|
74 |
+
return
|
75 |
+
|
76 |
+
def write_pfm(path, image, scale=1):
|
77 |
+
with open(path, "wb") as file:
|
78 |
+
color = None
|
79 |
+
|
80 |
+
if image.dtype.name != "float32":
|
81 |
+
raise Exception("Image dtype must be float32.")
|
82 |
+
|
83 |
+
image = np.flipud(image)
|
84 |
+
|
85 |
+
if len(image.shape) == 3 and image.shape[2] == 3: # color image
|
86 |
+
color = True
|
87 |
+
elif (
|
88 |
+
len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1
|
89 |
+
): # greyscale
|
90 |
+
color = False
|
91 |
+
else:
|
92 |
+
raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")
|
93 |
+
|
94 |
+
file.write("PF\n" if color else "Pf\n".encode())
|
95 |
+
file.write("%d %d\n".encode() % (image.shape[1], image.shape[0]))
|
96 |
+
|
97 |
+
endian = image.dtype.byteorder
|
98 |
+
|
99 |
+
if endian == "<" or endian == "=" and sys.byteorder == "little":
|
100 |
+
scale = -scale
|
101 |
+
|
102 |
+
file.write("%f\n".encode() % scale)
|
103 |
+
|
104 |
+
image.tofile(file)
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## Model Information
|
2 |
+
|
3 |
+
### Source model
|
4 |
+
- Input shape: 1x3x256x256
|
5 |
+
- Number of parameters: 20.33M
|
6 |
+
- Model size: 82.17M
|
7 |
+
- Output shape: 1x1x256x256
|
8 |
+
|
9 |
+
Source model repository: [midas](https://github.com/isl-org/MiDaS/tree/master)
|
10 |
+
|
11 |
+
### Converted model
|
12 |
+
|
13 |
+
- Precision: INT8
|
14 |
+
- Backend: QNN2.16
|
15 |
+
- Target Device: SNM972 QCS8550
|
16 |
+
|
17 |
+
## Inference with AidLite SDK
|
18 |
+
|
19 |
+
### SDK installation
|
20 |
+
Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
|
21 |
+
|
22 |
+
- Install AidLite SDK
|
23 |
+
|
24 |
+
```bash
|
25 |
+
# Install the appropriate version of the aidlite sdk
|
26 |
+
sudo aid-pkg update
|
27 |
+
sudo aid-pkg install aidlite-sdk
|
28 |
+
# Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
|
29 |
+
sudo aid-pkg install aidlite-{QNN VERSION}
|
30 |
+
```
|
31 |
+
|
32 |
+
- Verify AidLite SDK
|
33 |
+
|
34 |
+
```bash
|
35 |
+
# aidlite sdk c++ check
|
36 |
+
python3 -c "import aidlite ; print(aidlite.get_library_version())"
|
37 |
+
|
38 |
+
# aidlite sdk python check, Aidlux_Aidlite version <=2.1.0
|
39 |
+
python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
|
40 |
+
```
|
41 |
+
|
42 |
+
### Run Demo
|
43 |
+
#### python
|
44 |
+
```bash
|
45 |
+
cd model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite
|
46 |
+
python3 python/run_test.py --target_model ./models/midas_v2_w8a16.qnn216.ctx.bin --imgs ./python/dog.jpg --invoke_nums 10
|
47 |
+
```
|
48 |
+
|
49 |
+
|
50 |
+
#### c++
|
51 |
+
```bash
|
52 |
+
cd midas_v2/model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp
|
53 |
+
mkdir build && cd build
|
54 |
+
cmake ..
|
55 |
+
make
|
56 |
+
./run_test
|
57 |
+
```
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp/CMakeLists.txt
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
cmake_minimum_required (VERSION 3.5)
|
2 |
+
project("run_test")
|
3 |
+
|
4 |
+
find_package(OpenCV REQUIRED)
|
5 |
+
|
6 |
+
message(STATUS "oPENCV Library status:")
|
7 |
+
message(STATUS ">version:${OpenCV_VERSION}")
|
8 |
+
message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
|
9 |
+
|
10 |
+
set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
|
11 |
+
|
12 |
+
include_directories(
|
13 |
+
/usr/local/include
|
14 |
+
/usr/include/opencv4
|
15 |
+
)
|
16 |
+
|
17 |
+
link_directories(
|
18 |
+
/usr/local/lib/
|
19 |
+
)
|
20 |
+
|
21 |
+
file(GLOB SRC_LISTS
|
22 |
+
${CMAKE_CURRENT_SOURCE_DIR}/run_test.cpp
|
23 |
+
)
|
24 |
+
|
25 |
+
add_executable(run_test ${SRC_LISTS})
|
26 |
+
|
27 |
+
target_link_libraries(run_test
|
28 |
+
aidlite
|
29 |
+
${OpenCV_LIBS}
|
30 |
+
pthread
|
31 |
+
jsoncpp
|
32 |
+
)
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/cpp/run_test.cpp
ADDED
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#include <iostream>
|
2 |
+
#include <fstream>
|
3 |
+
#include <opencv2/opencv.hpp>
|
4 |
+
#include <aidlux/aidlite/aidlite.hpp>
|
5 |
+
#include <vector>
|
6 |
+
#include <numeric>
|
7 |
+
#include <cmath>
|
8 |
+
#include <jsoncpp/json/json.h>
|
9 |
+
|
10 |
+
using namespace cv;
|
11 |
+
using namespace std;
|
12 |
+
using namespace Aidlux::Aidlite;
|
13 |
+
|
14 |
+
const int net_w = 256;
|
15 |
+
const int net_h = 256;
|
16 |
+
|
17 |
+
const std::vector<float> mean_vals = {0.485f, 0.456f, 0.406f};
|
18 |
+
const std::vector<float> std_vals = {0.229f, 0.224f, 0.225f};
|
19 |
+
|
20 |
+
|
21 |
+
struct Args {
|
22 |
+
std::string target_model = "../../models/midas_v2_w8a16.qnn216.ctx.bin";
|
23 |
+
std::string imgs = "../dog.jpg";
|
24 |
+
int invoke_nums = 10;
|
25 |
+
std::string model_type = "QNN";
|
26 |
+
};
|
27 |
+
|
28 |
+
|
29 |
+
Args parse_args(int argc, char* argv[]) {
|
30 |
+
Args args;
|
31 |
+
for (int i = 1; i < argc; ++i) {
|
32 |
+
std::string arg = argv[i];
|
33 |
+
if (arg == "--target_model" && i + 1 < argc) {
|
34 |
+
args.target_model = argv[++i];
|
35 |
+
} else if (arg == "--imgs" && i + 1 < argc) {
|
36 |
+
args.imgs = argv[++i];
|
37 |
+
} else if (arg == "--invoke_nums" && i + 1 < argc) {
|
38 |
+
args.invoke_nums = std::stoi(argv[++i]);
|
39 |
+
} else if (arg == "--model_type" && i + 1 < argc) {
|
40 |
+
args.model_type = argv[++i];
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return args;
|
44 |
+
}
|
45 |
+
|
46 |
+
std::string to_lower(const std::string& str) {
|
47 |
+
std::string lower_str = str;
|
48 |
+
std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
|
49 |
+
return std::tolower(c);
|
50 |
+
});
|
51 |
+
return lower_str;
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
|
56 |
+
|
57 |
+
int current_coordinate[4] = {0, 0, 0, 0};
|
58 |
+
for(int a = 0; a < src_dims[0]; ++a){
|
59 |
+
current_coordinate[0] = a;
|
60 |
+
for(int b = 0; b < src_dims[1]; ++b){
|
61 |
+
current_coordinate[1] = b;
|
62 |
+
for(int c = 0; c < src_dims[2]; ++c){
|
63 |
+
current_coordinate[2] = c;
|
64 |
+
for(int d = 0; d < src_dims[3]; ++d){
|
65 |
+
current_coordinate[3] = d;
|
66 |
+
|
67 |
+
int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
|
68 |
+
current_coordinate[1]*src_dims[2]*src_dims[3] +
|
69 |
+
current_coordinate[2]*src_dims[3] +
|
70 |
+
current_coordinate[3];
|
71 |
+
|
72 |
+
int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
73 |
+
current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
74 |
+
current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
|
75 |
+
current_coordinate[tsp_dims[3]];
|
76 |
+
|
77 |
+
dest[new_index] = src[old_index];
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
return EXIT_SUCCESS;
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
// 替代 np.nan_to_num
|
88 |
+
void sanitizeDepthMap(cv::Mat& depth) {
|
89 |
+
for (int y = 0; y < depth.rows; ++y) {
|
90 |
+
float* row = depth.ptr<float>(y);
|
91 |
+
for (int x = 0; x < depth.cols; ++x) {
|
92 |
+
float val = row[x];
|
93 |
+
if (!std::isfinite(val)) {
|
94 |
+
row[x] = 0.0f;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
// 等效于 Python write_depth
|
101 |
+
void write_depth(const std::string& path, const cv::Mat& input_depth, bool grayscale = false, int bits = 1) {
|
102 |
+
CV_Assert(input_depth.type() == CV_32FC1);
|
103 |
+
|
104 |
+
// 拷贝 + 处理非法值
|
105 |
+
cv::Mat depth = input_depth.clone();
|
106 |
+
sanitizeDepthMap(depth);
|
107 |
+
|
108 |
+
double minVal, maxVal;
|
109 |
+
cv::minMaxLoc(depth, &minVal, &maxVal);
|
110 |
+
|
111 |
+
double max_val = (1 << (8 * bits)) - 1;
|
112 |
+
cv::Mat out;
|
113 |
+
|
114 |
+
if (maxVal - minVal > std::numeric_limits<float>::epsilon()) {
|
115 |
+
// 归一化并映射到位深范围
|
116 |
+
out = (depth - minVal) * (max_val / (maxVal - minVal));
|
117 |
+
} else {
|
118 |
+
out = cv::Mat::zeros(depth.size(), CV_32F);
|
119 |
+
}
|
120 |
+
|
121 |
+
if (!grayscale) {
|
122 |
+
out.convertTo(out, CV_8UC1);
|
123 |
+
cv::applyColorMap(out, out, cv::COLORMAP_INFERNO);
|
124 |
+
}
|
125 |
+
|
126 |
+
if (bits == 1) {
|
127 |
+
out.convertTo(out, CV_8U);
|
128 |
+
} else if (bits == 2) {
|
129 |
+
out.convertTo(out, CV_16U);
|
130 |
+
}
|
131 |
+
|
132 |
+
cv::imwrite(path, out);
|
133 |
+
}
|
134 |
+
|
135 |
+
// 等效于 Python write_pfm
|
136 |
+
void write_pfm(const std::string& path, const cv::Mat& image, float scale = 1.0f) {
|
137 |
+
CV_Assert(image.type() == CV_32FC1 || image.type() == CV_32FC3);
|
138 |
+
|
139 |
+
std::ofstream file(path, std::ios::binary);
|
140 |
+
if (!file.is_open()) {
|
141 |
+
std::cerr << "Failed to open file for writing PFM: " << path << std::endl;
|
142 |
+
return;
|
143 |
+
}
|
144 |
+
|
145 |
+
int width = image.cols;
|
146 |
+
int height = image.rows;
|
147 |
+
int channels = image.channels();
|
148 |
+
bool color = (channels == 3);
|
149 |
+
|
150 |
+
file << (color ? "PF" : "Pf") << "\n";
|
151 |
+
file << width << " " << height << "\n";
|
152 |
+
|
153 |
+
// Endianness: negative = little-endian
|
154 |
+
uint16_t endian_test = 0x1;
|
155 |
+
bool is_little_endian = *(reinterpret_cast<uint8_t*>(&endian_test)) == 0x1;
|
156 |
+
if (is_little_endian) {
|
157 |
+
scale = -scale;
|
158 |
+
}
|
159 |
+
|
160 |
+
file << scale << "\n";
|
161 |
+
|
162 |
+
// Flip vertically (OpenCV top-left origin -> PFM bottom-left origin)
|
163 |
+
cv::Mat flipped;
|
164 |
+
cv::flip(image, flipped, 0);
|
165 |
+
|
166 |
+
// Write raw data
|
167 |
+
file.write(reinterpret_cast<const char*>(flipped.data), flipped.total() * channels * sizeof(float));
|
168 |
+
file.close();
|
169 |
+
}
|
170 |
+
|
171 |
+
|
172 |
+
// ======================= Normalize =======================
|
173 |
+
void normalize(cv::Mat& image) {
|
174 |
+
CV_Assert(image.type() == CV_32FC3);
|
175 |
+
int rows = image.rows;
|
176 |
+
int cols = image.cols;
|
177 |
+
|
178 |
+
for (int y = 0; y < rows; ++y) {
|
179 |
+
cv::Vec3f* row = image.ptr<cv::Vec3f>(y);
|
180 |
+
for (int x = 0; x < cols; ++x) {
|
181 |
+
for (int c = 0; c < 3; ++c) {
|
182 |
+
row[x][c] = (row[x][c] - mean_vals[c]) / std_vals[c];
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
cv::Mat hwc_to_chw(const cv::Mat& image) {
|
189 |
+
std::vector<cv::Mat> channels(3);
|
190 |
+
cv::split(image, channels);
|
191 |
+
|
192 |
+
cv::Mat chw(3, image.rows * image.cols, CV_32F);
|
193 |
+
for (int c = 0; c < 3; ++c) {
|
194 |
+
memcpy(chw.ptr(c), channels[c].data, image.rows * image.cols * sizeof(float));
|
195 |
+
}
|
196 |
+
|
197 |
+
return chw;
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
bool first_execution = true;
|
202 |
+
cv::Mat img_process(const cv::Mat image_bgr, cv::Size& org_size_out) {
|
203 |
+
first_execution = false;
|
204 |
+
|
205 |
+
cv::Mat image_rgb;
|
206 |
+
cv::cvtColor(image_bgr, image_rgb, cv::COLOR_BGR2RGB);
|
207 |
+
image_rgb.convertTo(image_rgb, CV_32FC3, 1.0 / 255.0);
|
208 |
+
|
209 |
+
// 2. Save original size
|
210 |
+
org_size_out = image_rgb.size(); // H x W
|
211 |
+
|
212 |
+
// 3. Resize to 256x256 using cubic interpolation
|
213 |
+
cv::resize(image_rgb, image_rgb, cv::Size(net_w, net_h), 0, 0, cv::INTER_CUBIC);
|
214 |
+
|
215 |
+
// 4. Normalize using mean/std
|
216 |
+
normalize(image_rgb);
|
217 |
+
|
218 |
+
// 5. Convert HWC to CHW
|
219 |
+
cv::Mat chw = hwc_to_chw(image_rgb);
|
220 |
+
|
221 |
+
// 6. Add batch dimension: [1, C, H, W] → reshape to 1x3xHxW style float array
|
222 |
+
cv::Mat input_tensor(1, 3 * net_h * net_w, CV_32F);
|
223 |
+
memcpy(input_tensor.ptr<float>(), chw.data, 3 * net_h * net_w * sizeof(float));
|
224 |
+
|
225 |
+
std::cout << "Input resized to " << net_w << "x" << net_h << " before entering the encoder" << std::endl;
|
226 |
+
|
227 |
+
return input_tensor;
|
228 |
+
}
|
229 |
+
|
230 |
+
|
231 |
+
float* matToFloatPtr(const cv::Mat& input_mat, bool normalize = true) {
|
232 |
+
// 检查连续性
|
233 |
+
cv::Mat mat = input_mat;
|
234 |
+
if (!mat.isContinuous()) {
|
235 |
+
mat = mat.clone();
|
236 |
+
}
|
237 |
+
|
238 |
+
// 分配内存
|
239 |
+
int total_pixels = mat.rows * mat.cols;
|
240 |
+
int channels = mat.channels();
|
241 |
+
float* float_data = new float[total_pixels * channels];
|
242 |
+
|
243 |
+
// 根据数据类型转换
|
244 |
+
if (mat.type() == CV_8UC1 || mat.type() == CV_8UC3) {
|
245 |
+
uchar* ptr = mat.ptr<uchar>(0);
|
246 |
+
for (int i = 0; i < total_pixels * channels; ++i) {
|
247 |
+
float_data[i] = normalize ? (static_cast<float>(ptr[i]) / 255.0f) : ptr[i];
|
248 |
+
}
|
249 |
+
} else if (mat.type() == CV_32FC1 || mat.type() == CV_32FC3) {
|
250 |
+
float* ptr = mat.ptr<float>(0);
|
251 |
+
std::memcpy(float_data, ptr, total_pixels * channels * sizeof(float));
|
252 |
+
} else {
|
253 |
+
delete[] float_data;
|
254 |
+
return nullptr; // 不支持的类型
|
255 |
+
}
|
256 |
+
|
257 |
+
return float_data;
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
int invoke(const Args& args) {
|
262 |
+
std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
|
263 |
+
<< "Image Path: " << args.imgs << "\n"
|
264 |
+
<< "Inference Nums: " << args.invoke_nums << "\n"
|
265 |
+
<< "Model Type: " << args.model_type << "\n";
|
266 |
+
Model* model = Model::create_instance(args.target_model);
|
267 |
+
if(model == nullptr){
|
268 |
+
printf("Create model failed !\n");
|
269 |
+
return EXIT_FAILURE;
|
270 |
+
}
|
271 |
+
Config* config = Config::create_instance();
|
272 |
+
if(config == nullptr){
|
273 |
+
printf("Create config failed !\n");
|
274 |
+
return EXIT_FAILURE;
|
275 |
+
}
|
276 |
+
config->implement_type = ImplementType::TYPE_LOCAL;
|
277 |
+
std::string model_type_lower = to_lower(args.model_type);
|
278 |
+
if (model_type_lower == "qnn"){
|
279 |
+
config->framework_type = FrameworkType::TYPE_QNN;
|
280 |
+
} else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
|
281 |
+
config->framework_type = FrameworkType::TYPE_SNPE2;
|
282 |
+
}
|
283 |
+
config->accelerate_type = AccelerateType::TYPE_DSP;
|
284 |
+
config->is_quantify_model = 1;
|
285 |
+
|
286 |
+
unsigned int model_h = 256;
|
287 |
+
unsigned int model_w = 256;
|
288 |
+
std::vector<std::vector<uint32_t>> input_shapes = {{1,model_h,model_w,3}};
|
289 |
+
std::vector<std::vector<uint32_t>> output_shapes = {{1,model_h,model_w,1}};
|
290 |
+
model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
|
291 |
+
std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
|
292 |
+
if(fast_interpreter == nullptr){
|
293 |
+
printf("build_interpretper_from_model_and_config failed !\n");
|
294 |
+
return EXIT_FAILURE;
|
295 |
+
}
|
296 |
+
int result = fast_interpreter->init();
|
297 |
+
if(result != EXIT_SUCCESS){
|
298 |
+
printf("interpreter->init() failed !\n");
|
299 |
+
return EXIT_FAILURE;
|
300 |
+
}
|
301 |
+
// load model
|
302 |
+
fast_interpreter->load_model();
|
303 |
+
if(result != EXIT_SUCCESS){
|
304 |
+
printf("interpreter->load_model() failed !\n");
|
305 |
+
return EXIT_FAILURE;
|
306 |
+
}
|
307 |
+
printf("detect model load success!\n");
|
308 |
+
|
309 |
+
cv::Mat frame = cv::imread(args.imgs);
|
310 |
+
if (frame.empty()) {
|
311 |
+
printf("detect image load failed!\n");
|
312 |
+
return 1;
|
313 |
+
}
|
314 |
+
printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
|
315 |
+
cv::Mat input_data;
|
316 |
+
cv::Mat frame_clone = frame.clone();
|
317 |
+
int h = frame_clone.rows;
|
318 |
+
int w = frame_clone.cols;
|
319 |
+
cv::Size org_size(w, h);
|
320 |
+
cv::Size org_size0(256, 256);
|
321 |
+
|
322 |
+
cv::Mat input_tensor = img_process(frame_clone, org_size0);
|
323 |
+
float* float_data = matToFloatPtr(input_tensor);
|
324 |
+
unsigned int src_dims[4] = {1, 3, 256, 256};
|
325 |
+
unsigned int tsp_dims[4] = {0,2,3,1};
|
326 |
+
unsigned int stride_data_num = 1*256*256*3;
|
327 |
+
float* format_data = new float[stride_data_num];
|
328 |
+
transpose(float_data, src_dims, tsp_dims, format_data);
|
329 |
+
cv::Mat origin_buffer(3,256*256, CV_32F, format_data);
|
330 |
+
|
331 |
+
float *outdata0 = nullptr;
|
332 |
+
std::vector<float> invoke_time;
|
333 |
+
for (int i = 0; i < args.invoke_nums; ++i) {
|
334 |
+
result = fast_interpreter->set_input_tensor(0, origin_buffer.data);
|
335 |
+
if(result != EXIT_SUCCESS){
|
336 |
+
printf("interpreter->set_input_tensor() failed !\n");
|
337 |
+
return EXIT_FAILURE;
|
338 |
+
}
|
339 |
+
auto t1 = std::chrono::high_resolution_clock::now();
|
340 |
+
result = fast_interpreter->invoke();
|
341 |
+
auto t2 = std::chrono::high_resolution_clock::now();
|
342 |
+
std::chrono::duration<double> cost_time = t2 - t1;
|
343 |
+
invoke_time.push_back(cost_time.count() * 1000);
|
344 |
+
if(result != EXIT_SUCCESS){
|
345 |
+
printf("interpreter->invoke() failed !\n");
|
346 |
+
return EXIT_FAILURE;
|
347 |
+
}
|
348 |
+
uint32_t out_data_0 = 0;
|
349 |
+
result = fast_interpreter->get_output_tensor(0, (void**)&outdata0, &out_data_0);
|
350 |
+
if(result != EXIT_SUCCESS){
|
351 |
+
printf("interpreter->get_output_tensor() 1 failed !\n");
|
352 |
+
return EXIT_FAILURE;
|
353 |
+
}
|
354 |
+
|
355 |
+
}
|
356 |
+
|
357 |
+
float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
|
358 |
+
float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
|
359 |
+
float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
|
360 |
+
float var_invoketime = 0.0f;
|
361 |
+
for (auto time : invoke_time) {
|
362 |
+
var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
|
363 |
+
}
|
364 |
+
var_invoketime /= args.invoke_nums;
|
365 |
+
printf("=======================================\n");
|
366 |
+
printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
|
367 |
+
args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
|
368 |
+
printf("=======================================\n");
|
369 |
+
|
370 |
+
// post process
|
371 |
+
cv::Mat out_buffer(1,256*256, CV_32F, outdata0);
|
372 |
+
cv::Mat prediction_2d(256, 256, CV_32F, (void*)out_buffer.ptr<float>());
|
373 |
+
cv::Mat resized;
|
374 |
+
cv::resize(prediction_2d, resized, org_size, 0, 0, cv::INTER_CUBIC);
|
375 |
+
|
376 |
+
// 保存为图像
|
377 |
+
write_depth("depth_output.jpg", resized, false, 1);
|
378 |
+
|
379 |
+
// 保存为 PFM
|
380 |
+
write_pfm("depth_output.pfm", resized);
|
381 |
+
|
382 |
+
|
383 |
+
|
384 |
+
fast_interpreter->destory();
|
385 |
+
return 0;
|
386 |
+
}
|
387 |
+
|
388 |
+
|
389 |
+
int main(int argc, char* argv[]) {
|
390 |
+
Args args = parse_args(argc, argv);
|
391 |
+
return invoke(args);
|
392 |
+
}
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/models/midas_v2_w8a16.qnn216.ctx.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:0e26a9e1f7c7879c958086c295514e488ca9ecb7debab782a75158afd76982fd
|
3 |
+
size 19263488
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/dog.jpg
ADDED
![]() |
Git LFS Details
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/run_test.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
from utils import write_pfm,write_depth,img_process
|
6 |
+
import aidlite
|
7 |
+
import time
|
8 |
+
import argparse
|
9 |
+
|
10 |
+
def out_process(prediction,target_size):
|
11 |
+
prediction = torch.nn.functional.interpolate(
|
12 |
+
prediction,
|
13 |
+
size=target_size,
|
14 |
+
mode="bicubic",
|
15 |
+
align_corners=False,
|
16 |
+
)
|
17 |
+
prediction = prediction.squeeze().detach().numpy()
|
18 |
+
return prediction
|
19 |
+
|
20 |
+
class run_qnn:
|
21 |
+
def __init__(self,qnn_path):
|
22 |
+
super().__init__()
|
23 |
+
self.model = aidlite.Model.create_instance(qnn_path)
|
24 |
+
if self.model is None:
|
25 |
+
print("Create model failed !")
|
26 |
+
return
|
27 |
+
|
28 |
+
self.config = aidlite.Config.create_instance()
|
29 |
+
if self.config is None:
|
30 |
+
print("build_interpretper_from_model_and_config failed !")
|
31 |
+
return
|
32 |
+
|
33 |
+
self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
|
34 |
+
self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
|
35 |
+
self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
|
36 |
+
# self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
|
37 |
+
self.config.is_quantify_model = 1
|
38 |
+
|
39 |
+
self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
|
40 |
+
if self.interpreter is None:
|
41 |
+
print("build_interpretper_from_model_and_config failed !")
|
42 |
+
return
|
43 |
+
input_shapes = [[1,256,256,3]]
|
44 |
+
output_shapes = [[1,256,256,1]]
|
45 |
+
self.model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
|
46 |
+
output_shapes, aidlite.DataType.TYPE_FLOAT32)
|
47 |
+
|
48 |
+
if self.interpreter is None:
|
49 |
+
print("build_interpretper_from_model_and_config failed !")
|
50 |
+
result = self.interpreter.init()
|
51 |
+
if result != 0:
|
52 |
+
print(f"interpreter init failed !")
|
53 |
+
result = self.interpreter.load_model()
|
54 |
+
if result != 0:
|
55 |
+
print("interpreter load model failed !")
|
56 |
+
|
57 |
+
print(" model load success!")
|
58 |
+
|
59 |
+
def __call__(self, input,invoke_nums):
|
60 |
+
self.interpreter.set_input_tensor(0,input)
|
61 |
+
invoke_time=[]
|
62 |
+
for i in range(invoke_nums):
|
63 |
+
result = self.interpreter.set_input_tensor(0, input.data)
|
64 |
+
if result != 0:
|
65 |
+
print("interpreter set_input_tensor() failed")
|
66 |
+
t1=time.time()
|
67 |
+
result = self.interpreter.invoke()
|
68 |
+
cost_time = (time.time()-t1)*1000
|
69 |
+
invoke_time.append(cost_time)
|
70 |
+
|
71 |
+
max_invoke_time = max(invoke_time)
|
72 |
+
min_invoke_time = min(invoke_time)
|
73 |
+
mean_invoke_time = sum(invoke_time)/invoke_nums
|
74 |
+
var_invoketime=np.var(invoke_time)
|
75 |
+
print("====================================")
|
76 |
+
print(f"QNN invoke time:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
|
77 |
+
print("====================================")
|
78 |
+
features_0 = self.interpreter.get_output_tensor(0).reshape(1,256,256,1).transpose(0,3,1,2)
|
79 |
+
return features_0
|
80 |
+
|
81 |
+
|
82 |
+
|
83 |
+
def run(args):
|
84 |
+
img_path = args.imgs
|
85 |
+
qnn_path = args.target_model
|
86 |
+
invoke_num=args.invoke_nums
|
87 |
+
print("Start processing...")
|
88 |
+
img_input,org_size = img_process(img_path)
|
89 |
+
|
90 |
+
qnn_model =run_qnn(qnn_path)
|
91 |
+
prediction_qnn = qnn_model(img_input.numpy().transpose(0,2,3,1),invoke_num)
|
92 |
+
prediction_qnn = torch.tensor(prediction_qnn)
|
93 |
+
qnn_process = out_process(prediction_qnn,org_size)
|
94 |
+
|
95 |
+
write_depth("./python/results.jpg", qnn_process, grayscale=False, bits=1)
|
96 |
+
write_pfm("./python/results.pfm", qnn_process.astype(np.float32))
|
97 |
+
print("Finished")
|
98 |
+
|
99 |
+
def parser_args():
|
100 |
+
parser = argparse.ArgumentParser(description="Run model benchmarks")
|
101 |
+
parser.add_argument('--target_model',type=str,default='./models/midas_v2_w8a16.qnn216.ctx.bin',help="Inference model path")
|
102 |
+
parser.add_argument('--imgs',type=str,default='./python/dog.jpg',help="Predict images path")
|
103 |
+
parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
|
104 |
+
parser.add_argument('--model_type',type=str,default='QNN',help="Run backend")
|
105 |
+
args = parser.parse_args()
|
106 |
+
return args
|
107 |
+
|
108 |
+
|
109 |
+
if __name__ =="__main__":
|
110 |
+
args = parser_args()
|
111 |
+
run(args)
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/transforms.py
ADDED
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
import math
|
4 |
+
|
5 |
+
|
6 |
+
def apply_min_size(sample, size, image_interpolation_method=cv2.INTER_AREA):
|
7 |
+
"""Rezise the sample to ensure the given size. Keeps aspect ratio.
|
8 |
+
|
9 |
+
Args:
|
10 |
+
sample (dict): sample
|
11 |
+
size (tuple): image size
|
12 |
+
|
13 |
+
Returns:
|
14 |
+
tuple: new size
|
15 |
+
"""
|
16 |
+
shape = list(sample["disparity"].shape)
|
17 |
+
|
18 |
+
if shape[0] >= size[0] and shape[1] >= size[1]:
|
19 |
+
return sample
|
20 |
+
|
21 |
+
scale = [0, 0]
|
22 |
+
scale[0] = size[0] / shape[0]
|
23 |
+
scale[1] = size[1] / shape[1]
|
24 |
+
|
25 |
+
scale = max(scale)
|
26 |
+
|
27 |
+
shape[0] = math.ceil(scale * shape[0])
|
28 |
+
shape[1] = math.ceil(scale * shape[1])
|
29 |
+
|
30 |
+
# resize
|
31 |
+
sample["image"] = cv2.resize(
|
32 |
+
sample["image"], tuple(shape[::-1]), interpolation=image_interpolation_method
|
33 |
+
)
|
34 |
+
|
35 |
+
sample["disparity"] = cv2.resize(
|
36 |
+
sample["disparity"], tuple(shape[::-1]), interpolation=cv2.INTER_NEAREST
|
37 |
+
)
|
38 |
+
sample["mask"] = cv2.resize(
|
39 |
+
sample["mask"].astype(np.float32),
|
40 |
+
tuple(shape[::-1]),
|
41 |
+
interpolation=cv2.INTER_NEAREST,
|
42 |
+
)
|
43 |
+
sample["mask"] = sample["mask"].astype(bool)
|
44 |
+
|
45 |
+
return tuple(shape)
|
46 |
+
|
47 |
+
|
48 |
+
class Resize(object):
|
49 |
+
"""Resize sample to given size (width, height).
|
50 |
+
"""
|
51 |
+
|
52 |
+
def __init__(
|
53 |
+
self,
|
54 |
+
width,
|
55 |
+
height,
|
56 |
+
resize_target=True,
|
57 |
+
keep_aspect_ratio=False,
|
58 |
+
ensure_multiple_of=1,
|
59 |
+
resize_method="lower_bound",
|
60 |
+
image_interpolation_method=cv2.INTER_AREA,
|
61 |
+
):
|
62 |
+
"""Init.
|
63 |
+
|
64 |
+
Args:
|
65 |
+
width (int): desired output width
|
66 |
+
height (int): desired output height
|
67 |
+
resize_target (bool, optional):
|
68 |
+
True: Resize the full sample (image, mask, target).
|
69 |
+
False: Resize image only.
|
70 |
+
Defaults to True.
|
71 |
+
keep_aspect_ratio (bool, optional):
|
72 |
+
True: Keep the aspect ratio of the input sample.
|
73 |
+
Output sample might not have the given width and height, and
|
74 |
+
resize behaviour depends on the parameter 'resize_method'.
|
75 |
+
Defaults to False.
|
76 |
+
ensure_multiple_of (int, optional):
|
77 |
+
Output width and height is constrained to be multiple of this parameter.
|
78 |
+
Defaults to 1.
|
79 |
+
resize_method (str, optional):
|
80 |
+
"lower_bound": Output will be at least as large as the given size.
|
81 |
+
"upper_bound": Output will be at max as large as the given size. (Output size might be smaller than given size.)
|
82 |
+
"minimal": Scale as least as possible. (Output size might be smaller than given size.)
|
83 |
+
Defaults to "lower_bound".
|
84 |
+
"""
|
85 |
+
self.__width = width
|
86 |
+
self.__height = height
|
87 |
+
|
88 |
+
self.__resize_target = resize_target
|
89 |
+
self.__keep_aspect_ratio = keep_aspect_ratio
|
90 |
+
self.__multiple_of = ensure_multiple_of
|
91 |
+
self.__resize_method = resize_method
|
92 |
+
self.__image_interpolation_method = image_interpolation_method
|
93 |
+
|
94 |
+
def constrain_to_multiple_of(self, x, min_val=0, max_val=None):
|
95 |
+
y = (np.round(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
96 |
+
|
97 |
+
if max_val is not None and y > max_val:
|
98 |
+
y = (np.floor(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
99 |
+
|
100 |
+
if y < min_val:
|
101 |
+
y = (np.ceil(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
102 |
+
|
103 |
+
return y
|
104 |
+
|
105 |
+
def get_size(self, width, height):
|
106 |
+
# determine new height and width
|
107 |
+
scale_height = self.__height / height
|
108 |
+
scale_width = self.__width / width
|
109 |
+
|
110 |
+
if self.__keep_aspect_ratio:
|
111 |
+
if self.__resize_method == "lower_bound":
|
112 |
+
# scale such that output size is lower bound
|
113 |
+
if scale_width > scale_height:
|
114 |
+
# fit width
|
115 |
+
scale_height = scale_width
|
116 |
+
else:
|
117 |
+
# fit height
|
118 |
+
scale_width = scale_height
|
119 |
+
elif self.__resize_method == "upper_bound":
|
120 |
+
# scale such that output size is upper bound
|
121 |
+
if scale_width < scale_height:
|
122 |
+
# fit width
|
123 |
+
scale_height = scale_width
|
124 |
+
else:
|
125 |
+
# fit height
|
126 |
+
scale_width = scale_height
|
127 |
+
elif self.__resize_method == "minimal":
|
128 |
+
# scale as least as possbile
|
129 |
+
if abs(1 - scale_width) < abs(1 - scale_height):
|
130 |
+
# fit width
|
131 |
+
scale_height = scale_width
|
132 |
+
else:
|
133 |
+
# fit height
|
134 |
+
scale_width = scale_height
|
135 |
+
else:
|
136 |
+
raise ValueError(
|
137 |
+
f"resize_method {self.__resize_method} not implemented"
|
138 |
+
)
|
139 |
+
|
140 |
+
if self.__resize_method == "lower_bound":
|
141 |
+
new_height = self.constrain_to_multiple_of(
|
142 |
+
scale_height * height, min_val=self.__height
|
143 |
+
)
|
144 |
+
new_width = self.constrain_to_multiple_of(
|
145 |
+
scale_width * width, min_val=self.__width
|
146 |
+
)
|
147 |
+
elif self.__resize_method == "upper_bound":
|
148 |
+
new_height = self.constrain_to_multiple_of(
|
149 |
+
scale_height * height, max_val=self.__height
|
150 |
+
)
|
151 |
+
new_width = self.constrain_to_multiple_of(
|
152 |
+
scale_width * width, max_val=self.__width
|
153 |
+
)
|
154 |
+
elif self.__resize_method == "minimal":
|
155 |
+
new_height = self.constrain_to_multiple_of(scale_height * height)
|
156 |
+
new_width = self.constrain_to_multiple_of(scale_width * width)
|
157 |
+
else:
|
158 |
+
raise ValueError(f"resize_method {self.__resize_method} not implemented")
|
159 |
+
|
160 |
+
return (new_width, new_height)
|
161 |
+
|
162 |
+
def __call__(self, sample):
|
163 |
+
width, height = self.get_size(
|
164 |
+
sample["image"].shape[1], sample["image"].shape[0]
|
165 |
+
)
|
166 |
+
|
167 |
+
# resize sample
|
168 |
+
sample["image"] = cv2.resize(
|
169 |
+
sample["image"],
|
170 |
+
(width, height),
|
171 |
+
interpolation=self.__image_interpolation_method,
|
172 |
+
)
|
173 |
+
|
174 |
+
if self.__resize_target:
|
175 |
+
if "disparity" in sample:
|
176 |
+
sample["disparity"] = cv2.resize(
|
177 |
+
sample["disparity"],
|
178 |
+
(width, height),
|
179 |
+
interpolation=cv2.INTER_NEAREST,
|
180 |
+
)
|
181 |
+
|
182 |
+
if "depth" in sample:
|
183 |
+
sample["depth"] = cv2.resize(
|
184 |
+
sample["depth"], (width, height), interpolation=cv2.INTER_NEAREST
|
185 |
+
)
|
186 |
+
|
187 |
+
sample["mask"] = cv2.resize(
|
188 |
+
sample["mask"].astype(np.float32),
|
189 |
+
(width, height),
|
190 |
+
interpolation=cv2.INTER_NEAREST,
|
191 |
+
)
|
192 |
+
sample["mask"] = sample["mask"].astype(bool)
|
193 |
+
|
194 |
+
return sample
|
195 |
+
|
196 |
+
|
197 |
+
class NormalizeImage(object):
|
198 |
+
"""Normlize image by given mean and std.
|
199 |
+
"""
|
200 |
+
|
201 |
+
def __init__(self, mean, std):
|
202 |
+
self.__mean = mean
|
203 |
+
self.__std = std
|
204 |
+
|
205 |
+
def __call__(self, sample):
|
206 |
+
sample["image"] = (sample["image"] - self.__mean) / self.__std
|
207 |
+
|
208 |
+
return sample
|
209 |
+
|
210 |
+
|
211 |
+
class PrepareForNet(object):
|
212 |
+
"""Prepare sample for usage as network input.
|
213 |
+
"""
|
214 |
+
|
215 |
+
def __init__(self):
|
216 |
+
pass
|
217 |
+
|
218 |
+
def __call__(self, sample):
|
219 |
+
image = np.transpose(sample["image"], (2, 0, 1))
|
220 |
+
sample["image"] = np.ascontiguousarray(image).astype(np.float32)
|
221 |
+
|
222 |
+
if "mask" in sample:
|
223 |
+
sample["mask"] = sample["mask"].astype(np.float32)
|
224 |
+
sample["mask"] = np.ascontiguousarray(sample["mask"])
|
225 |
+
|
226 |
+
if "disparity" in sample:
|
227 |
+
disparity = sample["disparity"].astype(np.float32)
|
228 |
+
sample["disparity"] = np.ascontiguousarray(disparity)
|
229 |
+
|
230 |
+
if "depth" in sample:
|
231 |
+
depth = sample["depth"].astype(np.float32)
|
232 |
+
sample["depth"] = np.ascontiguousarray(depth)
|
233 |
+
|
234 |
+
return sample
|
model_farm_midas_v2_qcs8550_qnn2.16_w8a16_aidlite/python/utils.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import torch
|
3 |
+
import cv2
|
4 |
+
import os
|
5 |
+
|
6 |
+
from transforms import Resize, NormalizeImage, PrepareForNet
|
7 |
+
|
8 |
+
from torchvision.transforms import Compose
|
9 |
+
import sys
|
10 |
+
first_execution = True
|
11 |
+
def img_process(img_path):
|
12 |
+
global first_execution
|
13 |
+
first_execution = False
|
14 |
+
net_w, net_h = 256, 256
|
15 |
+
resize_mode = "upper_bound"
|
16 |
+
normalization = NormalizeImage(
|
17 |
+
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]
|
18 |
+
)
|
19 |
+
transform = Compose(
|
20 |
+
[
|
21 |
+
Resize(
|
22 |
+
net_w,
|
23 |
+
net_h,
|
24 |
+
resize_target=None,
|
25 |
+
keep_aspect_ratio=False,
|
26 |
+
ensure_multiple_of=32,
|
27 |
+
resize_method=resize_mode,
|
28 |
+
image_interpolation_method=cv2.INTER_CUBIC,
|
29 |
+
),
|
30 |
+
normalization,
|
31 |
+
PrepareForNet(),
|
32 |
+
]
|
33 |
+
)
|
34 |
+
# image = utils.read_image(img_path) # in [0, 1]
|
35 |
+
image = cv2.imread(img_path)
|
36 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) / 255.0
|
37 |
+
org_size= image.shape[:2]
|
38 |
+
image = transform({"image": image})["image"]
|
39 |
+
sample = torch.from_numpy(image).to("cpu").unsqueeze(0)
|
40 |
+
height, width = sample.shape[2:]
|
41 |
+
print(f"Input resized to {width}x{height} before entering the encoder")
|
42 |
+
|
43 |
+
return sample,org_size
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
def write_depth(path, depth, grayscale=False, bits=1):
|
48 |
+
if not grayscale:
|
49 |
+
bits = 1
|
50 |
+
|
51 |
+
if not np.isfinite(depth).all():
|
52 |
+
depth=np.nan_to_num(depth, nan=0.0, posinf=0.0, neginf=0.0)
|
53 |
+
print("WARNING: Non-finite depth values present")
|
54 |
+
|
55 |
+
depth_min = depth.min()
|
56 |
+
depth_max = depth.max()
|
57 |
+
|
58 |
+
max_val = (2**(8*bits))-1
|
59 |
+
|
60 |
+
if depth_max - depth_min > np.finfo("float").eps:
|
61 |
+
out = max_val * (depth - depth_min) / (depth_max - depth_min)
|
62 |
+
else:
|
63 |
+
out = np.zeros(depth.shape, dtype=depth.dtype)
|
64 |
+
|
65 |
+
# print("out :",out.shape,out)
|
66 |
+
if not grayscale:
|
67 |
+
out = cv2.applyColorMap(np.uint8(out), cv2.COLORMAP_INFERNO)
|
68 |
+
|
69 |
+
if bits == 1:
|
70 |
+
cv2.imwrite(path , out.astype("uint8"))
|
71 |
+
elif bits == 2:
|
72 |
+
cv2.imwrite(path , out.astype("uint16"))
|
73 |
+
|
74 |
+
return
|
75 |
+
|
76 |
+
def write_pfm(path, image, scale=1):
|
77 |
+
with open(path, "wb") as file:
|
78 |
+
color = None
|
79 |
+
|
80 |
+
if image.dtype.name != "float32":
|
81 |
+
raise Exception("Image dtype must be float32.")
|
82 |
+
|
83 |
+
image = np.flipud(image)
|
84 |
+
|
85 |
+
if len(image.shape) == 3 and image.shape[2] == 3: # color image
|
86 |
+
color = True
|
87 |
+
elif (
|
88 |
+
len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1
|
89 |
+
): # greyscale
|
90 |
+
color = False
|
91 |
+
else:
|
92 |
+
raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")
|
93 |
+
|
94 |
+
file.write("PF\n" if color else "Pf\n".encode())
|
95 |
+
file.write("%d %d\n".encode() % (image.shape[1], image.shape[0]))
|
96 |
+
|
97 |
+
endian = image.dtype.byteorder
|
98 |
+
|
99 |
+
if endian == "<" or endian == "=" and sys.byteorder == "little":
|
100 |
+
scale = -scale
|
101 |
+
|
102 |
+
file.write("%f\n".encode() % scale)
|
103 |
+
|
104 |
+
image.tofile(file)
|