Feng Wang
commited on
Commit
·
7ab6881
1
Parent(s):
39bbed9
feat(demo): add android demo of YOLOX
Browse files- demo/ncnn/android/README.md +25 -0
- demo/ncnn/android/app/build.gradle +24 -0
- demo/ncnn/android/app/src/main/AndroidManifest.xml +15 -0
- demo/ncnn/android/app/src/main/assets/yolox.param +222 -0
- demo/ncnn/android/app/src/main/java/com/megvii/yoloXncnn/MainActivity.java +247 -0
- demo/ncnn/android/app/src/main/java/com/megvii/yoloXncnn/YOLOXncnn.java +27 -0
- demo/ncnn/android/app/src/main/java/com/megvii/yoloXncnn/yoloXncnn.java +27 -0
- demo/ncnn/android/app/src/main/jni/CMakeLists.txt +14 -0
- demo/ncnn/android/app/src/main/jni/yoloXncnn_jni.cpp +480 -0
- demo/ncnn/android/app/src/main/res/layout/main.xml +35 -0
- demo/ncnn/android/app/src/main/res/values/strings.xml +4 -0
- demo/ncnn/android/build.gradle +17 -0
- demo/ncnn/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- demo/ncnn/android/gradle/wrapper/gradle-wrapper.properties +6 -0
- demo/ncnn/android/gradlew +172 -0
- demo/ncnn/android/gradlew.bat +84 -0
- demo/ncnn/android/settings.gradle +1 -0
- demo/ncnn/{yolox.cpp → cpp/yolox.cpp} +0 -0
demo/ncnn/android/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# YOLOX-Android-NCNN
|
2 |
+
|
3 |
+
Andoird app of YOLOX object detection base on [NCNN](https://github.com/Tencent/ncnn)
|
4 |
+
|
5 |
+
|
6 |
+
## Tutorial
|
7 |
+
|
8 |
+
### Step1
|
9 |
+
|
10 |
+
Download ncnn-android-vulkan.zip from [releases of ncnn](https://github.com/Tencent/ncnn/releases). This repo us
|
11 |
+
[20210525 release](https://github.com/Tencent/ncnn/releases/download/20210525/ncnn-20210525-android-vulkan.zip) for building.
|
12 |
+
|
13 |
+
### Step2
|
14 |
+
|
15 |
+
After downloading, please extract your zip file. Then, there are two ways to finish this step:
|
16 |
+
* put your extracted directory into app/src/main/jni
|
17 |
+
* change the ncnn_DIR path in app/src/main/jni/CMakeLists.txt to your extracted directory.
|
18 |
+
|
19 |
+
### Step3
|
20 |
+
Open this project with Android Studio, build it and enjoy!
|
21 |
+
|
22 |
+
|
23 |
+
## Reference
|
24 |
+
|
25 |
+
* [ncnn-android-yolov5](https://github.com/nihui/ncnn-android-yolov5)
|
demo/ncnn/android/app/build.gradle
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
apply plugin: 'com.android.application'
|
2 |
+
|
3 |
+
android {
|
4 |
+
compileSdkVersion 24
|
5 |
+
buildToolsVersion "29.0.2"
|
6 |
+
|
7 |
+
defaultConfig {
|
8 |
+
applicationId "com.megvii.yoloXncnn"
|
9 |
+
archivesBaseName = "$applicationId"
|
10 |
+
|
11 |
+
ndk {
|
12 |
+
moduleName "ncnn"
|
13 |
+
abiFilters "armeabi-v7a", "arm64-v8a"
|
14 |
+
}
|
15 |
+
minSdkVersion 24
|
16 |
+
}
|
17 |
+
|
18 |
+
externalNativeBuild {
|
19 |
+
cmake {
|
20 |
+
version "3.10.2"
|
21 |
+
path file('src/main/jni/CMakeLists.txt')
|
22 |
+
}
|
23 |
+
}
|
24 |
+
}
|
demo/ncnn/android/app/src/main/AndroidManifest.xml
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
3 |
+
package="com.megvii.yoloXncnn"
|
4 |
+
android:versionCode="1"
|
5 |
+
android:versionName="1.1">
|
6 |
+
<application android:label="@string/app_name" >
|
7 |
+
<activity android:name="MainActivity"
|
8 |
+
android:label="@string/app_name">
|
9 |
+
<intent-filter>
|
10 |
+
<action android:name="android.intent.action.MAIN" />
|
11 |
+
<category android:name="android.intent.category.LAUNCHER" />
|
12 |
+
</intent-filter>
|
13 |
+
</activity>
|
14 |
+
</application>
|
15 |
+
</manifest>
|
demo/ncnn/android/app/src/main/assets/yolox.param
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
7767517
|
2 |
+
220 250
|
3 |
+
Input images 0 1 images
|
4 |
+
YoloV5Focus focus 1 1 images 503
|
5 |
+
Convolution Conv_41 1 1 503 877 0=32 1=3 4=1 5=1 6=3456
|
6 |
+
Swish Mul_43 1 1 877 507
|
7 |
+
Convolution Conv_44 1 1 507 880 0=64 1=3 3=2 4=1 5=1 6=18432
|
8 |
+
Swish Mul_46 1 1 880 511
|
9 |
+
Split splitncnn_0 1 2 511 511_splitncnn_0 511_splitncnn_1
|
10 |
+
Convolution Conv_47 1 1 511_splitncnn_1 883 0=32 1=1 5=1 6=2048
|
11 |
+
Swish Mul_49 1 1 883 515
|
12 |
+
Split splitncnn_1 1 2 515 515_splitncnn_0 515_splitncnn_1
|
13 |
+
Convolution Conv_50 1 1 511_splitncnn_0 886 0=32 1=1 5=1 6=2048
|
14 |
+
Swish Mul_52 1 1 886 519
|
15 |
+
Convolution Conv_53 1 1 515_splitncnn_1 889 0=32 1=1 5=1 6=1024
|
16 |
+
Swish Mul_55 1 1 889 523
|
17 |
+
Convolution Conv_56 1 1 523 892 0=32 1=3 4=1 5=1 6=9216
|
18 |
+
Swish Mul_58 1 1 892 527
|
19 |
+
BinaryOp Add_59 2 1 527 515_splitncnn_0 528
|
20 |
+
Concat Concat_60 2 1 528 519 529
|
21 |
+
Convolution Conv_61 1 1 529 895 0=64 1=1 5=1 6=4096
|
22 |
+
Swish Mul_63 1 1 895 533
|
23 |
+
Convolution Conv_64 1 1 533 898 0=128 1=3 3=2 4=1 5=1 6=73728
|
24 |
+
Swish Mul_66 1 1 898 537
|
25 |
+
Split splitncnn_2 1 2 537 537_splitncnn_0 537_splitncnn_1
|
26 |
+
Convolution Conv_67 1 1 537_splitncnn_1 901 0=64 1=1 5=1 6=8192
|
27 |
+
Swish Mul_69 1 1 901 541
|
28 |
+
Split splitncnn_3 1 2 541 541_splitncnn_0 541_splitncnn_1
|
29 |
+
Convolution Conv_70 1 1 537_splitncnn_0 904 0=64 1=1 5=1 6=8192
|
30 |
+
Swish Mul_72 1 1 904 545
|
31 |
+
Convolution Conv_73 1 1 541_splitncnn_1 907 0=64 1=1 5=1 6=4096
|
32 |
+
Swish Mul_75 1 1 907 549
|
33 |
+
Convolution Conv_76 1 1 549 910 0=64 1=3 4=1 5=1 6=36864
|
34 |
+
Swish Mul_78 1 1 910 553
|
35 |
+
BinaryOp Add_79 2 1 553 541_splitncnn_0 554
|
36 |
+
Split splitncnn_4 1 2 554 554_splitncnn_0 554_splitncnn_1
|
37 |
+
Convolution Conv_80 1 1 554_splitncnn_1 913 0=64 1=1 5=1 6=4096
|
38 |
+
Swish Mul_82 1 1 913 558
|
39 |
+
Convolution Conv_83 1 1 558 916 0=64 1=3 4=1 5=1 6=36864
|
40 |
+
Swish Mul_85 1 1 916 562
|
41 |
+
BinaryOp Add_86 2 1 562 554_splitncnn_0 563
|
42 |
+
Split splitncnn_5 1 2 563 563_splitncnn_0 563_splitncnn_1
|
43 |
+
Convolution Conv_87 1 1 563_splitncnn_1 919 0=64 1=1 5=1 6=4096
|
44 |
+
Swish Mul_89 1 1 919 567
|
45 |
+
Convolution Conv_90 1 1 567 922 0=64 1=3 4=1 5=1 6=36864
|
46 |
+
Swish Mul_92 1 1 922 571
|
47 |
+
BinaryOp Add_93 2 1 571 563_splitncnn_0 572
|
48 |
+
Concat Concat_94 2 1 572 545 573
|
49 |
+
Convolution Conv_95 1 1 573 925 0=128 1=1 5=1 6=16384
|
50 |
+
Swish Mul_97 1 1 925 577
|
51 |
+
Split splitncnn_6 1 2 577 577_splitncnn_0 577_splitncnn_1
|
52 |
+
Convolution Conv_98 1 1 577_splitncnn_1 928 0=256 1=3 3=2 4=1 5=1 6=294912
|
53 |
+
Swish Mul_100 1 1 928 581
|
54 |
+
Split splitncnn_7 1 2 581 581_splitncnn_0 581_splitncnn_1
|
55 |
+
Convolution Conv_101 1 1 581_splitncnn_1 931 0=128 1=1 5=1 6=32768
|
56 |
+
Swish Mul_103 1 1 931 585
|
57 |
+
Split splitncnn_8 1 2 585 585_splitncnn_0 585_splitncnn_1
|
58 |
+
Convolution Conv_104 1 1 581_splitncnn_0 934 0=128 1=1 5=1 6=32768
|
59 |
+
Swish Mul_106 1 1 934 589
|
60 |
+
Convolution Conv_107 1 1 585_splitncnn_1 937 0=128 1=1 5=1 6=16384
|
61 |
+
Swish Mul_109 1 1 937 593
|
62 |
+
Convolution Conv_110 1 1 593 940 0=128 1=3 4=1 5=1 6=147456
|
63 |
+
Swish Mul_112 1 1 940 597
|
64 |
+
BinaryOp Add_113 2 1 597 585_splitncnn_0 598
|
65 |
+
Split splitncnn_9 1 2 598 598_splitncnn_0 598_splitncnn_1
|
66 |
+
Convolution Conv_114 1 1 598_splitncnn_1 943 0=128 1=1 5=1 6=16384
|
67 |
+
Swish Mul_116 1 1 943 602
|
68 |
+
Convolution Conv_117 1 1 602 946 0=128 1=3 4=1 5=1 6=147456
|
69 |
+
Swish Mul_119 1 1 946 606
|
70 |
+
BinaryOp Add_120 2 1 606 598_splitncnn_0 607
|
71 |
+
Split splitncnn_10 1 2 607 607_splitncnn_0 607_splitncnn_1
|
72 |
+
Convolution Conv_121 1 1 607_splitncnn_1 949 0=128 1=1 5=1 6=16384
|
73 |
+
Swish Mul_123 1 1 949 611
|
74 |
+
Convolution Conv_124 1 1 611 952 0=128 1=3 4=1 5=1 6=147456
|
75 |
+
Swish Mul_126 1 1 952 615
|
76 |
+
BinaryOp Add_127 2 1 615 607_splitncnn_0 616
|
77 |
+
Concat Concat_128 2 1 616 589 617
|
78 |
+
Convolution Conv_129 1 1 617 955 0=256 1=1 5=1 6=65536
|
79 |
+
Swish Mul_131 1 1 955 621
|
80 |
+
Split splitncnn_11 1 2 621 621_splitncnn_0 621_splitncnn_1
|
81 |
+
Convolution Conv_132 1 1 621_splitncnn_1 958 0=512 1=3 3=2 4=1 5=1 6=1179648
|
82 |
+
Swish Mul_134 1 1 958 625
|
83 |
+
Convolution Conv_135 1 1 625 961 0=256 1=1 5=1 6=131072
|
84 |
+
Swish Mul_137 1 1 961 629
|
85 |
+
Split splitncnn_12 1 4 629 629_splitncnn_0 629_splitncnn_1 629_splitncnn_2 629_splitncnn_3
|
86 |
+
Pooling MaxPool_138 1 1 629_splitncnn_3 630 1=5 3=2 5=1
|
87 |
+
Pooling MaxPool_139 1 1 629_splitncnn_2 631 1=9 3=4 5=1
|
88 |
+
Pooling MaxPool_140 1 1 629_splitncnn_1 632 1=13 3=6 5=1
|
89 |
+
Concat Concat_141 4 1 629_splitncnn_0 630 631 632 633
|
90 |
+
Convolution Conv_142 1 1 633 964 0=512 1=1 5=1 6=524288
|
91 |
+
Swish Mul_144 1 1 964 637
|
92 |
+
Split splitncnn_13 1 2 637 637_splitncnn_0 637_splitncnn_1
|
93 |
+
Convolution Conv_145 1 1 637_splitncnn_1 967 0=256 1=1 5=1 6=131072
|
94 |
+
Swish Mul_147 1 1 967 641
|
95 |
+
Convolution Conv_148 1 1 637_splitncnn_0 970 0=256 1=1 5=1 6=131072
|
96 |
+
Swish Mul_150 1 1 970 645
|
97 |
+
Convolution Conv_151 1 1 641 973 0=256 1=1 5=1 6=65536
|
98 |
+
Swish Mul_153 1 1 973 649
|
99 |
+
Convolution Conv_154 1 1 649 976 0=256 1=3 4=1 5=1 6=589824
|
100 |
+
Swish Mul_156 1 1 976 653
|
101 |
+
Concat Concat_157 2 1 653 645 654
|
102 |
+
Convolution Conv_158 1 1 654 979 0=512 1=1 5=1 6=262144
|
103 |
+
Swish Mul_160 1 1 979 658
|
104 |
+
Convolution Conv_161 1 1 658 982 0=256 1=1 5=1 6=131072
|
105 |
+
Swish Mul_163 1 1 982 662
|
106 |
+
Split splitncnn_14 1 2 662 662_splitncnn_0 662_splitncnn_1
|
107 |
+
Interp Resize_165 1 1 662_splitncnn_1 667 0=1 1=2.000000e+00 2=2.000000e+00
|
108 |
+
Concat Concat_166 2 1 667 621_splitncnn_0 668
|
109 |
+
Split splitncnn_15 1 2 668 668_splitncnn_0 668_splitncnn_1
|
110 |
+
Convolution Conv_167 1 1 668_splitncnn_1 985 0=128 1=1 5=1 6=65536
|
111 |
+
Swish Mul_169 1 1 985 672
|
112 |
+
Convolution Conv_170 1 1 668_splitncnn_0 988 0=128 1=1 5=1 6=65536
|
113 |
+
Swish Mul_172 1 1 988 676
|
114 |
+
Convolution Conv_173 1 1 672 991 0=128 1=1 5=1 6=16384
|
115 |
+
Swish Mul_175 1 1 991 680
|
116 |
+
Convolution Conv_176 1 1 680 994 0=128 1=3 4=1 5=1 6=147456
|
117 |
+
Swish Mul_178 1 1 994 684
|
118 |
+
Concat Concat_179 2 1 684 676 685
|
119 |
+
Convolution Conv_180 1 1 685 997 0=256 1=1 5=1 6=65536
|
120 |
+
Swish Mul_182 1 1 997 689
|
121 |
+
Convolution Conv_183 1 1 689 1000 0=128 1=1 5=1 6=32768
|
122 |
+
Swish Mul_185 1 1 1000 693
|
123 |
+
Split splitncnn_16 1 2 693 693_splitncnn_0 693_splitncnn_1
|
124 |
+
Interp Resize_187 1 1 693_splitncnn_1 698 0=1 1=2.000000e+00 2=2.000000e+00
|
125 |
+
Concat Concat_188 2 1 698 577_splitncnn_0 699
|
126 |
+
Split splitncnn_17 1 2 699 699_splitncnn_0 699_splitncnn_1
|
127 |
+
Convolution Conv_189 1 1 699_splitncnn_1 1003 0=64 1=1 5=1 6=16384
|
128 |
+
Swish Mul_191 1 1 1003 703
|
129 |
+
Convolution Conv_192 1 1 699_splitncnn_0 1006 0=64 1=1 5=1 6=16384
|
130 |
+
Swish Mul_194 1 1 1006 707
|
131 |
+
Convolution Conv_195 1 1 703 1009 0=64 1=1 5=1 6=4096
|
132 |
+
Swish Mul_197 1 1 1009 711
|
133 |
+
Convolution Conv_198 1 1 711 1012 0=64 1=3 4=1 5=1 6=36864
|
134 |
+
Swish Mul_200 1 1 1012 715
|
135 |
+
Concat Concat_201 2 1 715 707 716
|
136 |
+
Convolution Conv_202 1 1 716 1015 0=128 1=1 5=1 6=16384
|
137 |
+
Swish Mul_204 1 1 1015 720
|
138 |
+
Split splitncnn_18 1 2 720 720_splitncnn_0 720_splitncnn_1
|
139 |
+
Convolution Conv_205 1 1 720_splitncnn_1 1018 0=128 1=3 3=2 4=1 5=1 6=147456
|
140 |
+
Swish Mul_207 1 1 1018 724
|
141 |
+
Concat Concat_208 2 1 724 693_splitncnn_0 725
|
142 |
+
Split splitncnn_19 1 2 725 725_splitncnn_0 725_splitncnn_1
|
143 |
+
Convolution Conv_209 1 1 725_splitncnn_1 1021 0=128 1=1 5=1 6=32768
|
144 |
+
Swish Mul_211 1 1 1021 729
|
145 |
+
Convolution Conv_212 1 1 725_splitncnn_0 1024 0=128 1=1 5=1 6=32768
|
146 |
+
Swish Mul_214 1 1 1024 733
|
147 |
+
Convolution Conv_215 1 1 729 1027 0=128 1=1 5=1 6=16384
|
148 |
+
Swish Mul_217 1 1 1027 737
|
149 |
+
Convolution Conv_218 1 1 737 1030 0=128 1=3 4=1 5=1 6=147456
|
150 |
+
Swish Mul_220 1 1 1030 741
|
151 |
+
Concat Concat_221 2 1 741 733 742
|
152 |
+
Convolution Conv_222 1 1 742 1033 0=256 1=1 5=1 6=65536
|
153 |
+
Swish Mul_224 1 1 1033 746
|
154 |
+
Split splitncnn_20 1 2 746 746_splitncnn_0 746_splitncnn_1
|
155 |
+
Convolution Conv_225 1 1 746_splitncnn_1 1036 0=256 1=3 3=2 4=1 5=1 6=589824
|
156 |
+
Swish Mul_227 1 1 1036 750
|
157 |
+
Concat Concat_228 2 1 750 662_splitncnn_0 751
|
158 |
+
Split splitncnn_21 1 2 751 751_splitncnn_0 751_splitncnn_1
|
159 |
+
Convolution Conv_229 1 1 751_splitncnn_1 1039 0=256 1=1 5=1 6=131072
|
160 |
+
Swish Mul_231 1 1 1039 755
|
161 |
+
Convolution Conv_232 1 1 751_splitncnn_0 1042 0=256 1=1 5=1 6=131072
|
162 |
+
Swish Mul_234 1 1 1042 759
|
163 |
+
Convolution Conv_235 1 1 755 1045 0=256 1=1 5=1 6=65536
|
164 |
+
Swish Mul_237 1 1 1045 763
|
165 |
+
Convolution Conv_238 1 1 763 1048 0=256 1=3 4=1 5=1 6=589824
|
166 |
+
Swish Mul_240 1 1 1048 767
|
167 |
+
Concat Concat_241 2 1 767 759 768
|
168 |
+
Convolution Conv_242 1 1 768 1051 0=512 1=1 5=1 6=262144
|
169 |
+
Swish Mul_244 1 1 1051 772
|
170 |
+
Convolution Conv_245 1 1 720_splitncnn_0 1054 0=128 1=1 5=1 6=16384
|
171 |
+
Swish Mul_247 1 1 1054 776
|
172 |
+
Split splitncnn_22 1 2 776 776_splitncnn_0 776_splitncnn_1
|
173 |
+
Convolution Conv_248 1 1 776_splitncnn_1 1057 0=128 1=3 4=1 5=1 6=147456
|
174 |
+
Swish Mul_250 1 1 1057 780
|
175 |
+
Convolution Conv_251 1 1 780 1060 0=128 1=3 4=1 5=1 6=147456
|
176 |
+
Swish Mul_253 1 1 1060 784
|
177 |
+
Convolution Conv_254 1 1 784 797 0=80 1=1 5=1 6=10240 9=4
|
178 |
+
Convolution Conv_255 1 1 776_splitncnn_0 1063 0=128 1=3 4=1 5=1 6=147456
|
179 |
+
Swish Mul_257 1 1 1063 789
|
180 |
+
Convolution Conv_258 1 1 789 1066 0=128 1=3 4=1 5=1 6=147456
|
181 |
+
Swish Mul_260 1 1 1066 793
|
182 |
+
Split splitncnn_23 1 2 793 793_splitncnn_0 793_splitncnn_1
|
183 |
+
Convolution Conv_261 1 1 793_splitncnn_1 794 0=4 1=1 5=1 6=512
|
184 |
+
Convolution Conv_262 1 1 793_splitncnn_0 796 0=1 1=1 5=1 6=128 9=4
|
185 |
+
Concat Concat_265 3 1 794 796 797 798
|
186 |
+
Convolution Conv_266 1 1 746_splitncnn_0 1069 0=128 1=1 5=1 6=32768
|
187 |
+
Swish Mul_268 1 1 1069 802
|
188 |
+
Split splitncnn_24 1 2 802 802_splitncnn_0 802_splitncnn_1
|
189 |
+
Convolution Conv_269 1 1 802_splitncnn_1 1072 0=128 1=3 4=1 5=1 6=147456
|
190 |
+
Swish Mul_271 1 1 1072 806
|
191 |
+
Convolution Conv_272 1 1 806 1075 0=128 1=3 4=1 5=1 6=147456
|
192 |
+
Swish Mul_274 1 1 1075 810
|
193 |
+
Convolution Conv_275 1 1 810 823 0=80 1=1 5=1 6=10240 9=4
|
194 |
+
Convolution Conv_276 1 1 802_splitncnn_0 1078 0=128 1=3 4=1 5=1 6=147456
|
195 |
+
Swish Mul_278 1 1 1078 815
|
196 |
+
Convolution Conv_279 1 1 815 1081 0=128 1=3 4=1 5=1 6=147456
|
197 |
+
Swish Mul_281 1 1 1081 819
|
198 |
+
Split splitncnn_25 1 2 819 819_splitncnn_0 819_splitncnn_1
|
199 |
+
Convolution Conv_282 1 1 819_splitncnn_1 820 0=4 1=1 5=1 6=512
|
200 |
+
Convolution Conv_283 1 1 819_splitncnn_0 822 0=1 1=1 5=1 6=128 9=4
|
201 |
+
Concat Concat_286 3 1 820 822 823 824
|
202 |
+
Convolution Conv_287 1 1 772 1084 0=128 1=1 5=1 6=65536
|
203 |
+
Swish Mul_289 1 1 1084 828
|
204 |
+
Split splitncnn_26 1 2 828 828_splitncnn_0 828_splitncnn_1
|
205 |
+
Convolution Conv_290 1 1 828_splitncnn_1 1087 0=128 1=3 4=1 5=1 6=147456
|
206 |
+
Swish Mul_292 1 1 1087 832
|
207 |
+
Convolution Conv_293 1 1 832 1090 0=128 1=3 4=1 5=1 6=147456
|
208 |
+
Swish Mul_295 1 1 1090 836
|
209 |
+
Convolution Conv_296 1 1 836 849 0=80 1=1 5=1 6=10240 9=4
|
210 |
+
Convolution Conv_297 1 1 828_splitncnn_0 1093 0=128 1=3 4=1 5=1 6=147456
|
211 |
+
Swish Mul_299 1 1 1093 841
|
212 |
+
Convolution Conv_300 1 1 841 1096 0=128 1=3 4=1 5=1 6=147456
|
213 |
+
Swish Mul_302 1 1 1096 845
|
214 |
+
Split splitncnn_27 1 2 845 845_splitncnn_0 845_splitncnn_1
|
215 |
+
Convolution Conv_303 1 1 845_splitncnn_1 846 0=4 1=1 5=1 6=512
|
216 |
+
Convolution Conv_304 1 1 845_splitncnn_0 848 0=1 1=1 5=1 6=128 9=4
|
217 |
+
Concat Concat_307 3 1 846 848 849 850
|
218 |
+
Reshape Reshape_315 1 1 798 858 0=-1 1=85
|
219 |
+
Reshape Reshape_323 1 1 824 866 0=-1 1=85
|
220 |
+
Reshape Reshape_331 1 1 850 874 0=-1 1=85
|
221 |
+
Concat Concat_332 3 1 858 866 874 875 0=1
|
222 |
+
Permute Transpose_333 1 1 875 output 0=1
|
demo/ncnn/android/app/src/main/java/com/megvii/yoloXncnn/MainActivity.java
ADDED
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Some code in this file is based on:
|
2 |
+
// https://github.com/nihui/ncnn-android-yolov5/blob/master/app/src/main/java/com/tencent/yolov5ncnn/MainActivity.java
|
3 |
+
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
4 |
+
// Copyright (C) Megvii, Inc. and its affiliates. All rights reserved.
|
5 |
+
|
6 |
+
package com.megvii.yoloXncnn;
|
7 |
+
|
8 |
+
import android.app.Activity;
|
9 |
+
import android.content.Intent;
|
10 |
+
import android.graphics.Bitmap;
|
11 |
+
import android.graphics.BitmapFactory;
|
12 |
+
import android.graphics.Canvas;
|
13 |
+
import android.graphics.Color;
|
14 |
+
import android.graphics.Paint;
|
15 |
+
import android.media.ExifInterface;
|
16 |
+
import android.graphics.Matrix;
|
17 |
+
import android.net.Uri;
|
18 |
+
import android.os.Bundle;
|
19 |
+
import android.util.Log;
|
20 |
+
import android.view.View;
|
21 |
+
import android.widget.Button;
|
22 |
+
import android.widget.ImageView;
|
23 |
+
|
24 |
+
import java.io.FileNotFoundException;
|
25 |
+
import java.io.InputStream;
|
26 |
+
import java.io.IOException;
|
27 |
+
|
28 |
+
public class MainActivity extends Activity
|
29 |
+
{
|
30 |
+
private static final int SELECT_IMAGE = 1;
|
31 |
+
|
32 |
+
private ImageView imageView;
|
33 |
+
private Bitmap bitmap = null;
|
34 |
+
private Bitmap yourSelectedImage = null;
|
35 |
+
|
36 |
+
private YOLOXncnn yoloX = new YOLOXncnn();
|
37 |
+
|
38 |
+
/** Called when the activity is first created. */
|
39 |
+
@Override
|
40 |
+
public void onCreate(Bundle savedInstanceState)
|
41 |
+
{
|
42 |
+
super.onCreate(savedInstanceState);
|
43 |
+
setContentView(R.layout.main);
|
44 |
+
|
45 |
+
boolean ret_init = yoloX.Init(getAssets());
|
46 |
+
if (!ret_init)
|
47 |
+
{
|
48 |
+
Log.e("MainActivity", "yoloXncnn Init failed");
|
49 |
+
}
|
50 |
+
|
51 |
+
imageView = (ImageView) findViewById(R.id.imageView);
|
52 |
+
|
53 |
+
Button buttonImage = (Button) findViewById(R.id.buttonImage);
|
54 |
+
buttonImage.setOnClickListener(new View.OnClickListener() {
|
55 |
+
@Override
|
56 |
+
public void onClick(View arg0) {
|
57 |
+
Intent i = new Intent(Intent.ACTION_PICK);
|
58 |
+
i.setType("image/*");
|
59 |
+
startActivityForResult(i, SELECT_IMAGE);
|
60 |
+
}
|
61 |
+
});
|
62 |
+
|
63 |
+
Button buttonDetect = (Button) findViewById(R.id.buttonDetect);
|
64 |
+
buttonDetect.setOnClickListener(new View.OnClickListener() {
|
65 |
+
@Override
|
66 |
+
public void onClick(View arg0) {
|
67 |
+
if (yourSelectedImage == null)
|
68 |
+
return;
|
69 |
+
YOLOXncnn.Obj[] objects = yoloX.Detect(yourSelectedImage, false);
|
70 |
+
|
71 |
+
showObjects(objects);
|
72 |
+
}
|
73 |
+
});
|
74 |
+
|
75 |
+
Button buttonDetectGPU = (Button) findViewById(R.id.buttonDetectGPU);
|
76 |
+
buttonDetectGPU.setOnClickListener(new View.OnClickListener() {
|
77 |
+
@Override
|
78 |
+
public void onClick(View arg0) {
|
79 |
+
if (yourSelectedImage == null)
|
80 |
+
return;
|
81 |
+
|
82 |
+
YOLOXncnn.Obj[] objects = yoloX.Detect(yourSelectedImage, true);
|
83 |
+
|
84 |
+
showObjects(objects);
|
85 |
+
}
|
86 |
+
});
|
87 |
+
}
|
88 |
+
|
89 |
+
private void showObjects(YOLOXncnn.Obj[] objects)
|
90 |
+
{
|
91 |
+
if (objects == null)
|
92 |
+
{
|
93 |
+
imageView.setImageBitmap(bitmap);
|
94 |
+
return;
|
95 |
+
}
|
96 |
+
|
97 |
+
// draw objects on bitmap
|
98 |
+
Bitmap rgba = bitmap.copy(Bitmap.Config.ARGB_8888, true);
|
99 |
+
|
100 |
+
final int[] colors = new int[] {
|
101 |
+
Color.rgb( 54, 67, 244),
|
102 |
+
Color.rgb( 99, 30, 233),
|
103 |
+
Color.rgb(176, 39, 156),
|
104 |
+
Color.rgb(183, 58, 103),
|
105 |
+
Color.rgb(181, 81, 63),
|
106 |
+
Color.rgb(243, 150, 33),
|
107 |
+
Color.rgb(244, 169, 3),
|
108 |
+
Color.rgb(212, 188, 0),
|
109 |
+
Color.rgb(136, 150, 0),
|
110 |
+
Color.rgb( 80, 175, 76),
|
111 |
+
Color.rgb( 74, 195, 139),
|
112 |
+
Color.rgb( 57, 220, 205),
|
113 |
+
Color.rgb( 59, 235, 255),
|
114 |
+
Color.rgb( 7, 193, 255),
|
115 |
+
Color.rgb( 0, 152, 255),
|
116 |
+
Color.rgb( 34, 87, 255),
|
117 |
+
Color.rgb( 72, 85, 121),
|
118 |
+
Color.rgb(158, 158, 158),
|
119 |
+
Color.rgb(139, 125, 96)
|
120 |
+
};
|
121 |
+
|
122 |
+
Canvas canvas = new Canvas(rgba);
|
123 |
+
|
124 |
+
Paint paint = new Paint();
|
125 |
+
paint.setStyle(Paint.Style.STROKE);
|
126 |
+
paint.setStrokeWidth(4);
|
127 |
+
|
128 |
+
Paint textbgpaint = new Paint();
|
129 |
+
textbgpaint.setColor(Color.WHITE);
|
130 |
+
textbgpaint.setStyle(Paint.Style.FILL);
|
131 |
+
|
132 |
+
Paint textpaint = new Paint();
|
133 |
+
textpaint.setColor(Color.BLACK);
|
134 |
+
textpaint.setTextSize(26);
|
135 |
+
textpaint.setTextAlign(Paint.Align.LEFT);
|
136 |
+
|
137 |
+
for (int i = 0; i < objects.length; i++)
|
138 |
+
{
|
139 |
+
paint.setColor(colors[i % 19]);
|
140 |
+
|
141 |
+
canvas.drawRect(objects[i].x, objects[i].y, objects[i].x + objects[i].w, objects[i].y + objects[i].h, paint);
|
142 |
+
|
143 |
+
// draw filled text inside image
|
144 |
+
{
|
145 |
+
String text = objects[i].label + " = " + String.format("%.1f", objects[i].prob * 100) + "%";
|
146 |
+
|
147 |
+
float text_width = textpaint.measureText(text);
|
148 |
+
float text_height = - textpaint.ascent() + textpaint.descent();
|
149 |
+
|
150 |
+
float x = objects[i].x;
|
151 |
+
float y = objects[i].y - text_height;
|
152 |
+
if (y < 0)
|
153 |
+
y = 0;
|
154 |
+
if (x + text_width > rgba.getWidth())
|
155 |
+
x = rgba.getWidth() - text_width;
|
156 |
+
|
157 |
+
canvas.drawRect(x, y, x + text_width, y + text_height, textbgpaint);
|
158 |
+
|
159 |
+
canvas.drawText(text, x, y - textpaint.ascent(), textpaint);
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
imageView.setImageBitmap(rgba);
|
164 |
+
}
|
165 |
+
|
166 |
+
@Override
|
167 |
+
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
168 |
+
{
|
169 |
+
super.onActivityResult(requestCode, resultCode, data);
|
170 |
+
|
171 |
+
if (resultCode == RESULT_OK && null != data) {
|
172 |
+
Uri selectedImage = data.getData();
|
173 |
+
|
174 |
+
try
|
175 |
+
{
|
176 |
+
if (requestCode == SELECT_IMAGE) {
|
177 |
+
bitmap = decodeUri(selectedImage);
|
178 |
+
|
179 |
+
yourSelectedImage = bitmap.copy(Bitmap.Config.ARGB_8888, true);
|
180 |
+
|
181 |
+
imageView.setImageBitmap(bitmap);
|
182 |
+
}
|
183 |
+
}
|
184 |
+
catch (FileNotFoundException e)
|
185 |
+
{
|
186 |
+
Log.e("MainActivity", "FileNotFoundException");
|
187 |
+
return;
|
188 |
+
}
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException
|
193 |
+
{
|
194 |
+
// Decode image size
|
195 |
+
BitmapFactory.Options o = new BitmapFactory.Options();
|
196 |
+
o.inJustDecodeBounds = true;
|
197 |
+
BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);
|
198 |
+
|
199 |
+
// The new size we want to scale to
|
200 |
+
final int REQUIRED_SIZE = 640;
|
201 |
+
|
202 |
+
// Find the correct scale value. It should be the power of 2.
|
203 |
+
int width_tmp = o.outWidth, height_tmp = o.outHeight;
|
204 |
+
int scale = 1;
|
205 |
+
while (true) {
|
206 |
+
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) {
|
207 |
+
break;
|
208 |
+
}
|
209 |
+
width_tmp /= 2;
|
210 |
+
height_tmp /= 2;
|
211 |
+
scale *= 2;
|
212 |
+
}
|
213 |
+
|
214 |
+
// Decode with inSampleSize
|
215 |
+
BitmapFactory.Options o2 = new BitmapFactory.Options();
|
216 |
+
o2.inSampleSize = scale;
|
217 |
+
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);
|
218 |
+
|
219 |
+
// Rotate according to EXIF
|
220 |
+
int rotate = 0;
|
221 |
+
try
|
222 |
+
{
|
223 |
+
ExifInterface exif = new ExifInterface(getContentResolver().openInputStream(selectedImage));
|
224 |
+
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
225 |
+
switch (orientation) {
|
226 |
+
case ExifInterface.ORIENTATION_ROTATE_270:
|
227 |
+
rotate = 270;
|
228 |
+
break;
|
229 |
+
case ExifInterface.ORIENTATION_ROTATE_180:
|
230 |
+
rotate = 180;
|
231 |
+
break;
|
232 |
+
case ExifInterface.ORIENTATION_ROTATE_90:
|
233 |
+
rotate = 90;
|
234 |
+
break;
|
235 |
+
}
|
236 |
+
}
|
237 |
+
catch (IOException e)
|
238 |
+
{
|
239 |
+
Log.e("MainActivity", "ExifInterface IOException");
|
240 |
+
}
|
241 |
+
|
242 |
+
Matrix matrix = new Matrix();
|
243 |
+
matrix.postRotate(rotate);
|
244 |
+
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
245 |
+
}
|
246 |
+
|
247 |
+
}
|
demo/ncnn/android/app/src/main/java/com/megvii/yoloXncnn/YOLOXncnn.java
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright (C) Megvii, Inc. and its affiliates. All rights reserved.
|
2 |
+
|
3 |
+
package com.megvii.yoloXncnn;
|
4 |
+
|
5 |
+
import android.content.res.AssetManager;
|
6 |
+
import android.graphics.Bitmap;
|
7 |
+
|
8 |
+
public class YOLOXncnn
|
9 |
+
{
|
10 |
+
public native boolean Init(AssetManager mgr);
|
11 |
+
|
12 |
+
public class Obj
|
13 |
+
{
|
14 |
+
public float x;
|
15 |
+
public float y;
|
16 |
+
public float w;
|
17 |
+
public float h;
|
18 |
+
public String label;
|
19 |
+
public float prob;
|
20 |
+
}
|
21 |
+
|
22 |
+
public native Obj[] Detect(Bitmap bitmap, boolean use_gpu);
|
23 |
+
|
24 |
+
static {
|
25 |
+
System.loadLibrary("yoloXncnn");
|
26 |
+
}
|
27 |
+
}
|
demo/ncnn/android/app/src/main/java/com/megvii/yoloXncnn/yoloXncnn.java
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright (C) Megvii, Inc. and its affiliates. All rights reserved.
|
2 |
+
|
3 |
+
package com.megvii.yoloXncnn;
|
4 |
+
|
5 |
+
import android.content.res.AssetManager;
|
6 |
+
import android.graphics.Bitmap;
|
7 |
+
|
8 |
+
public class YOLOXncnn
|
9 |
+
{
|
10 |
+
public native boolean Init(AssetManager mgr);
|
11 |
+
|
12 |
+
public class Obj
|
13 |
+
{
|
14 |
+
public float x;
|
15 |
+
public float y;
|
16 |
+
public float w;
|
17 |
+
public float h;
|
18 |
+
public String label;
|
19 |
+
public float prob;
|
20 |
+
}
|
21 |
+
|
22 |
+
public native Obj[] Detect(Bitmap bitmap, boolean use_gpu);
|
23 |
+
|
24 |
+
static {
|
25 |
+
System.loadLibrary("yoloXncnn");
|
26 |
+
}
|
27 |
+
}
|
demo/ncnn/android/app/src/main/jni/CMakeLists.txt
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
project(yoloXncnn)
|
2 |
+
|
3 |
+
cmake_minimum_required(VERSION 3.4.1)
|
4 |
+
|
5 |
+
set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn-20210525-android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn)
|
6 |
+
find_package(ncnn REQUIRED)
|
7 |
+
|
8 |
+
add_library(yoloXncnn SHARED yoloXncnn_jni.cpp)
|
9 |
+
|
10 |
+
target_link_libraries(yoloXncnn
|
11 |
+
ncnn
|
12 |
+
|
13 |
+
jnigraphics
|
14 |
+
)
|
demo/ncnn/android/app/src/main/jni/yoloXncnn_jni.cpp
ADDED
@@ -0,0 +1,480 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Some code in this file is based on:
|
2 |
+
// https://github.com/nihui/ncnn-android-yolov5/blob/master/app/src/main/jni/yolov5ncnn_jni.cpp
|
3 |
+
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
4 |
+
// Copyright (C) Megvii, Inc. and its affiliates. All rights reserved.
|
5 |
+
|
6 |
+
#include <android/asset_manager_jni.h>
|
7 |
+
#include <android/bitmap.h>
|
8 |
+
#include <android/log.h>
|
9 |
+
|
10 |
+
#include <jni.h>
|
11 |
+
|
12 |
+
#include <string>
|
13 |
+
#include <vector>
|
14 |
+
|
15 |
+
// ncnn
|
16 |
+
#include "layer.h"
|
17 |
+
#include "net.h"
|
18 |
+
#include "benchmark.h"
|
19 |
+
|
20 |
+
static ncnn::UnlockedPoolAllocator g_blob_pool_allocator;
|
21 |
+
static ncnn::PoolAllocator g_workspace_pool_allocator;
|
22 |
+
|
23 |
+
static ncnn::Net yoloX;
|
24 |
+
|
25 |
+
class YoloV5Focus : public ncnn::Layer
|
26 |
+
{
|
27 |
+
public:
|
28 |
+
YoloV5Focus()
|
29 |
+
{
|
30 |
+
one_blob_only = true;
|
31 |
+
}
|
32 |
+
|
33 |
+
virtual int forward(const ncnn::Mat& bottom_blob, ncnn::Mat& top_blob, const ncnn::Option& opt) const
|
34 |
+
{
|
35 |
+
int w = bottom_blob.w;
|
36 |
+
int h = bottom_blob.h;
|
37 |
+
int channels = bottom_blob.c;
|
38 |
+
|
39 |
+
int outw = w / 2;
|
40 |
+
int outh = h / 2;
|
41 |
+
int outc = channels * 4;
|
42 |
+
|
43 |
+
top_blob.create(outw, outh, outc, 4u, 1, opt.blob_allocator);
|
44 |
+
if (top_blob.empty())
|
45 |
+
return -100;
|
46 |
+
|
47 |
+
#pragma omp parallel for num_threads(opt.num_threads)
|
48 |
+
for (int p = 0; p < outc; p++)
|
49 |
+
{
|
50 |
+
const float* ptr = bottom_blob.channel(p % channels).row((p / channels) % 2) + ((p / channels) / 2);
|
51 |
+
float* outptr = top_blob.channel(p);
|
52 |
+
|
53 |
+
for (int i = 0; i < outh; i++)
|
54 |
+
{
|
55 |
+
for (int j = 0; j < outw; j++)
|
56 |
+
{
|
57 |
+
*outptr = *ptr;
|
58 |
+
|
59 |
+
outptr += 1;
|
60 |
+
ptr += 2;
|
61 |
+
}
|
62 |
+
|
63 |
+
ptr += w;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
return 0;
|
68 |
+
}
|
69 |
+
};
|
70 |
+
|
71 |
+
DEFINE_LAYER_CREATOR(YoloV5Focus)
|
72 |
+
|
73 |
+
struct Object
|
74 |
+
{
|
75 |
+
float x;
|
76 |
+
float y;
|
77 |
+
float w;
|
78 |
+
float h;
|
79 |
+
int label;
|
80 |
+
float prob;
|
81 |
+
};
|
82 |
+
|
83 |
+
struct GridAndStride
|
84 |
+
{
|
85 |
+
int grid0;
|
86 |
+
int grid1;
|
87 |
+
int stride;
|
88 |
+
};
|
89 |
+
|
90 |
+
static inline float intersection_area(const Object& a, const Object& b)
|
91 |
+
{
|
92 |
+
if (a.x > b.x + b.w || a.x + a.w < b.x || a.y > b.y + b.h || a.y + a.h < b.y)
|
93 |
+
{
|
94 |
+
// no intersection
|
95 |
+
return 0.f;
|
96 |
+
}
|
97 |
+
|
98 |
+
float inter_width = std::min(a.x + a.w, b.x + b.w) - std::max(a.x, b.x);
|
99 |
+
float inter_height = std::min(a.y + a.h, b.y + b.h) - std::max(a.y, b.y);
|
100 |
+
|
101 |
+
return inter_width * inter_height;
|
102 |
+
}
|
103 |
+
|
104 |
+
static void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right)
|
105 |
+
{
|
106 |
+
int i = left;
|
107 |
+
int j = right;
|
108 |
+
float p = faceobjects[(left + right) / 2].prob;
|
109 |
+
|
110 |
+
while (i <= j)
|
111 |
+
{
|
112 |
+
while (faceobjects[i].prob > p)
|
113 |
+
i++;
|
114 |
+
|
115 |
+
while (faceobjects[j].prob < p)
|
116 |
+
j--;
|
117 |
+
|
118 |
+
if (i <= j)
|
119 |
+
{
|
120 |
+
// swap
|
121 |
+
std::swap(faceobjects[i], faceobjects[j]);
|
122 |
+
|
123 |
+
i++;
|
124 |
+
j--;
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
#pragma omp parallel sections
|
129 |
+
{
|
130 |
+
#pragma omp section
|
131 |
+
{
|
132 |
+
if (left < j) qsort_descent_inplace(faceobjects, left, j);
|
133 |
+
}
|
134 |
+
#pragma omp section
|
135 |
+
{
|
136 |
+
if (i < right) qsort_descent_inplace(faceobjects, i, right);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
static void qsort_descent_inplace(std::vector<Object>& faceobjects)
|
142 |
+
{
|
143 |
+
if (faceobjects.empty())
|
144 |
+
return;
|
145 |
+
|
146 |
+
qsort_descent_inplace(faceobjects, 0, faceobjects.size() - 1);
|
147 |
+
}
|
148 |
+
|
149 |
+
static void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked, float nms_threshold)
|
150 |
+
{
|
151 |
+
picked.clear();
|
152 |
+
|
153 |
+
const int n = faceobjects.size();
|
154 |
+
|
155 |
+
std::vector<float> areas(n);
|
156 |
+
for (int i = 0; i < n; i++)
|
157 |
+
{
|
158 |
+
areas[i] = faceobjects[i].w * faceobjects[i].h;
|
159 |
+
}
|
160 |
+
|
161 |
+
for (int i = 0; i < n; i++)
|
162 |
+
{
|
163 |
+
const Object& a = faceobjects[i];
|
164 |
+
|
165 |
+
int keep = 1;
|
166 |
+
for (int j = 0; j < (int)picked.size(); j++)
|
167 |
+
{
|
168 |
+
const Object& b = faceobjects[picked[j]];
|
169 |
+
|
170 |
+
// intersection over union
|
171 |
+
float inter_area = intersection_area(a, b);
|
172 |
+
float union_area = areas[i] + areas[picked[j]] - inter_area;
|
173 |
+
// float IoU = inter_area / union_area
|
174 |
+
if (inter_area / union_area > nms_threshold)
|
175 |
+
keep = 0;
|
176 |
+
}
|
177 |
+
|
178 |
+
if (keep)
|
179 |
+
picked.push_back(i);
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
static void generate_grids_and_stride(const int target_size, std::vector<int>& strides, std::vector<GridAndStride>& grid_strides)
|
184 |
+
{
|
185 |
+
for (auto stride : strides)
|
186 |
+
{
|
187 |
+
int num_grid = target_size / stride;
|
188 |
+
for (int g1 = 0; g1 < num_grid; g1++)
|
189 |
+
{
|
190 |
+
for (int g0 = 0; g0 < num_grid; g0++)
|
191 |
+
{
|
192 |
+
grid_strides.push_back((GridAndStride){g0, g1, stride});
|
193 |
+
}
|
194 |
+
}
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
static void generate_yolox_proposals(std::vector<GridAndStride> grid_strides, const ncnn::Mat& feat_blob, float prob_threshold, std::vector<Object>& objects)
|
199 |
+
{
|
200 |
+
const int num_grid = feat_blob.h;
|
201 |
+
fprintf(stderr, "output height: %d, width: %d, channels: %d, dims:%d\n", feat_blob.h, feat_blob.w, feat_blob.c, feat_blob.dims);
|
202 |
+
|
203 |
+
const int num_class = feat_blob.w - 5;
|
204 |
+
|
205 |
+
const int num_anchors = grid_strides.size();
|
206 |
+
|
207 |
+
const float* feat_ptr = feat_blob.channel(0);
|
208 |
+
for (int anchor_idx = 0; anchor_idx < num_anchors; anchor_idx++)
|
209 |
+
{
|
210 |
+
const int grid0 = grid_strides[anchor_idx].grid0;
|
211 |
+
const int grid1 = grid_strides[anchor_idx].grid1;
|
212 |
+
const int stride = grid_strides[anchor_idx].stride;
|
213 |
+
|
214 |
+
// yolox/models/yolo_head.py decode logic
|
215 |
+
// outputs[..., :2] = (outputs[..., :2] + grids) * strides
|
216 |
+
// outputs[..., 2:4] = torch.exp(outputs[..., 2:4]) * strides
|
217 |
+
float x_center = (feat_ptr[0] + grid0) * stride;
|
218 |
+
float y_center = (feat_ptr[1] + grid1) * stride;
|
219 |
+
float w = exp(feat_ptr[2]) * stride;
|
220 |
+
float h = exp(feat_ptr[3]) * stride;
|
221 |
+
float x0 = x_center - w * 0.5f;
|
222 |
+
float y0 = y_center - h * 0.5f;
|
223 |
+
|
224 |
+
float box_objectness = feat_ptr[4];
|
225 |
+
for (int class_idx = 0; class_idx < num_class; class_idx++)
|
226 |
+
{
|
227 |
+
float box_cls_score = feat_ptr[5 + class_idx];
|
228 |
+
float box_prob = box_objectness * box_cls_score;
|
229 |
+
if (box_prob > prob_threshold)
|
230 |
+
{
|
231 |
+
Object obj;
|
232 |
+
obj.x = x0;
|
233 |
+
obj.y = y0;
|
234 |
+
obj.w = w;
|
235 |
+
obj.h = h;
|
236 |
+
obj.label = class_idx;
|
237 |
+
obj.prob = box_prob;
|
238 |
+
|
239 |
+
objects.push_back(obj);
|
240 |
+
}
|
241 |
+
|
242 |
+
} // class loop
|
243 |
+
feat_ptr += feat_blob.w;
|
244 |
+
|
245 |
+
} // point anchor loop
|
246 |
+
}
|
247 |
+
|
248 |
+
|
249 |
+
extern "C" {
|
250 |
+
|
251 |
+
// FIXME DeleteGlobalRef is missing for objCls
|
252 |
+
static jclass objCls = NULL;
|
253 |
+
static jmethodID constructortorId;
|
254 |
+
static jfieldID xId;
|
255 |
+
static jfieldID yId;
|
256 |
+
static jfieldID wId;
|
257 |
+
static jfieldID hId;
|
258 |
+
static jfieldID labelId;
|
259 |
+
static jfieldID probId;
|
260 |
+
|
261 |
+
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
262 |
+
{
|
263 |
+
__android_log_print(ANDROID_LOG_DEBUG, "YOLOXncnn", "JNI_OnLoad");
|
264 |
+
|
265 |
+
ncnn::create_gpu_instance();
|
266 |
+
|
267 |
+
return JNI_VERSION_1_4;
|
268 |
+
}
|
269 |
+
|
270 |
+
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
|
271 |
+
{
|
272 |
+
__android_log_print(ANDROID_LOG_DEBUG, "YOLOXncnn", "JNI_OnUnload");
|
273 |
+
|
274 |
+
ncnn::destroy_gpu_instance();
|
275 |
+
}
|
276 |
+
|
277 |
+
// public native boolean Init(AssetManager mgr);
|
278 |
+
JNIEXPORT jboolean JNICALL Java_com_megvii_yoloXncnn_YOLOXncnn_Init(JNIEnv* env, jobject thiz, jobject assetManager)
|
279 |
+
{
|
280 |
+
ncnn::Option opt;
|
281 |
+
opt.lightmode = true;
|
282 |
+
opt.num_threads = 4;
|
283 |
+
opt.blob_allocator = &g_blob_pool_allocator;
|
284 |
+
opt.workspace_allocator = &g_workspace_pool_allocator;
|
285 |
+
opt.use_packing_layout = true;
|
286 |
+
|
287 |
+
// use vulkan compute
|
288 |
+
if (ncnn::get_gpu_count() != 0)
|
289 |
+
opt.use_vulkan_compute = true;
|
290 |
+
|
291 |
+
AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
|
292 |
+
|
293 |
+
yoloX.opt = opt;
|
294 |
+
|
295 |
+
yoloX.register_custom_layer("YoloV5Focus", YoloV5Focus_layer_creator);
|
296 |
+
|
297 |
+
// init param
|
298 |
+
{
|
299 |
+
int ret = yoloX.load_param(mgr, "yolox.param");
|
300 |
+
if (ret != 0)
|
301 |
+
{
|
302 |
+
__android_log_print(ANDROID_LOG_DEBUG, "YOLOXncnn", "load_param failed");
|
303 |
+
return JNI_FALSE;
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
// init bin
|
308 |
+
{
|
309 |
+
int ret = yoloX.load_model(mgr, "yolox.bin");
|
310 |
+
if (ret != 0)
|
311 |
+
{
|
312 |
+
__android_log_print(ANDROID_LOG_DEBUG, "YOLOXncnn", "load_model failed");
|
313 |
+
return JNI_FALSE;
|
314 |
+
}
|
315 |
+
}
|
316 |
+
|
317 |
+
// init jni glue
|
318 |
+
jclass localObjCls = env->FindClass("com/megvii/yoloXncnn/YOLOXncnn$Obj");
|
319 |
+
objCls = reinterpret_cast<jclass>(env->NewGlobalRef(localObjCls));
|
320 |
+
|
321 |
+
constructortorId = env->GetMethodID(objCls, "<init>", "(Lcom/megvii/yoloXncnn/YOLOXncnn;)V");
|
322 |
+
|
323 |
+
xId = env->GetFieldID(objCls, "x", "F");
|
324 |
+
yId = env->GetFieldID(objCls, "y", "F");
|
325 |
+
wId = env->GetFieldID(objCls, "w", "F");
|
326 |
+
hId = env->GetFieldID(objCls, "h", "F");
|
327 |
+
labelId = env->GetFieldID(objCls, "label", "Ljava/lang/String;");
|
328 |
+
probId = env->GetFieldID(objCls, "prob", "F");
|
329 |
+
|
330 |
+
return JNI_TRUE;
|
331 |
+
}
|
332 |
+
|
333 |
+
// public native Obj[] Detect(Bitmap bitmap, boolean use_gpu);
|
334 |
+
JNIEXPORT jobjectArray JNICALL Java_com_megvii_yoloXncnn_YOLOXncnn_Detect(JNIEnv* env, jobject thiz, jobject bitmap, jboolean use_gpu)
|
335 |
+
{
|
336 |
+
if (use_gpu == JNI_TRUE && ncnn::get_gpu_count() == 0)
|
337 |
+
{
|
338 |
+
return NULL;
|
339 |
+
//return env->NewStringUTF("no vulkan capable gpu");
|
340 |
+
}
|
341 |
+
|
342 |
+
double start_time = ncnn::get_current_time();
|
343 |
+
|
344 |
+
AndroidBitmapInfo info;
|
345 |
+
AndroidBitmap_getInfo(env, bitmap, &info);
|
346 |
+
const int width = info.width;
|
347 |
+
const int height = info.height;
|
348 |
+
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
|
349 |
+
return NULL;
|
350 |
+
|
351 |
+
// parameters which might change for different model
|
352 |
+
const int target_size = 640;
|
353 |
+
const float prob_threshold = 0.3f;
|
354 |
+
const float nms_threshold = 0.65f;
|
355 |
+
std::vector<int> strides = {8, 16, 32}; // might have stride=64
|
356 |
+
// python 0-1 input tensor with rgb_means = (0.485, 0.456, 0.406), std = (0.229, 0.224, 0.225)
|
357 |
+
// so for 0-255 input image, rgb_mean should multiply 255 and norm should div by std.
|
358 |
+
const float mean_vals[3] = {255.f * 0.485f, 255.f * 0.456, 255.f * 0.406f};
|
359 |
+
const float norm_vals[3] = {1 / (255.f * 0.229f), 1 / (255.f * 0.224f), 1 / (255.f * 0.225f)};
|
360 |
+
|
361 |
+
int w = width;
|
362 |
+
int h = height;
|
363 |
+
float scale = 1.f;
|
364 |
+
if (w > h)
|
365 |
+
{
|
366 |
+
scale = (float)target_size / w;
|
367 |
+
w = target_size;
|
368 |
+
h = h * scale;
|
369 |
+
}
|
370 |
+
else
|
371 |
+
{
|
372 |
+
scale = (float)target_size / h;
|
373 |
+
h = target_size;
|
374 |
+
w = w * scale;
|
375 |
+
}
|
376 |
+
|
377 |
+
ncnn::Mat in = ncnn::Mat::from_android_bitmap_resize(env, bitmap, ncnn::Mat::PIXEL_RGB, w, h);
|
378 |
+
|
379 |
+
// pad to target_size rectangle
|
380 |
+
int wpad = target_size - w;
|
381 |
+
int hpad = target_size - h;
|
382 |
+
ncnn::Mat in_pad;
|
383 |
+
// different from yolov5, yolox only pad on bottom and right side,
|
384 |
+
// which means users don't need to extra padding info to decode boxes coordinate.
|
385 |
+
ncnn::copy_make_border(in, in_pad, 0, hpad, 0, wpad, ncnn::BORDER_CONSTANT, 114.f);
|
386 |
+
|
387 |
+
// yolox
|
388 |
+
std::vector<Object> objects;
|
389 |
+
{
|
390 |
+
|
391 |
+
in_pad.substract_mean_normalize(mean_vals, norm_vals);
|
392 |
+
|
393 |
+
ncnn::Extractor ex = yoloX.create_extractor();
|
394 |
+
|
395 |
+
ex.set_vulkan_compute(use_gpu);
|
396 |
+
|
397 |
+
ex.input("images", in_pad);
|
398 |
+
|
399 |
+
std::vector<Object> proposals;
|
400 |
+
|
401 |
+
// yolox decode and generate proposal logic
|
402 |
+
{
|
403 |
+
ncnn::Mat out;
|
404 |
+
ex.extract("output", out);
|
405 |
+
|
406 |
+
std::vector<GridAndStride> grid_strides;
|
407 |
+
generate_grids_and_stride(target_size, strides, grid_strides);
|
408 |
+
generate_yolox_proposals(grid_strides, out, prob_threshold, proposals);
|
409 |
+
|
410 |
+
}
|
411 |
+
|
412 |
+
// sort all proposals by score from highest to lowest
|
413 |
+
qsort_descent_inplace(proposals);
|
414 |
+
|
415 |
+
// apply nms with nms_threshold
|
416 |
+
std::vector<int> picked;
|
417 |
+
nms_sorted_bboxes(proposals, picked, nms_threshold);
|
418 |
+
|
419 |
+
int count = picked.size();
|
420 |
+
|
421 |
+
objects.resize(count);
|
422 |
+
for (int i = 0; i < count; i++)
|
423 |
+
{
|
424 |
+
objects[i] = proposals[picked[i]];
|
425 |
+
|
426 |
+
// adjust offset to original unpadded
|
427 |
+
float x0 = (objects[i].x) / scale;
|
428 |
+
float y0 = (objects[i].y) / scale;
|
429 |
+
float x1 = (objects[i].x + objects[i].w) / scale;
|
430 |
+
float y1 = (objects[i].y + objects[i].h) / scale;
|
431 |
+
|
432 |
+
// clip
|
433 |
+
x0 = std::max(std::min(x0, (float)(width - 1)), 0.f);
|
434 |
+
y0 = std::max(std::min(y0, (float)(height - 1)), 0.f);
|
435 |
+
x1 = std::max(std::min(x1, (float)(width - 1)), 0.f);
|
436 |
+
y1 = std::max(std::min(y1, (float)(height - 1)), 0.f);
|
437 |
+
|
438 |
+
objects[i].x = x0;
|
439 |
+
objects[i].y = y0;
|
440 |
+
objects[i].w = x1 - x0;
|
441 |
+
objects[i].h = y1 - y0;
|
442 |
+
}
|
443 |
+
}
|
444 |
+
|
445 |
+
// objects to Obj[]
|
446 |
+
static const char* class_names[] = {
|
447 |
+
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
|
448 |
+
"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
|
449 |
+
"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
|
450 |
+
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
|
451 |
+
"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
|
452 |
+
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
|
453 |
+
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
|
454 |
+
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
|
455 |
+
"hair drier", "toothbrush"
|
456 |
+
};
|
457 |
+
|
458 |
+
jobjectArray jObjArray = env->NewObjectArray(objects.size(), objCls, NULL);
|
459 |
+
|
460 |
+
for (size_t i=0; i<objects.size(); i++)
|
461 |
+
{
|
462 |
+
jobject jObj = env->NewObject(objCls, constructortorId, thiz);
|
463 |
+
|
464 |
+
env->SetFloatField(jObj, xId, objects[i].x);
|
465 |
+
env->SetFloatField(jObj, yId, objects[i].y);
|
466 |
+
env->SetFloatField(jObj, wId, objects[i].w);
|
467 |
+
env->SetFloatField(jObj, hId, objects[i].h);
|
468 |
+
env->SetObjectField(jObj, labelId, env->NewStringUTF(class_names[objects[i].label]));
|
469 |
+
env->SetFloatField(jObj, probId, objects[i].prob);
|
470 |
+
|
471 |
+
env->SetObjectArrayElement(jObjArray, i, jObj);
|
472 |
+
}
|
473 |
+
|
474 |
+
double elasped = ncnn::get_current_time() - start_time;
|
475 |
+
__android_log_print(ANDROID_LOG_DEBUG, "YOLOXncnn", "%.2fms detect", elasped);
|
476 |
+
|
477 |
+
return jObjArray;
|
478 |
+
}
|
479 |
+
|
480 |
+
}
|
demo/ncnn/android/app/src/main/res/layout/main.xml
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
3 |
+
android:orientation="vertical"
|
4 |
+
android:layout_width="fill_parent"
|
5 |
+
android:layout_height="fill_parent">
|
6 |
+
|
7 |
+
<LinearLayout
|
8 |
+
android:orientation="horizontal"
|
9 |
+
android:layout_width="fill_parent"
|
10 |
+
android:layout_height="wrap_content">
|
11 |
+
|
12 |
+
<Button
|
13 |
+
android:id="@+id/buttonImage"
|
14 |
+
android:layout_width="wrap_content"
|
15 |
+
android:layout_height="wrap_content"
|
16 |
+
android:text="image" />
|
17 |
+
<Button
|
18 |
+
android:id="@+id/buttonDetect"
|
19 |
+
android:layout_width="wrap_content"
|
20 |
+
android:layout_height="wrap_content"
|
21 |
+
android:text="infer-cpu" />
|
22 |
+
<Button
|
23 |
+
android:id="@+id/buttonDetectGPU"
|
24 |
+
android:layout_width="wrap_content"
|
25 |
+
android:layout_height="wrap_content"
|
26 |
+
android:text="infer-gpu" />
|
27 |
+
</LinearLayout>
|
28 |
+
|
29 |
+
<ImageView
|
30 |
+
android:id="@+id/imageView"
|
31 |
+
android:layout_width="fill_parent"
|
32 |
+
android:layout_height="fill_parent"
|
33 |
+
android:layout_weight="1" />
|
34 |
+
|
35 |
+
</LinearLayout>
|
demo/ncnn/android/app/src/main/res/values/strings.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<resources>
|
3 |
+
<string name="app_name">yoloXncnn</string>
|
4 |
+
</resources>
|
demo/ncnn/android/build.gradle
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
2 |
+
buildscript {
|
3 |
+
repositories {
|
4 |
+
jcenter()
|
5 |
+
google()
|
6 |
+
}
|
7 |
+
dependencies {
|
8 |
+
classpath 'com.android.tools.build:gradle:3.5.0'
|
9 |
+
}
|
10 |
+
}
|
11 |
+
|
12 |
+
allprojects {
|
13 |
+
repositories {
|
14 |
+
jcenter()
|
15 |
+
google()
|
16 |
+
}
|
17 |
+
}
|
demo/ncnn/android/gradle/wrapper/gradle-wrapper.jar
ADDED
Binary file (54.3 kB). View file
|
|
demo/ncnn/android/gradle/wrapper/gradle-wrapper.properties
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#Sun Aug 25 10:34:48 CST 2019
|
2 |
+
distributionBase=GRADLE_USER_HOME
|
3 |
+
distributionPath=wrapper/dists
|
4 |
+
zipStoreBase=GRADLE_USER_HOME
|
5 |
+
zipStorePath=wrapper/dists
|
6 |
+
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
demo/ncnn/android/gradlew
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env sh
|
2 |
+
|
3 |
+
##############################################################################
|
4 |
+
##
|
5 |
+
## Gradle start up script for UN*X
|
6 |
+
##
|
7 |
+
##############################################################################
|
8 |
+
|
9 |
+
# Attempt to set APP_HOME
|
10 |
+
# Resolve links: $0 may be a link
|
11 |
+
PRG="$0"
|
12 |
+
# Need this for relative symlinks.
|
13 |
+
while [ -h "$PRG" ] ; do
|
14 |
+
ls=`ls -ld "$PRG"`
|
15 |
+
link=`expr "$ls" : '.*-> \(.*\)$'`
|
16 |
+
if expr "$link" : '/.*' > /dev/null; then
|
17 |
+
PRG="$link"
|
18 |
+
else
|
19 |
+
PRG=`dirname "$PRG"`"/$link"
|
20 |
+
fi
|
21 |
+
done
|
22 |
+
SAVED="`pwd`"
|
23 |
+
cd "`dirname \"$PRG\"`/" >/dev/null
|
24 |
+
APP_HOME="`pwd -P`"
|
25 |
+
cd "$SAVED" >/dev/null
|
26 |
+
|
27 |
+
APP_NAME="Gradle"
|
28 |
+
APP_BASE_NAME=`basename "$0"`
|
29 |
+
|
30 |
+
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
31 |
+
DEFAULT_JVM_OPTS=""
|
32 |
+
|
33 |
+
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
34 |
+
MAX_FD="maximum"
|
35 |
+
|
36 |
+
warn () {
|
37 |
+
echo "$*"
|
38 |
+
}
|
39 |
+
|
40 |
+
die () {
|
41 |
+
echo
|
42 |
+
echo "$*"
|
43 |
+
echo
|
44 |
+
exit 1
|
45 |
+
}
|
46 |
+
|
47 |
+
# OS specific support (must be 'true' or 'false').
|
48 |
+
cygwin=false
|
49 |
+
msys=false
|
50 |
+
darwin=false
|
51 |
+
nonstop=false
|
52 |
+
case "`uname`" in
|
53 |
+
CYGWIN* )
|
54 |
+
cygwin=true
|
55 |
+
;;
|
56 |
+
Darwin* )
|
57 |
+
darwin=true
|
58 |
+
;;
|
59 |
+
MINGW* )
|
60 |
+
msys=true
|
61 |
+
;;
|
62 |
+
NONSTOP* )
|
63 |
+
nonstop=true
|
64 |
+
;;
|
65 |
+
esac
|
66 |
+
|
67 |
+
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
68 |
+
|
69 |
+
# Determine the Java command to use to start the JVM.
|
70 |
+
if [ -n "$JAVA_HOME" ] ; then
|
71 |
+
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
72 |
+
# IBM's JDK on AIX uses strange locations for the executables
|
73 |
+
JAVACMD="$JAVA_HOME/jre/sh/java"
|
74 |
+
else
|
75 |
+
JAVACMD="$JAVA_HOME/bin/java"
|
76 |
+
fi
|
77 |
+
if [ ! -x "$JAVACMD" ] ; then
|
78 |
+
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
79 |
+
|
80 |
+
Please set the JAVA_HOME variable in your environment to match the
|
81 |
+
location of your Java installation."
|
82 |
+
fi
|
83 |
+
else
|
84 |
+
JAVACMD="java"
|
85 |
+
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
86 |
+
|
87 |
+
Please set the JAVA_HOME variable in your environment to match the
|
88 |
+
location of your Java installation."
|
89 |
+
fi
|
90 |
+
|
91 |
+
# Increase the maximum file descriptors if we can.
|
92 |
+
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
93 |
+
MAX_FD_LIMIT=`ulimit -H -n`
|
94 |
+
if [ $? -eq 0 ] ; then
|
95 |
+
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
96 |
+
MAX_FD="$MAX_FD_LIMIT"
|
97 |
+
fi
|
98 |
+
ulimit -n $MAX_FD
|
99 |
+
if [ $? -ne 0 ] ; then
|
100 |
+
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
101 |
+
fi
|
102 |
+
else
|
103 |
+
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
104 |
+
fi
|
105 |
+
fi
|
106 |
+
|
107 |
+
# For Darwin, add options to specify how the application appears in the dock
|
108 |
+
if $darwin; then
|
109 |
+
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
110 |
+
fi
|
111 |
+
|
112 |
+
# For Cygwin, switch paths to Windows format before running java
|
113 |
+
if $cygwin ; then
|
114 |
+
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
115 |
+
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
116 |
+
JAVACMD=`cygpath --unix "$JAVACMD"`
|
117 |
+
|
118 |
+
# We build the pattern for arguments to be converted via cygpath
|
119 |
+
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
120 |
+
SEP=""
|
121 |
+
for dir in $ROOTDIRSRAW ; do
|
122 |
+
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
123 |
+
SEP="|"
|
124 |
+
done
|
125 |
+
OURCYGPATTERN="(^($ROOTDIRS))"
|
126 |
+
# Add a user-defined pattern to the cygpath arguments
|
127 |
+
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
128 |
+
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
129 |
+
fi
|
130 |
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
131 |
+
i=0
|
132 |
+
for arg in "$@" ; do
|
133 |
+
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
134 |
+
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
135 |
+
|
136 |
+
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
137 |
+
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
138 |
+
else
|
139 |
+
eval `echo args$i`="\"$arg\""
|
140 |
+
fi
|
141 |
+
i=$((i+1))
|
142 |
+
done
|
143 |
+
case $i in
|
144 |
+
(0) set -- ;;
|
145 |
+
(1) set -- "$args0" ;;
|
146 |
+
(2) set -- "$args0" "$args1" ;;
|
147 |
+
(3) set -- "$args0" "$args1" "$args2" ;;
|
148 |
+
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
149 |
+
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
150 |
+
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
151 |
+
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
152 |
+
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
153 |
+
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
154 |
+
esac
|
155 |
+
fi
|
156 |
+
|
157 |
+
# Escape application args
|
158 |
+
save () {
|
159 |
+
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
160 |
+
echo " "
|
161 |
+
}
|
162 |
+
APP_ARGS=$(save "$@")
|
163 |
+
|
164 |
+
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
165 |
+
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
166 |
+
|
167 |
+
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
168 |
+
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
169 |
+
cd "$(dirname "$0")"
|
170 |
+
fi
|
171 |
+
|
172 |
+
exec "$JAVACMD" "$@"
|
demo/ncnn/android/gradlew.bat
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@if "%DEBUG%" == "" @echo off
|
2 |
+
@rem ##########################################################################
|
3 |
+
@rem
|
4 |
+
@rem Gradle startup script for Windows
|
5 |
+
@rem
|
6 |
+
@rem ##########################################################################
|
7 |
+
|
8 |
+
@rem Set local scope for the variables with windows NT shell
|
9 |
+
if "%OS%"=="Windows_NT" setlocal
|
10 |
+
|
11 |
+
set DIRNAME=%~dp0
|
12 |
+
if "%DIRNAME%" == "" set DIRNAME=.
|
13 |
+
set APP_BASE_NAME=%~n0
|
14 |
+
set APP_HOME=%DIRNAME%
|
15 |
+
|
16 |
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
17 |
+
set DEFAULT_JVM_OPTS=
|
18 |
+
|
19 |
+
@rem Find java.exe
|
20 |
+
if defined JAVA_HOME goto findJavaFromJavaHome
|
21 |
+
|
22 |
+
set JAVA_EXE=java.exe
|
23 |
+
%JAVA_EXE% -version >NUL 2>&1
|
24 |
+
if "%ERRORLEVEL%" == "0" goto init
|
25 |
+
|
26 |
+
echo.
|
27 |
+
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
28 |
+
echo.
|
29 |
+
echo Please set the JAVA_HOME variable in your environment to match the
|
30 |
+
echo location of your Java installation.
|
31 |
+
|
32 |
+
goto fail
|
33 |
+
|
34 |
+
:findJavaFromJavaHome
|
35 |
+
set JAVA_HOME=%JAVA_HOME:"=%
|
36 |
+
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
37 |
+
|
38 |
+
if exist "%JAVA_EXE%" goto init
|
39 |
+
|
40 |
+
echo.
|
41 |
+
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
42 |
+
echo.
|
43 |
+
echo Please set the JAVA_HOME variable in your environment to match the
|
44 |
+
echo location of your Java installation.
|
45 |
+
|
46 |
+
goto fail
|
47 |
+
|
48 |
+
:init
|
49 |
+
@rem Get command-line arguments, handling Windows variants
|
50 |
+
|
51 |
+
if not "%OS%" == "Windows_NT" goto win9xME_args
|
52 |
+
|
53 |
+
:win9xME_args
|
54 |
+
@rem Slurp the command line arguments.
|
55 |
+
set CMD_LINE_ARGS=
|
56 |
+
set _SKIP=2
|
57 |
+
|
58 |
+
:win9xME_args_slurp
|
59 |
+
if "x%~1" == "x" goto execute
|
60 |
+
|
61 |
+
set CMD_LINE_ARGS=%*
|
62 |
+
|
63 |
+
:execute
|
64 |
+
@rem Setup the command line
|
65 |
+
|
66 |
+
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
67 |
+
|
68 |
+
@rem Execute Gradle
|
69 |
+
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
70 |
+
|
71 |
+
:end
|
72 |
+
@rem End local scope for the variables with windows NT shell
|
73 |
+
if "%ERRORLEVEL%"=="0" goto mainEnd
|
74 |
+
|
75 |
+
:fail
|
76 |
+
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
77 |
+
rem the _cmd.exe /c_ return code!
|
78 |
+
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
79 |
+
exit /b 1
|
80 |
+
|
81 |
+
:mainEnd
|
82 |
+
if "%OS%"=="Windows_NT" endlocal
|
83 |
+
|
84 |
+
:omega
|
demo/ncnn/android/settings.gradle
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
include ':app'
|
demo/ncnn/{yolox.cpp → cpp/yolox.cpp}
RENAMED
File without changes
|