├── .DS_Store ├── .gitignore ├── README.md ├── app ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── nanodet-m-416.bin │ ├── nanodet-m-416.param │ ├── out.mp4 │ ├── picodet-l-640.bin │ ├── picodet-l-640.param │ ├── picodet-s-416.bin │ ├── picodet-s-416.param │ ├── yolov5s.bin │ ├── yolov5s.param │ ├── yolox-nano.bin │ └── yolox-nano.param │ ├── java │ └── com │ │ └── baidu │ │ ├── common │ │ ├── AppCompatPreferenceActivity.java │ │ ├── CameraSurfaceView.java │ │ └── Utils.java │ │ └── picodetncnn │ │ ├── CameraFragment.java │ │ ├── ContentFragment.java │ │ ├── MainActivity.java │ │ ├── NanoDetNcnn.java │ │ └── PhotoFragment.java │ ├── jni │ ├── CMakeLists.txt │ ├── nanodet.cpp │ ├── nanodet.h │ ├── nanodetncnn.cpp │ ├── ndk-stl-config.cmake │ ├── ndkcamera.cpp │ └── ndkcamera.h │ └── res │ ├── drawable-v24 │ ├── camera.png │ ├── ic_launcher_foreground.xml │ └── photo.png │ ├── drawable-xxhdpi │ ├── btn_switch_default.png │ ├── btn_switch_pressed.png │ ├── camera.png │ ├── paddle.png │ └── photo.png │ ├── drawable │ ├── btn_settings.xml │ ├── btn_settings_default.xml │ ├── btn_settings_pressed.xml │ ├── btn_shutter.xml │ ├── btn_shutter_default.xml │ ├── btn_shutter_pressed.xml │ ├── btn_switch.xml │ ├── camera.png │ ├── ic_launcher_background.xml │ ├── photo.png │ └── photo1.png │ ├── layout │ ├── activity_main.xml │ ├── content_main.xml │ ├── fragment_camera.xml │ ├── fragment_content.xml │ └── fragment_photo.xml │ ├── menu │ └── menu_main.xml │ ├── navigation │ └── nav_graph.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── downloadQrcode.png ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties ├── ncnn ├── README.md ├── nanodet-small.gif └── picodet-small.gif ├── old_assset ├── nanodet-m-320.bin ├── nanodet-m-320.param ├── nanodet-m-416.bin ├── nanodet-m-416.param ├── nanodet-m.param ├── out.avi ├── out.mp4 ├── picodet-m-processed-320.bin ├── picodet-m-processed-320.param ├── picodet-m-processed-416.bin ├── picodet-m-processed-416.param ├── picodet-s-four-head.bin ├── picodet-s-four-head.param ├── picodet-s-three-head.bin ├── picodet-s-three-head.param ├── yolov5s.bin ├── yolov5s.param ├── yolox-nano.bin └── yolox-nano.param ├── paddlelite └── README.md ├── screenshot_car.jpg └── settings.gradle /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | app/.cxx 4 | app/build 5 | app/release 6 | app/src/main/assets/old_assset 7 | app/src/main/jni/aaa 8 | app/src/main/jni/ncnn-20210720-android-vulkan 9 | app/src/main/jni/opencv 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PP-PicoDet-Android-Demo 2 | The PicoDet object detection mobile demo 3 | 4 | # Support Library 5 | [NCNN](ncnn/README.md) 6 | [Paddle-LIte](paddlelite/README.md) 7 | 8 | # Apk Download 9 | ### [download link](https://paddledet.bj.bcebos.com/deploy/third_engine/PP-PicoDet.apk) 10 | 11 | ### scan to download 12 | 13 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | // buildToolsVersion "29.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.baidu.picodetncnn" 9 | archivesBaseName = "$applicationId" 10 | minSdkVersion 24 11 | } 12 | 13 | externalNativeBuild { 14 | cmake { 15 | version "3.10.2" 16 | path file('src/main/jni/CMakeLists.txt') 17 | // abiFilters "armeabi" 18 | } 19 | 20 | } 21 | sourceSets { 22 | main { 23 | jniLibs.srcDirs = ['libs'] 24 | } 25 | 26 | } 27 | // ndk{ 28 | // abiFilters "armeabi-v7a" 29 | // } 30 | } 31 | 32 | dependencies { 33 | implementation fileTree(dir: "libs", include: ["*.jar"]) 34 | implementation 'androidx.appcompat:appcompat:1.1.0' 35 | implementation 'com.google.android.material:material:1.0.0' 36 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 37 | implementation 'androidx.navigation:navigation-fragment:2.1.0' 38 | implementation 'androidx.navigation:navigation-ui:2.1.0' 39 | testImplementation 'junit:junit:4.12' 40 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 41 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 42 | } 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/assets/nanodet-m-416.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/assets/nanodet-m-416.bin -------------------------------------------------------------------------------- /app/src/main/assets/nanodet-m-416.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 201 226 3 | Input input.1 0 1 input.1 4 | Convolution Conv_0 1 1 input.1 784 0=24 1=3 11=3 2=1 12=1 3=2 13=2 4=1 14=1 15=1 16=1 5=1 6=648 5 | ReLU LeakyRelu_1 1 1 784 424 0=1.000000e-01 6 | Pooling MaxPool_2 1 1 424 425 0=0 1=3 11=3 2=2 12=2 3=1 13=1 14=1 15=1 5=1 7 | Split splitncnn_0 1 2 425 425_splitncnn_0 425_splitncnn_1 8 | ConvolutionDepthWise Conv_3 1 1 425_splitncnn_1 787 0=24 1=3 11=3 2=1 12=1 3=2 13=2 4=1 14=1 15=1 16=1 5=1 6=216 7=24 9 | Convolution Conv_4 1 1 787 790 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=2112 10 | ReLU LeakyRelu_5 1 1 790 430 0=1.000000e-01 11 | Convolution Conv_6 1 1 425_splitncnn_0 793 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=2112 12 | ReLU LeakyRelu_7 1 1 793 433 0=1.000000e-01 13 | ConvolutionDepthWise Conv_8 1 1 433 796 0=88 1=3 11=3 2=1 12=1 3=2 13=2 4=1 14=1 15=1 16=1 5=1 6=792 7=88 14 | Convolution Conv_9 1 1 796 799 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=7744 15 | ReLU LeakyRelu_10 1 1 799 438 0=1.000000e-01 16 | Concat Concat_11 2 1 430 438 439 0=0 17 | ShuffleChannel Reshape_16 1 1 439 444 0=2 1=0 18 | Slice Split_17 1 2 444 445 446 -23300=2,88,-233 1=0 19 | Convolution Conv_18 1 1 446 802 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=7744 20 | ReLU LeakyRelu_19 1 1 802 449 0=1.000000e-01 21 | ConvolutionDepthWise Conv_20 1 1 449 805 0=88 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=792 7=88 22 | Convolution Conv_21 1 1 805 808 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=7744 23 | ReLU LeakyRelu_22 1 1 808 454 0=1.000000e-01 24 | Concat Concat_23 2 1 445 454 455 0=0 25 | ShuffleChannel Reshape_28 1 1 455 460 0=2 1=0 26 | Slice Split_29 1 2 460 461 462 -23300=2,88,-233 1=0 27 | Convolution Conv_30 1 1 462 811 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=7744 28 | ReLU LeakyRelu_31 1 1 811 465 0=1.000000e-01 29 | ConvolutionDepthWise Conv_32 1 1 465 814 0=88 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=792 7=88 30 | Convolution Conv_33 1 1 814 817 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=7744 31 | ReLU LeakyRelu_34 1 1 817 470 0=1.000000e-01 32 | Concat Concat_35 2 1 461 470 471 0=0 33 | ShuffleChannel Reshape_40 1 1 471 476 0=2 1=0 34 | Slice Split_41 1 2 476 477 478 -23300=2,88,-233 1=0 35 | Convolution Conv_42 1 1 478 820 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=7744 36 | ReLU LeakyRelu_43 1 1 820 481 0=1.000000e-01 37 | ConvolutionDepthWise Conv_44 1 1 481 823 0=88 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=792 7=88 38 | Convolution Conv_45 1 1 823 826 0=88 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=7744 39 | ReLU LeakyRelu_46 1 1 826 486 0=1.000000e-01 40 | Concat Concat_47 2 1 477 486 487 0=0 41 | ShuffleChannel Reshape_52 1 1 487 492 0=2 1=0 42 | Split splitncnn_1 1 3 492 492_splitncnn_0 492_splitncnn_1 492_splitncnn_2 43 | ConvolutionDepthWise Conv_53 1 1 492_splitncnn_2 829 0=176 1=3 11=3 2=1 12=1 3=2 13=2 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 44 | Convolution Conv_54 1 1 829 832 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 45 | ReLU LeakyRelu_55 1 1 832 497 0=1.000000e-01 46 | Convolution Conv_56 1 1 492_splitncnn_1 835 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 47 | ReLU LeakyRelu_57 1 1 835 500 0=1.000000e-01 48 | ConvolutionDepthWise Conv_58 1 1 500 838 0=176 1=3 11=3 2=1 12=1 3=2 13=2 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 49 | Convolution Conv_59 1 1 838 841 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 50 | ReLU LeakyRelu_60 1 1 841 505 0=1.000000e-01 51 | Concat Concat_61 2 1 497 505 506 0=0 52 | ShuffleChannel Reshape_66 1 1 506 511 0=2 1=0 53 | Slice Split_67 1 2 511 512 513 -23300=2,176,-233 1=0 54 | Convolution Conv_68 1 1 513 844 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 55 | ReLU LeakyRelu_69 1 1 844 516 0=1.000000e-01 56 | ConvolutionDepthWise Conv_70 1 1 516 847 0=176 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 57 | Convolution Conv_71 1 1 847 850 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 58 | ReLU LeakyRelu_72 1 1 850 521 0=1.000000e-01 59 | Concat Concat_73 2 1 512 521 522 0=0 60 | ShuffleChannel Reshape_78 1 1 522 527 0=2 1=0 61 | Slice Split_79 1 2 527 528 529 -23300=2,176,-233 1=0 62 | Convolution Conv_80 1 1 529 853 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 63 | ReLU LeakyRelu_81 1 1 853 532 0=1.000000e-01 64 | ConvolutionDepthWise Conv_82 1 1 532 856 0=176 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 65 | Convolution Conv_83 1 1 856 859 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 66 | ReLU LeakyRelu_84 1 1 859 537 0=1.000000e-01 67 | Concat Concat_85 2 1 528 537 538 0=0 68 | ShuffleChannel Reshape_90 1 1 538 543 0=2 1=0 69 | Slice Split_91 1 2 543 544 545 -23300=2,176,-233 1=0 70 | Convolution Conv_92 1 1 545 862 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 71 | ReLU LeakyRelu_93 1 1 862 548 0=1.000000e-01 72 | ConvolutionDepthWise Conv_94 1 1 548 865 0=176 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 73 | Convolution Conv_95 1 1 865 868 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 74 | ReLU LeakyRelu_96 1 1 868 553 0=1.000000e-01 75 | Concat Concat_97 2 1 544 553 554 0=0 76 | ShuffleChannel Reshape_102 1 1 554 559 0=2 1=0 77 | Slice Split_103 1 2 559 560 561 -23300=2,176,-233 1=0 78 | Convolution Conv_104 1 1 561 871 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 79 | ReLU LeakyRelu_105 1 1 871 564 0=1.000000e-01 80 | ConvolutionDepthWise Conv_106 1 1 564 874 0=176 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 81 | Convolution Conv_107 1 1 874 877 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 82 | ReLU LeakyRelu_108 1 1 877 569 0=1.000000e-01 83 | Concat Concat_109 2 1 560 569 570 0=0 84 | ShuffleChannel Reshape_114 1 1 570 575 0=2 1=0 85 | Slice Split_115 1 2 575 576 577 -23300=2,176,-233 1=0 86 | Convolution Conv_116 1 1 577 880 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 87 | ReLU LeakyRelu_117 1 1 880 580 0=1.000000e-01 88 | ConvolutionDepthWise Conv_118 1 1 580 883 0=176 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 89 | Convolution Conv_119 1 1 883 886 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 90 | ReLU LeakyRelu_120 1 1 886 585 0=1.000000e-01 91 | Concat Concat_121 2 1 576 585 586 0=0 92 | ShuffleChannel Reshape_126 1 1 586 591 0=2 1=0 93 | Slice Split_127 1 2 591 592 593 -23300=2,176,-233 1=0 94 | Convolution Conv_128 1 1 593 889 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 95 | ReLU LeakyRelu_129 1 1 889 596 0=1.000000e-01 96 | ConvolutionDepthWise Conv_130 1 1 596 892 0=176 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 97 | Convolution Conv_131 1 1 892 895 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 98 | ReLU LeakyRelu_132 1 1 895 601 0=1.000000e-01 99 | Concat Concat_133 2 1 592 601 602 0=0 100 | ShuffleChannel Reshape_138 1 1 602 607 0=2 1=0 101 | Slice Split_139 1 2 607 608 609 -23300=2,176,-233 1=0 102 | Convolution Conv_140 1 1 609 898 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 103 | ReLU LeakyRelu_141 1 1 898 612 0=1.000000e-01 104 | ConvolutionDepthWise Conv_142 1 1 612 901 0=176 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1584 7=176 105 | Convolution Conv_143 1 1 901 904 0=176 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=30976 106 | ReLU LeakyRelu_144 1 1 904 617 0=1.000000e-01 107 | Concat Concat_145 2 1 608 617 618 0=0 108 | ShuffleChannel Reshape_150 1 1 618 623 0=2 1=0 109 | Split splitncnn_2 1 3 623 623_splitncnn_0 623_splitncnn_1 623_splitncnn_2 110 | ConvolutionDepthWise Conv_151 1 1 623_splitncnn_2 907 0=352 1=3 11=3 2=1 12=1 3=2 13=2 4=1 14=1 15=1 16=1 5=1 6=3168 7=352 111 | Convolution Conv_152 1 1 907 910 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 112 | ReLU LeakyRelu_153 1 1 910 628 0=1.000000e-01 113 | Convolution Conv_154 1 1 623_splitncnn_1 913 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 114 | ReLU LeakyRelu_155 1 1 913 631 0=1.000000e-01 115 | ConvolutionDepthWise Conv_156 1 1 631 916 0=352 1=3 11=3 2=1 12=1 3=2 13=2 4=1 14=1 15=1 16=1 5=1 6=3168 7=352 116 | Convolution Conv_157 1 1 916 919 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 117 | ReLU LeakyRelu_158 1 1 919 636 0=1.000000e-01 118 | Concat Concat_159 2 1 628 636 637 0=0 119 | ShuffleChannel Reshape_164 1 1 637 642 0=2 1=0 120 | Slice Split_165 1 2 642 643 644 -23300=2,352,-233 1=0 121 | Convolution Conv_166 1 1 644 922 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 122 | ReLU LeakyRelu_167 1 1 922 647 0=1.000000e-01 123 | ConvolutionDepthWise Conv_168 1 1 647 925 0=352 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=3168 7=352 124 | Convolution Conv_169 1 1 925 928 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 125 | ReLU LeakyRelu_170 1 1 928 652 0=1.000000e-01 126 | Concat Concat_171 2 1 643 652 653 0=0 127 | ShuffleChannel Reshape_176 1 1 653 658 0=2 1=0 128 | Slice Split_177 1 2 658 659 660 -23300=2,352,-233 1=0 129 | Convolution Conv_178 1 1 660 931 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 130 | ReLU LeakyRelu_179 1 1 931 663 0=1.000000e-01 131 | ConvolutionDepthWise Conv_180 1 1 663 934 0=352 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=3168 7=352 132 | Convolution Conv_181 1 1 934 937 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 133 | ReLU LeakyRelu_182 1 1 937 668 0=1.000000e-01 134 | Concat Concat_183 2 1 659 668 669 0=0 135 | ShuffleChannel Reshape_188 1 1 669 674 0=2 1=0 136 | Slice Split_189 1 2 674 675 676 -23300=2,352,-233 1=0 137 | Convolution Conv_190 1 1 676 940 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 138 | ReLU LeakyRelu_191 1 1 940 679 0=1.000000e-01 139 | ConvolutionDepthWise Conv_192 1 1 679 943 0=352 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=3168 7=352 140 | Convolution Conv_193 1 1 943 946 0=352 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=123904 141 | ReLU LeakyRelu_194 1 1 946 684 0=1.000000e-01 142 | Concat Concat_195 2 1 675 684 685 0=0 143 | ShuffleChannel Reshape_200 1 1 685 690 0=2 1=0 144 | Convolution Conv_201 1 1 492_splitncnn_0 691 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=22528 145 | Convolution Conv_202 1 1 623_splitncnn_0 692 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=45056 146 | Convolution Conv_203 1 1 690 693 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=90112 147 | Split splitncnn_3 1 2 693 693_splitncnn_0 693_splitncnn_1 148 | Interp Resize_205 1 1 693_splitncnn_1 698 0=2 1=2.000000e+00 2=2.000000e+00 3=0 4=0 6=0 149 | BinaryOp Add_206 2 1 692 698 699 0=0 150 | Split splitncnn_4 1 2 699 699_splitncnn_0 699_splitncnn_1 151 | Interp Resize_208 1 1 699_splitncnn_1 704 0=2 1=2.000000e+00 2=2.000000e+00 3=0 4=0 6=0 152 | BinaryOp Add_209 2 1 691 704 705 0=0 153 | Split splitncnn_5 1 2 705 705_splitncnn_0 705_splitncnn_1 154 | Interp Resize_211 1 1 705_splitncnn_1 710 0=2 1=5.000000e-01 2=5.000000e-01 3=0 4=0 6=0 155 | BinaryOp Add_212 2 1 699_splitncnn_0 710 711 0=0 156 | Split splitncnn_6 1 2 711 711_splitncnn_0 711_splitncnn_1 157 | Interp Resize_214 1 1 711_splitncnn_1 716 0=2 1=5.000000e-01 2=5.000000e-01 3=0 4=0 6=0 158 | BinaryOp Add_215 2 1 693_splitncnn_0 716 717 0=0 159 | ConvolutionDepthWise Conv_216 1 1 705_splitncnn_0 949 0=128 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1152 7=128 160 | ReLU LeakyRelu_217 1 1 949 720 0=1.000000e-01 161 | Convolution Conv_218 1 1 720 952 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=16384 162 | ReLU LeakyRelu_219 1 1 952 723 0=1.000000e-01 163 | ConvolutionDepthWise Conv_220 1 1 723 955 0=128 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1152 7=128 164 | ReLU LeakyRelu_221 1 1 955 726 0=1.000000e-01 165 | Convolution Conv_222 1 1 726 958 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=16384 166 | ReLU LeakyRelu_223 1 1 958 729 0=1.000000e-01 167 | Convolution Conv_224 1 1 729 730 0=112 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=14336 168 | Slice Split_225 1 2 730 731 732 -23300=2,80,-233 1=0 169 | Sigmoid Sigmoid_226 1 1 731 733 170 | Reshape Reshape_228 1 1 733 735 0=-1 1=80 171 | Permute Transpose_229 1 1 735 cls_pred_stride_8 0=1 172 | Reshape Reshape_231 1 1 732 738 0=-1 1=32 173 | Permute Transpose_232 1 1 738 dis_pred_stride_8 0=1 174 | ConvolutionDepthWise Conv_233 1 1 711_splitncnn_0 961 0=128 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1152 7=128 175 | ReLU LeakyRelu_234 1 1 961 742 0=1.000000e-01 176 | Convolution Conv_235 1 1 742 964 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=16384 177 | ReLU LeakyRelu_236 1 1 964 745 0=1.000000e-01 178 | ConvolutionDepthWise Conv_237 1 1 745 967 0=128 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1152 7=128 179 | ReLU LeakyRelu_238 1 1 967 748 0=1.000000e-01 180 | Convolution Conv_239 1 1 748 970 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=16384 181 | ReLU LeakyRelu_240 1 1 970 751 0=1.000000e-01 182 | Convolution Conv_241 1 1 751 752 0=112 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=14336 183 | Slice Split_242 1 2 752 753 754 -23300=2,80,-233 1=0 184 | Sigmoid Sigmoid_243 1 1 753 755 185 | Reshape Reshape_245 1 1 755 757 0=-1 1=80 186 | Permute Transpose_246 1 1 757 cls_pred_stride_16 0=1 187 | Reshape Reshape_248 1 1 754 760 0=-1 1=32 188 | Permute Transpose_249 1 1 760 dis_pred_stride_16 0=1 189 | ConvolutionDepthWise Conv_250 1 1 717 973 0=128 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1152 7=128 190 | ReLU LeakyRelu_251 1 1 973 764 0=1.000000e-01 191 | Convolution Conv_252 1 1 764 976 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=16384 192 | ReLU LeakyRelu_253 1 1 976 767 0=1.000000e-01 193 | ConvolutionDepthWise Conv_254 1 1 767 979 0=128 1=3 11=3 2=1 12=1 3=1 13=1 4=1 14=1 15=1 16=1 5=1 6=1152 7=128 194 | ReLU LeakyRelu_255 1 1 979 770 0=1.000000e-01 195 | Convolution Conv_256 1 1 770 982 0=128 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=16384 196 | ReLU LeakyRelu_257 1 1 982 773 0=1.000000e-01 197 | Convolution Conv_258 1 1 773 774 0=112 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 15=0 16=0 5=1 6=14336 198 | Slice Split_259 1 2 774 775 776 -23300=2,80,-233 1=0 199 | Sigmoid Sigmoid_260 1 1 775 777 200 | Reshape Reshape_262 1 1 777 779 0=-1 1=80 201 | Permute Transpose_263 1 1 779 cls_pred_stride_32 0=1 202 | Reshape Reshape_265 1 1 776 782 0=-1 1=32 203 | Permute Transpose_266 1 1 782 dis_pred_stride_32 0=1 204 | -------------------------------------------------------------------------------- /app/src/main/assets/out.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/assets/out.mp4 -------------------------------------------------------------------------------- /app/src/main/assets/picodet-l-640.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/assets/picodet-l-640.bin -------------------------------------------------------------------------------- /app/src/main/assets/picodet-s-416.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/assets/picodet-s-416.bin -------------------------------------------------------------------------------- /app/src/main/assets/yolov5s.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/assets/yolov5s.bin -------------------------------------------------------------------------------- /app/src/main/assets/yolov5s.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 192 216 3 | Input images 0 1 images 4 | YoloV5Focus focus 1 1 images 207 5 | Convolution Conv_41 1 1 207 208 0=32 1=3 4=1 5=1 6=3456 6 | HardSwish Div_49 1 1 208 216 0=1.666667e-01 7 | Convolution Conv_50 1 1 216 217 0=64 1=3 3=2 4=1 5=1 6=18432 8 | HardSwish Div_58 1 1 217 225 0=1.666667e-01 9 | Split splitncnn_0 1 2 225 225_splitncnn_0 225_splitncnn_1 10 | Convolution Conv_59 1 1 225_splitncnn_1 226 0=32 1=1 5=1 6=2048 11 | HardSwish Div_67 1 1 226 234 0=1.666667e-01 12 | Split splitncnn_1 1 2 234 234_splitncnn_0 234_splitncnn_1 13 | Convolution Conv_68 1 1 234_splitncnn_1 235 0=32 1=1 5=1 6=1024 14 | HardSwish Div_76 1 1 235 243 0=1.666667e-01 15 | Convolution Conv_77 1 1 243 244 0=32 1=3 4=1 5=1 6=9216 16 | HardSwish Div_85 1 1 244 252 0=1.666667e-01 17 | BinaryOp Add_86 2 1 234_splitncnn_0 252 253 18 | Convolution Conv_87 1 1 253 254 0=32 1=1 6=1024 19 | Convolution Conv_88 1 1 225_splitncnn_0 255 0=32 1=1 6=2048 20 | Concat Concat_89 2 1 254 255 256 21 | BatchNorm BatchNormalization_90 1 1 256 257 0=64 22 | ReLU LeakyRelu_91 1 1 257 258 0=1.000000e-01 23 | Convolution Conv_92 1 1 258 259 0=64 1=1 5=1 6=4096 24 | HardSwish Div_100 1 1 259 267 0=1.666667e-01 25 | Convolution Conv_101 1 1 267 268 0=128 1=3 3=2 4=1 5=1 6=73728 26 | HardSwish Div_109 1 1 268 276 0=1.666667e-01 27 | Split splitncnn_2 1 2 276 276_splitncnn_0 276_splitncnn_1 28 | Convolution Conv_110 1 1 276_splitncnn_1 277 0=64 1=1 5=1 6=8192 29 | HardSwish Div_118 1 1 277 285 0=1.666667e-01 30 | Split splitncnn_3 1 2 285 285_splitncnn_0 285_splitncnn_1 31 | Convolution Conv_119 1 1 285_splitncnn_1 286 0=64 1=1 5=1 6=4096 32 | HardSwish Div_127 1 1 286 294 0=1.666667e-01 33 | Convolution Conv_128 1 1 294 295 0=64 1=3 4=1 5=1 6=36864 34 | HardSwish Div_136 1 1 295 303 0=1.666667e-01 35 | BinaryOp Add_137 2 1 285_splitncnn_0 303 304 36 | Split splitncnn_4 1 2 304 304_splitncnn_0 304_splitncnn_1 37 | Convolution Conv_138 1 1 304_splitncnn_1 305 0=64 1=1 5=1 6=4096 38 | HardSwish Div_146 1 1 305 313 0=1.666667e-01 39 | Convolution Conv_147 1 1 313 314 0=64 1=3 4=1 5=1 6=36864 40 | HardSwish Div_155 1 1 314 322 0=1.666667e-01 41 | BinaryOp Add_156 2 1 304_splitncnn_0 322 323 42 | Split splitncnn_5 1 2 323 323_splitncnn_0 323_splitncnn_1 43 | Convolution Conv_157 1 1 323_splitncnn_1 324 0=64 1=1 5=1 6=4096 44 | HardSwish Div_165 1 1 324 332 0=1.666667e-01 45 | Convolution Conv_166 1 1 332 333 0=64 1=3 4=1 5=1 6=36864 46 | HardSwish Div_174 1 1 333 341 0=1.666667e-01 47 | BinaryOp Add_175 2 1 323_splitncnn_0 341 342 48 | Convolution Conv_176 1 1 342 343 0=64 1=1 6=4096 49 | Convolution Conv_177 1 1 276_splitncnn_0 344 0=64 1=1 6=8192 50 | Concat Concat_178 2 1 343 344 345 51 | BatchNorm BatchNormalization_179 1 1 345 346 0=128 52 | ReLU LeakyRelu_180 1 1 346 347 0=1.000000e-01 53 | Convolution Conv_181 1 1 347 348 0=128 1=1 5=1 6=16384 54 | HardSwish Div_189 1 1 348 356 0=1.666667e-01 55 | Split splitncnn_6 1 2 356 356_splitncnn_0 356_splitncnn_1 56 | Convolution Conv_190 1 1 356_splitncnn_1 357 0=256 1=3 3=2 4=1 5=1 6=294912 57 | HardSwish Div_198 1 1 357 365 0=1.666667e-01 58 | Split splitncnn_7 1 2 365 365_splitncnn_0 365_splitncnn_1 59 | Convolution Conv_199 1 1 365_splitncnn_1 366 0=128 1=1 5=1 6=32768 60 | HardSwish Div_207 1 1 366 374 0=1.666667e-01 61 | Split splitncnn_8 1 2 374 374_splitncnn_0 374_splitncnn_1 62 | Convolution Conv_208 1 1 374_splitncnn_1 375 0=128 1=1 5=1 6=16384 63 | HardSwish Div_216 1 1 375 383 0=1.666667e-01 64 | Convolution Conv_217 1 1 383 384 0=128 1=3 4=1 5=1 6=147456 65 | HardSwish Div_225 1 1 384 392 0=1.666667e-01 66 | BinaryOp Add_226 2 1 374_splitncnn_0 392 393 67 | Split splitncnn_9 1 2 393 393_splitncnn_0 393_splitncnn_1 68 | Convolution Conv_227 1 1 393_splitncnn_1 394 0=128 1=1 5=1 6=16384 69 | HardSwish Div_235 1 1 394 402 0=1.666667e-01 70 | Convolution Conv_236 1 1 402 403 0=128 1=3 4=1 5=1 6=147456 71 | HardSwish Div_244 1 1 403 411 0=1.666667e-01 72 | BinaryOp Add_245 2 1 393_splitncnn_0 411 412 73 | Split splitncnn_10 1 2 412 412_splitncnn_0 412_splitncnn_1 74 | Convolution Conv_246 1 1 412_splitncnn_1 413 0=128 1=1 5=1 6=16384 75 | HardSwish Div_254 1 1 413 421 0=1.666667e-01 76 | Convolution Conv_255 1 1 421 422 0=128 1=3 4=1 5=1 6=147456 77 | HardSwish Div_263 1 1 422 430 0=1.666667e-01 78 | BinaryOp Add_264 2 1 412_splitncnn_0 430 431 79 | Convolution Conv_265 1 1 431 432 0=128 1=1 6=16384 80 | Convolution Conv_266 1 1 365_splitncnn_0 433 0=128 1=1 6=32768 81 | Concat Concat_267 2 1 432 433 434 82 | BatchNorm BatchNormalization_268 1 1 434 435 0=256 83 | ReLU LeakyRelu_269 1 1 435 436 0=1.000000e-01 84 | Convolution Conv_270 1 1 436 437 0=256 1=1 5=1 6=65536 85 | HardSwish Div_278 1 1 437 445 0=1.666667e-01 86 | Split splitncnn_11 1 2 445 445_splitncnn_0 445_splitncnn_1 87 | Convolution Conv_279 1 1 445_splitncnn_1 446 0=512 1=3 3=2 4=1 5=1 6=1179648 88 | HardSwish Div_287 1 1 446 454 0=1.666667e-01 89 | Convolution Conv_288 1 1 454 455 0=256 1=1 5=1 6=131072 90 | HardSwish Div_296 1 1 455 463 0=1.666667e-01 91 | Split splitncnn_12 1 4 463 463_splitncnn_0 463_splitncnn_1 463_splitncnn_2 463_splitncnn_3 92 | Pooling MaxPool_297 1 1 463_splitncnn_3 464 1=5 3=2 5=1 93 | Pooling MaxPool_298 1 1 463_splitncnn_2 465 1=9 3=4 5=1 94 | Pooling MaxPool_299 1 1 463_splitncnn_1 466 1=13 3=6 5=1 95 | Concat Concat_300 4 1 463_splitncnn_0 464 465 466 467 96 | Convolution Conv_301 1 1 467 468 0=512 1=1 5=1 6=524288 97 | HardSwish Div_309 1 1 468 476 0=1.666667e-01 98 | Split splitncnn_13 1 2 476 476_splitncnn_0 476_splitncnn_1 99 | Convolution Conv_310 1 1 476_splitncnn_1 477 0=256 1=1 5=1 6=131072 100 | HardSwish Div_318 1 1 477 485 0=1.666667e-01 101 | Convolution Conv_319 1 1 485 486 0=256 1=1 5=1 6=65536 102 | HardSwish Div_327 1 1 486 494 0=1.666667e-01 103 | Convolution Conv_328 1 1 494 495 0=256 1=3 4=1 5=1 6=589824 104 | HardSwish Div_336 1 1 495 503 0=1.666667e-01 105 | Convolution Conv_337 1 1 503 504 0=256 1=1 6=65536 106 | Convolution Conv_338 1 1 476_splitncnn_0 505 0=256 1=1 6=131072 107 | Concat Concat_339 2 1 504 505 506 108 | BatchNorm BatchNormalization_340 1 1 506 507 0=512 109 | ReLU LeakyRelu_341 1 1 507 508 0=1.000000e-01 110 | Convolution Conv_342 1 1 508 509 0=512 1=1 5=1 6=262144 111 | HardSwish Div_350 1 1 509 517 0=1.666667e-01 112 | Convolution Conv_351 1 1 517 518 0=256 1=1 5=1 6=131072 113 | HardSwish Div_359 1 1 518 526 0=1.666667e-01 114 | Split splitncnn_14 1 2 526 526_splitncnn_0 526_splitncnn_1 115 | Interp Resize_361 1 1 526_splitncnn_1 536 0=1 1=2.000000e+00 2=2.000000e+00 116 | Concat Concat_362 2 1 536 445_splitncnn_0 537 117 | Split splitncnn_15 1 2 537 537_splitncnn_0 537_splitncnn_1 118 | Convolution Conv_363 1 1 537_splitncnn_1 538 0=128 1=1 5=1 6=65536 119 | HardSwish Div_371 1 1 538 546 0=1.666667e-01 120 | Convolution Conv_372 1 1 546 547 0=128 1=1 5=1 6=16384 121 | HardSwish Div_380 1 1 547 555 0=1.666667e-01 122 | Convolution Conv_381 1 1 555 556 0=128 1=3 4=1 5=1 6=147456 123 | HardSwish Div_389 1 1 556 564 0=1.666667e-01 124 | Convolution Conv_390 1 1 564 565 0=128 1=1 6=16384 125 | Convolution Conv_391 1 1 537_splitncnn_0 566 0=128 1=1 6=65536 126 | Concat Concat_392 2 1 565 566 567 127 | BatchNorm BatchNormalization_393 1 1 567 568 0=256 128 | ReLU LeakyRelu_394 1 1 568 569 0=1.000000e-01 129 | Convolution Conv_395 1 1 569 570 0=256 1=1 5=1 6=65536 130 | HardSwish Div_403 1 1 570 578 0=1.666667e-01 131 | Convolution Conv_404 1 1 578 579 0=128 1=1 5=1 6=32768 132 | HardSwish Div_412 1 1 579 587 0=1.666667e-01 133 | Split splitncnn_16 1 2 587 587_splitncnn_0 587_splitncnn_1 134 | Interp Resize_414 1 1 587_splitncnn_1 597 0=1 1=2.000000e+00 2=2.000000e+00 135 | Concat Concat_415 2 1 597 356_splitncnn_0 598 136 | Split splitncnn_17 1 2 598 598_splitncnn_0 598_splitncnn_1 137 | Convolution Conv_416 1 1 598_splitncnn_1 599 0=64 1=1 5=1 6=16384 138 | HardSwish Div_424 1 1 599 607 0=1.666667e-01 139 | Convolution Conv_425 1 1 607 608 0=64 1=1 5=1 6=4096 140 | HardSwish Div_433 1 1 608 616 0=1.666667e-01 141 | Convolution Conv_434 1 1 616 617 0=64 1=3 4=1 5=1 6=36864 142 | HardSwish Div_442 1 1 617 625 0=1.666667e-01 143 | Convolution Conv_443 1 1 625 626 0=64 1=1 6=4096 144 | Convolution Conv_444 1 1 598_splitncnn_0 627 0=64 1=1 6=16384 145 | Concat Concat_445 2 1 626 627 628 146 | BatchNorm BatchNormalization_446 1 1 628 629 0=128 147 | ReLU LeakyRelu_447 1 1 629 630 0=1.000000e-01 148 | Convolution Conv_448 1 1 630 631 0=128 1=1 5=1 6=16384 149 | HardSwish Div_456 1 1 631 639 0=1.666667e-01 150 | Split splitncnn_18 1 2 639 639_splitncnn_0 639_splitncnn_1 151 | Convolution Conv_457 1 1 639_splitncnn_1 640 0=128 1=3 3=2 4=1 5=1 6=147456 152 | HardSwish Div_465 1 1 640 648 0=1.666667e-01 153 | Concat Concat_466 2 1 648 587_splitncnn_0 649 154 | Split splitncnn_19 1 2 649 649_splitncnn_0 649_splitncnn_1 155 | Convolution Conv_467 1 1 649_splitncnn_1 650 0=128 1=1 5=1 6=32768 156 | HardSwish Div_475 1 1 650 658 0=1.666667e-01 157 | Convolution Conv_476 1 1 658 659 0=128 1=1 5=1 6=16384 158 | HardSwish Div_484 1 1 659 667 0=1.666667e-01 159 | Convolution Conv_485 1 1 667 668 0=128 1=3 4=1 5=1 6=147456 160 | HardSwish Div_493 1 1 668 676 0=1.666667e-01 161 | Convolution Conv_494 1 1 676 677 0=128 1=1 6=16384 162 | Convolution Conv_495 1 1 649_splitncnn_0 678 0=128 1=1 6=32768 163 | Concat Concat_496 2 1 677 678 679 164 | BatchNorm BatchNormalization_497 1 1 679 680 0=256 165 | ReLU LeakyRelu_498 1 1 680 681 0=1.000000e-01 166 | Convolution Conv_499 1 1 681 682 0=256 1=1 5=1 6=65536 167 | HardSwish Div_507 1 1 682 690 0=1.666667e-01 168 | Split splitncnn_20 1 2 690 690_splitncnn_0 690_splitncnn_1 169 | Convolution Conv_508 1 1 690_splitncnn_1 691 0=256 1=3 3=2 4=1 5=1 6=589824 170 | HardSwish Div_516 1 1 691 699 0=1.666667e-01 171 | Concat Concat_517 2 1 699 526_splitncnn_0 700 172 | Split splitncnn_21 1 2 700 700_splitncnn_0 700_splitncnn_1 173 | Convolution Conv_518 1 1 700_splitncnn_1 701 0=256 1=1 5=1 6=131072 174 | HardSwish Div_526 1 1 701 709 0=1.666667e-01 175 | Convolution Conv_527 1 1 709 710 0=256 1=1 5=1 6=65536 176 | HardSwish Div_535 1 1 710 718 0=1.666667e-01 177 | Convolution Conv_536 1 1 718 719 0=256 1=3 4=1 5=1 6=589824 178 | HardSwish Div_544 1 1 719 727 0=1.666667e-01 179 | Convolution Conv_545 1 1 727 728 0=256 1=1 6=65536 180 | Convolution Conv_546 1 1 700_splitncnn_0 729 0=256 1=1 6=131072 181 | Concat Concat_547 2 1 728 729 730 182 | BatchNorm BatchNormalization_548 1 1 730 731 0=512 183 | ReLU LeakyRelu_549 1 1 731 732 0=1.000000e-01 184 | Convolution Conv_550 1 1 732 733 0=512 1=1 5=1 6=262144 185 | HardSwish Div_558 1 1 733 741 0=1.666667e-01 186 | Convolution Conv_559 1 1 639_splitncnn_0 742 0=255 1=1 5=1 6=32640 187 | Reshape Reshape_573 1 1 742 760 0=-1 1=85 2=3 188 | Permute Transpose_574 1 1 760 output 0=1 189 | Convolution Conv_575 1 1 690_splitncnn_0 762 0=255 1=1 5=1 6=65280 190 | Reshape Reshape_589 1 1 762 780 0=-1 1=85 2=3 191 | Permute Transpose_590 1 1 780 781 0=1 192 | Convolution Conv_591 1 1 741 782 0=255 1=1 5=1 6=130560 193 | Reshape Reshape_605 1 1 782 800 0=-1 1=85 2=3 194 | Permute Transpose_606 1 1 800 801 0=1 -------------------------------------------------------------------------------- /app/src/main/assets/yolox-nano.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/assets/yolox-nano.bin -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/common/AppCompatPreferenceActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.baidu.common; 18 | 19 | import android.content.res.Configuration; 20 | import android.os.Bundle; 21 | import android.preference.PreferenceActivity; 22 | import android.view.MenuInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | 26 | import androidx.annotation.LayoutRes; 27 | import androidx.annotation.Nullable; 28 | import androidx.appcompat.app.ActionBar; 29 | import androidx.appcompat.app.AppCompatDelegate; 30 | import androidx.appcompat.widget.Toolbar; 31 | 32 | /** 33 | * A {@link PreferenceActivity} which implements and proxies the necessary calls 34 | * to be used with AppCompat. 35 | *

36 | * This technique can be used with an {@link android.app.Activity} class, not just 37 | * {@link PreferenceActivity}. 38 | */ 39 | public abstract class AppCompatPreferenceActivity extends PreferenceActivity { 40 | private AppCompatDelegate mDelegate; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | getDelegate().installViewFactory(); 45 | getDelegate().onCreate(savedInstanceState); 46 | super.onCreate(savedInstanceState); 47 | } 48 | 49 | @Override 50 | protected void onPostCreate(Bundle savedInstanceState) { 51 | super.onPostCreate(savedInstanceState); 52 | getDelegate().onPostCreate(savedInstanceState); 53 | } 54 | 55 | public ActionBar getSupportActionBar() { 56 | return getDelegate().getSupportActionBar(); 57 | } 58 | 59 | public void setSupportActionBar(@Nullable Toolbar toolbar) { 60 | getDelegate().setSupportActionBar(toolbar); 61 | } 62 | 63 | @Override 64 | public MenuInflater getMenuInflater() { 65 | return getDelegate().getMenuInflater(); 66 | } 67 | 68 | @Override 69 | public void setContentView(@LayoutRes int layoutResID) { 70 | getDelegate().setContentView(layoutResID); 71 | } 72 | 73 | @Override 74 | public void setContentView(View view) { 75 | getDelegate().setContentView(view); 76 | } 77 | 78 | @Override 79 | public void setContentView(View view, ViewGroup.LayoutParams params) { 80 | getDelegate().setContentView(view, params); 81 | } 82 | 83 | @Override 84 | public void addContentView(View view, ViewGroup.LayoutParams params) { 85 | getDelegate().addContentView(view, params); 86 | } 87 | 88 | @Override 89 | protected void onPostResume() { 90 | super.onPostResume(); 91 | getDelegate().onPostResume(); 92 | } 93 | 94 | @Override 95 | protected void onTitleChanged(CharSequence title, int color) { 96 | super.onTitleChanged(title, color); 97 | getDelegate().setTitle(title); 98 | } 99 | 100 | @Override 101 | public void onConfigurationChanged(Configuration newConfig) { 102 | super.onConfigurationChanged(newConfig); 103 | getDelegate().onConfigurationChanged(newConfig); 104 | } 105 | 106 | @Override 107 | protected void onStop() { 108 | super.onStop(); 109 | getDelegate().onStop(); 110 | } 111 | 112 | @Override 113 | protected void onDestroy() { 114 | super.onDestroy(); 115 | getDelegate().onDestroy(); 116 | } 117 | 118 | public void invalidateOptionsMenu() { 119 | getDelegate().invalidateOptionsMenu(); 120 | } 121 | 122 | private AppCompatDelegate getDelegate() { 123 | if (mDelegate == null) { 124 | mDelegate = AppCompatDelegate.create(this, null); 125 | } 126 | return mDelegate; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/common/CameraSurfaceView.java: -------------------------------------------------------------------------------- 1 | package com.baidu.common; 2 | 3 | import android.content.Context; 4 | import android.graphics.SurfaceTexture; 5 | import android.hardware.Camera; 6 | import android.hardware.Camera.CameraInfo; 7 | import android.hardware.Camera.Size; 8 | import android.opengl.GLES11Ext; 9 | import android.opengl.GLES20; 10 | import android.opengl.GLSurfaceView; 11 | import android.opengl.GLSurfaceView.Renderer; 12 | import android.opengl.Matrix; 13 | import android.util.AttributeSet; 14 | import android.util.Log; 15 | 16 | import java.io.IOException; 17 | import java.nio.ByteBuffer; 18 | import java.nio.ByteOrder; 19 | import java.nio.FloatBuffer; 20 | import java.util.List; 21 | 22 | import javax.microedition.khronos.egl.EGLConfig; 23 | import javax.microedition.khronos.opengles.GL10; 24 | 25 | public class CameraSurfaceView extends GLSurfaceView implements Renderer, 26 | SurfaceTexture.OnFrameAvailableListener { 27 | private static final String TAG = CameraSurfaceView.class.getSimpleName(); 28 | 29 | public static final int EXPECTED_PREVIEW_WIDTH = 1280; 30 | public static final int EXPECTED_PREVIEW_HEIGHT = 720; 31 | 32 | 33 | protected int numberOfCameras; 34 | protected int selectedCameraId; 35 | protected boolean disableCamera = false; 36 | protected Camera camera; 37 | 38 | protected Context context; 39 | protected SurfaceTexture surfaceTexture; 40 | protected int surfaceWidth = 0; 41 | protected int surfaceHeight = 0; 42 | protected int textureWidth = 0; 43 | protected int textureHeight = 0; 44 | 45 | // In order to manipulate the camera preview data and render the modified one 46 | // to the screen, three textures are created and the data flow is shown as following: 47 | // previewdata->camTextureId->fboTexureId->drawTexureId->framebuffer 48 | protected int[] fbo = {0}; 49 | protected int[] camTextureId = {0}; 50 | protected int[] fboTexureId = {0}; 51 | protected int[] drawTexureId = {0}; 52 | 53 | private final String vss = "" 54 | + "attribute vec2 vPosition;\n" 55 | + "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n" 56 | + "void main() {\n" + " texCoord = vTexCoord;\n" 57 | + " gl_Position = vec4 (vPosition.x, vPosition.y, 0.0, 1.0);\n" 58 | + "}"; 59 | 60 | private final String fssCam2FBO = "" 61 | + "#extension GL_OES_EGL_image_external : require\n" 62 | + "precision mediump float;\n" 63 | + "uniform samplerExternalOES sTexture;\n" 64 | + "varying vec2 texCoord;\n" 65 | + "void main() {\n" 66 | + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; 67 | 68 | private final String fssTex2Screen = "" 69 | + "precision mediump float;\n" 70 | + "uniform sampler2D sTexture;\n" 71 | + "varying vec2 texCoord;\n" 72 | + "void main() {\n" 73 | + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; 74 | 75 | private final float vertexCoords[] = { 76 | -1, -1, 77 | -1, 1, 78 | 1, -1, 79 | 1, 1}; 80 | private float textureCoords[] = { 81 | 0, 1, 82 | 0, 0, 83 | 1, 1, 84 | 1, 0}; 85 | 86 | private FloatBuffer vertexCoordsBuffer; 87 | private FloatBuffer textureCoordsBuffer; 88 | 89 | private int progCam2FBO = -1; 90 | private int progTex2Screen = -1; 91 | private int vcCam2FBO; 92 | private int tcCam2FBO; 93 | private int vcTex2Screen; 94 | private int tcTex2Screen; 95 | 96 | public interface OnTextureChangedListener { 97 | public boolean onTextureChanged(int inTextureId, int outTextureId, int textureWidth, int textureHeight); 98 | } 99 | 100 | private OnTextureChangedListener onTextureChangedListener = null; 101 | 102 | public void setOnTextureChangedListener(OnTextureChangedListener listener) { 103 | onTextureChangedListener = listener; 104 | } 105 | 106 | public CameraSurfaceView(Context ctx, AttributeSet attrs) { 107 | super(ctx, attrs); 108 | context = ctx; 109 | setEGLContextClientVersion(2); 110 | setRenderer(this); 111 | setRenderMode(RENDERMODE_WHEN_DIRTY); 112 | 113 | // Find the total number of available cameras and the ID of the default camera 114 | numberOfCameras = Camera.getNumberOfCameras(); 115 | CameraInfo cameraInfo = new CameraInfo(); 116 | for (int i = 0; i < numberOfCameras; i++) { 117 | Camera.getCameraInfo(i, cameraInfo); 118 | if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { 119 | selectedCameraId = i; 120 | } 121 | } 122 | } 123 | 124 | @Override 125 | public void onSurfaceCreated(GL10 gl, EGLConfig config) { 126 | // Create OES texture for storing camera preview data(YUV format) 127 | GLES20.glGenTextures(1, camTextureId, 0); 128 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, camTextureId[0]); 129 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 130 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 131 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 132 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 133 | surfaceTexture = new SurfaceTexture(camTextureId[0]); 134 | surfaceTexture.setOnFrameAvailableListener(this); 135 | 136 | // Prepare vertex and texture coordinates 137 | int bytes = vertexCoords.length * Float.SIZE / Byte.SIZE; 138 | vertexCoordsBuffer = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); 139 | textureCoordsBuffer = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); 140 | vertexCoordsBuffer.put(vertexCoords).position(0); 141 | textureCoordsBuffer.put(textureCoords).position(0); 142 | 143 | // Create vertex and fragment shaders 144 | // camTextureId->fboTexureId 145 | progCam2FBO = Utils.createShaderProgram(vss, fssCam2FBO); 146 | vcCam2FBO = GLES20.glGetAttribLocation(progCam2FBO, "vPosition"); 147 | tcCam2FBO = GLES20.glGetAttribLocation(progCam2FBO, "vTexCoord"); 148 | GLES20.glEnableVertexAttribArray(vcCam2FBO); 149 | GLES20.glEnableVertexAttribArray(tcCam2FBO); 150 | // fboTexureId/drawTexureId -> screen 151 | progTex2Screen = Utils.createShaderProgram(vss, fssTex2Screen); 152 | vcTex2Screen = GLES20.glGetAttribLocation(progTex2Screen, "vPosition"); 153 | tcTex2Screen = GLES20.glGetAttribLocation(progTex2Screen, "vTexCoord"); 154 | GLES20.glEnableVertexAttribArray(vcTex2Screen); 155 | GLES20.glEnableVertexAttribArray(tcTex2Screen); 156 | } 157 | 158 | @Override 159 | public void onSurfaceChanged(GL10 gl, int width, int height) { 160 | surfaceWidth = width; 161 | surfaceHeight = height; 162 | openCamera(); 163 | } 164 | 165 | @Override 166 | public void onDrawFrame(GL10 gl) { 167 | if (surfaceTexture == null) return; 168 | 169 | GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 170 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 171 | surfaceTexture.updateTexImage(); 172 | float matrix[] = new float[16]; 173 | surfaceTexture.getTransformMatrix(matrix); 174 | 175 | // camTextureId->fboTexureId 176 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo[0]); 177 | GLES20.glViewport(0, 0, textureWidth, textureHeight); 178 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 179 | GLES20.glUseProgram(progCam2FBO); 180 | GLES20.glVertexAttribPointer(vcCam2FBO, 2, GLES20.GL_FLOAT, false, 4 * 2, vertexCoordsBuffer); 181 | textureCoordsBuffer.clear(); 182 | textureCoordsBuffer.put(transformTextureCoordinates(textureCoords, matrix)); 183 | textureCoordsBuffer.position(0); 184 | GLES20.glVertexAttribPointer(tcCam2FBO, 2, GLES20.GL_FLOAT, false, 4 * 2, textureCoordsBuffer); 185 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 186 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, camTextureId[0]); 187 | GLES20.glUniform1i(GLES20.glGetUniformLocation(progCam2FBO, "sTexture"), 0); 188 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 189 | GLES20.glFlush(); 190 | 191 | // Check if the draw texture is set 192 | int targetTexureId = fboTexureId[0]; 193 | if (onTextureChangedListener != null) { 194 | boolean modified = onTextureChangedListener.onTextureChanged(fboTexureId[0], drawTexureId[0], 195 | textureWidth, textureHeight); 196 | if (modified) { 197 | targetTexureId = drawTexureId[0]; 198 | } 199 | } 200 | 201 | // fboTexureId/drawTexureId->Screen 202 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 203 | GLES20.glViewport(0, 0, surfaceWidth, surfaceHeight); 204 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 205 | GLES20.glUseProgram(progTex2Screen); 206 | GLES20.glVertexAttribPointer(vcTex2Screen, 2, GLES20.GL_FLOAT, false, 4 * 2, vertexCoordsBuffer); 207 | textureCoordsBuffer.clear(); 208 | textureCoordsBuffer.put(textureCoords); 209 | textureCoordsBuffer.position(0); 210 | GLES20.glVertexAttribPointer(tcTex2Screen, 2, GLES20.GL_FLOAT, false, 4 * 2, textureCoordsBuffer); 211 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 212 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, targetTexureId); 213 | GLES20.glUniform1i(GLES20.glGetUniformLocation(progTex2Screen, "sTexture"), 0); 214 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 215 | GLES20.glFlush(); 216 | } 217 | 218 | private float[] transformTextureCoordinates(float[] coords, float[] matrix) { 219 | float[] result = new float[coords.length]; 220 | float[] vt = new float[4]; 221 | for (int i = 0; i < coords.length; i += 2) { 222 | float[] v = {coords[i], coords[i + 1], 0, 1}; 223 | Matrix.multiplyMV(vt, 0, matrix, 0, v, 0); 224 | result[i] = vt[0]; 225 | result[i + 1] = vt[1]; 226 | } 227 | return result; 228 | } 229 | 230 | @Override 231 | public void onResume() { 232 | super.onResume(); 233 | } 234 | 235 | @Override 236 | public void onPause() { 237 | super.onPause(); 238 | releaseCamera(); 239 | } 240 | 241 | @Override 242 | public void onFrameAvailable(SurfaceTexture surfaceTexture) { 243 | requestRender(); 244 | } 245 | 246 | public void disableCamera() { 247 | disableCamera = true; 248 | } 249 | 250 | public void switchCamera() { 251 | releaseCamera(); 252 | selectedCameraId = (selectedCameraId + 1) % numberOfCameras; 253 | openCamera(); 254 | } 255 | 256 | public void openCamera() { 257 | if (disableCamera) return; 258 | camera = Camera.open(selectedCameraId); 259 | List supportedPreviewSizes = camera.getParameters().getSupportedPreviewSizes(); 260 | Size previewSize = Utils.getOptimalPreviewSize(supportedPreviewSizes, EXPECTED_PREVIEW_WIDTH, 261 | EXPECTED_PREVIEW_HEIGHT); 262 | Camera.Parameters parameters = camera.getParameters(); 263 | parameters.setPreviewSize(previewSize.width, previewSize.height); 264 | if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { 265 | parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); 266 | } 267 | camera.setParameters(parameters); 268 | int degree = Utils.getCameraDisplayOrientation(context, selectedCameraId); 269 | camera.setDisplayOrientation(degree); 270 | boolean rotate = degree == 90 || degree == 270; 271 | textureWidth = rotate ? previewSize.height : previewSize.width; 272 | textureHeight = rotate ? previewSize.width : previewSize.height; 273 | // Destroy FBO and draw textures 274 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 275 | GLES20.glDeleteFramebuffers(1, fbo, 0); 276 | GLES20.glDeleteTextures(1, drawTexureId, 0); 277 | GLES20.glDeleteTextures(1, fboTexureId, 0); 278 | // Normal texture for storing modified camera preview data(RGBA format) 279 | GLES20.glGenTextures(1, drawTexureId, 0); 280 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, drawTexureId[0]); 281 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, textureWidth, textureHeight, 0, 282 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); 283 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 284 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 285 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 286 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 287 | // FBO texture for storing camera preview data(RGBA format) 288 | GLES20.glGenTextures(1, fboTexureId, 0); 289 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fboTexureId[0]); 290 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, textureWidth, textureHeight, 0, 291 | GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); 292 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 293 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 294 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); 295 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 296 | // Generate FBO and bind to FBO texture 297 | GLES20.glGenFramebuffers(1, fbo, 0); 298 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo[0]); 299 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, 300 | fboTexureId[0], 0); 301 | try { 302 | camera.setPreviewTexture(surfaceTexture); 303 | } catch (IOException exception) { 304 | Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 305 | } 306 | camera.startPreview(); 307 | } 308 | 309 | public void releaseCamera() { 310 | if (camera != null) { 311 | camera.setPreviewCallback(null); 312 | camera.stopPreview(); 313 | camera.release(); 314 | camera = null; 315 | } 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/common/Utils.java: -------------------------------------------------------------------------------- 1 | package com.baidu.common; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.hardware.Camera; 6 | import android.opengl.GLES20; 7 | import android.os.Environment; 8 | import android.util.Log; 9 | import android.view.Surface; 10 | import android.view.WindowManager; 11 | 12 | import java.io.BufferedInputStream; 13 | import java.io.BufferedOutputStream; 14 | import java.io.File; 15 | import java.io.FileNotFoundException; 16 | import java.io.FileOutputStream; 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.io.OutputStream; 20 | import java.util.List; 21 | 22 | public class Utils { 23 | private static final String TAG = Utils.class.getSimpleName(); 24 | 25 | public static void RecursiveCreateDirectories(String fileDir) { 26 | String[] fileDirs = fileDir.split("\\/"); 27 | String topPath = ""; 28 | for (int i = 0; i < fileDirs.length; i++) { 29 | topPath += "/" + fileDirs[i]; 30 | File file = new File(topPath); 31 | if (file.exists()) { 32 | continue; 33 | } else { 34 | file.mkdir(); 35 | } 36 | } 37 | } 38 | 39 | public static void copyFileFromAssets(Context appCtx, String srcPath, String dstPath) { 40 | if (srcPath.isEmpty() || dstPath.isEmpty()) { 41 | return; 42 | } 43 | String dstDir = dstPath.substring(0, dstPath.lastIndexOf('/')); 44 | if (dstDir.length() > 0) { 45 | RecursiveCreateDirectories(dstDir); 46 | } 47 | InputStream is = null; 48 | OutputStream os = null; 49 | try { 50 | is = new BufferedInputStream(appCtx.getAssets().open(srcPath)); 51 | os = new BufferedOutputStream(new FileOutputStream(new File(dstPath))); 52 | byte[] buffer = new byte[1024]; 53 | int length = 0; 54 | while ((length = is.read(buffer)) != -1) { 55 | os.write(buffer, 0, length); 56 | } 57 | } catch (FileNotFoundException e) { 58 | e.printStackTrace(); 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | } finally { 62 | try { 63 | os.close(); 64 | is.close(); 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } 68 | } 69 | } 70 | 71 | public static void copyDirectoryFromAssets(Context appCtx, String srcDir, String dstDir) { 72 | if (srcDir.isEmpty() || dstDir.isEmpty()) { 73 | return; 74 | } 75 | try { 76 | if (!new File(dstDir).exists()) { 77 | new File(dstDir).mkdirs(); 78 | } 79 | for (String fileName : appCtx.getAssets().list(srcDir)) { 80 | String srcSubPath = srcDir + File.separator + fileName; 81 | String dstSubPath = dstDir + File.separator + fileName; 82 | if (new File(srcSubPath).isDirectory()) { 83 | copyDirectoryFromAssets(appCtx, srcSubPath, dstSubPath); 84 | } else { 85 | copyFileFromAssets(appCtx, srcSubPath, dstSubPath); 86 | } 87 | } 88 | } catch (Exception e) { 89 | e.printStackTrace(); 90 | } 91 | } 92 | 93 | public static float[] parseFloatsFromString(String string, String delimiter) { 94 | String[] pieces = string.trim().toLowerCase().split(delimiter); 95 | float[] floats = new float[pieces.length]; 96 | for (int i = 0; i < pieces.length; i++) { 97 | floats[i] = Float.parseFloat(pieces[i].trim()); 98 | } 99 | return floats; 100 | } 101 | 102 | public static long[] parseLongsFromString(String string, String delimiter) { 103 | String[] pieces = string.trim().toLowerCase().split(delimiter); 104 | long[] longs = new long[pieces.length]; 105 | for (int i = 0; i < pieces.length; i++) { 106 | longs[i] = Long.parseLong(pieces[i].trim()); 107 | } 108 | return longs; 109 | } 110 | 111 | public static String getSDCardDirectory() { 112 | return Environment.getExternalStorageDirectory().getAbsolutePath(); 113 | } 114 | 115 | public static String getDCIMDirectory() { 116 | return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath(); 117 | } 118 | 119 | public static Camera.Size getOptimalPreviewSize(List sizes, int w, int h) { 120 | final double ASPECT_TOLERANCE = 0.1; 121 | double targetRatio = (double) w / h; 122 | if (sizes == null) return null; 123 | 124 | Camera.Size optimalSize = null; 125 | double minDiff = Double.MAX_VALUE; 126 | 127 | int targetHeight = h; 128 | 129 | // Try to find an size match aspect ratio and size 130 | for (Camera.Size size : sizes) { 131 | double ratio = (double) size.width / size.height; 132 | if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 133 | if (Math.abs(size.height - targetHeight) < minDiff) { 134 | optimalSize = size; 135 | minDiff = Math.abs(size.height - targetHeight); 136 | } 137 | } 138 | 139 | // Cannot find the one match the aspect ratio, ignore the requirement 140 | if (optimalSize == null) { 141 | minDiff = Double.MAX_VALUE; 142 | for (Camera.Size size : sizes) { 143 | if (Math.abs(size.height - targetHeight) < minDiff) { 144 | optimalSize = size; 145 | minDiff = Math.abs(size.height - targetHeight); 146 | } 147 | } 148 | } 149 | return optimalSize; 150 | } 151 | 152 | public static int getScreenWidth() { 153 | return Resources.getSystem().getDisplayMetrics().widthPixels; 154 | } 155 | 156 | public static int getScreenHeight() { 157 | return Resources.getSystem().getDisplayMetrics().heightPixels; 158 | } 159 | 160 | public static int getCameraDisplayOrientation(Context context, int cameraId) { 161 | Camera.CameraInfo info = new Camera.CameraInfo(); 162 | Camera.getCameraInfo(cameraId, info); 163 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 164 | int rotation = wm.getDefaultDisplay().getRotation(); 165 | int degrees = 0; 166 | switch (rotation) { 167 | case Surface.ROTATION_0: 168 | degrees = 0; 169 | break; 170 | case Surface.ROTATION_90: 171 | degrees = 90; 172 | break; 173 | case Surface.ROTATION_180: 174 | degrees = 180; 175 | break; 176 | case Surface.ROTATION_270: 177 | degrees = 270; 178 | break; 179 | } 180 | int result; 181 | if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 182 | result = (info.orientation + degrees) % 360; 183 | result = (360 - result) % 360; // compensate the mirror 184 | } else { 185 | // back-facing 186 | result = (info.orientation - degrees + 360) % 360; 187 | } 188 | return result; 189 | } 190 | 191 | public static int createShaderProgram(String vss, String fss) { 192 | int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); 193 | GLES20.glShaderSource(vshader, vss); 194 | GLES20.glCompileShader(vshader); 195 | int[] status = new int[1]; 196 | GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, status, 0); 197 | if (status[0] == 0) { 198 | Log.e(TAG, GLES20.glGetShaderInfoLog(vshader)); 199 | GLES20.glDeleteShader(vshader); 200 | vshader = 0; 201 | return 0; 202 | } 203 | 204 | int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); 205 | GLES20.glShaderSource(fshader, fss); 206 | GLES20.glCompileShader(fshader); 207 | GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, status, 0); 208 | if (status[0] == 0) { 209 | Log.e(TAG, GLES20.glGetShaderInfoLog(fshader)); 210 | GLES20.glDeleteShader(vshader); 211 | GLES20.glDeleteShader(fshader); 212 | fshader = 0; 213 | return 0; 214 | } 215 | 216 | int program = GLES20.glCreateProgram(); 217 | GLES20.glAttachShader(program, vshader); 218 | GLES20.glAttachShader(program, fshader); 219 | GLES20.glLinkProgram(program); 220 | GLES20.glDeleteShader(vshader); 221 | GLES20.glDeleteShader(fshader); 222 | GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0); 223 | if (status[0] == 0) { 224 | Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 225 | program = 0; 226 | return 0; 227 | } 228 | GLES20.glValidateProgram(program); 229 | GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, status, 0); 230 | if (status[0] == 0) { 231 | Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 232 | GLES20.glDeleteProgram(program); 233 | program = 0; 234 | return 0; 235 | } 236 | 237 | return program; 238 | } 239 | 240 | public static boolean isSupportedNPU() { 241 | String hardware = android.os.Build.HARDWARE; 242 | return hardware.equalsIgnoreCase("kirin810") || hardware.equalsIgnoreCase("kirin990"); 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/picodetncnn/CameraFragment.java: -------------------------------------------------------------------------------- 1 | package com.baidu.picodetncnn; 2 | 3 | import android.Manifest; 4 | import android.app.AlertDialog; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.content.SharedPreferences; 8 | import android.content.pm.PackageManager; 9 | import android.graphics.PixelFormat; 10 | import android.os.Bundle; 11 | import android.preference.PreferenceManager; 12 | import android.util.Log; 13 | import android.view.LayoutInflater; 14 | import android.view.SurfaceHolder; 15 | import android.view.SurfaceView; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.widget.AdapterView; 19 | import android.widget.Button; 20 | import android.widget.ImageButton; 21 | import android.widget.Spinner; 22 | import android.widget.TextView; 23 | import android.widget.Toast; 24 | 25 | import androidx.annotation.NonNull; 26 | import androidx.core.app.ActivityCompat; 27 | import androidx.core.content.ContextCompat; 28 | import androidx.fragment.app.Fragment; 29 | 30 | import com.baidu.common.CameraSurfaceView; 31 | import com.baidu.common.Utils; 32 | 33 | import java.io.File; 34 | import java.text.SimpleDateFormat; 35 | import java.util.Date; 36 | 37 | public class CameraFragment extends Fragment implements View.OnClickListener, SurfaceHolder.Callback { 38 | private static final String TAG = CameraFragment.class.getSimpleName(); 39 | 40 | private NanoDetNcnn nanodetncnn = new NanoDetNcnn(); 41 | private int facing = 1; 42 | 43 | // CameraSurfaceView svPreview; 44 | private SurfaceView cameraView; 45 | ImageButton btnSwitch; 46 | ImageButton btnShutter; 47 | ImageButton btnSettings; 48 | 49 | private Spinner spinnerModel; 50 | private Spinner spinnerCPUGPU; 51 | private int current_model = 0; 52 | private int current_cpugpu = 0; 53 | 54 | String savedImagePath = ""; 55 | int lastFrameIndex = 0; 56 | long lastFrameTime; 57 | 58 | 59 | @Override 60 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 61 | Bundle savedInstanceState) { 62 | // Inflate the layout for this fragment 63 | return inflater.inflate(R.layout.fragment_camera, container, false); 64 | } 65 | 66 | public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { 67 | super.onViewCreated(view, savedInstanceState); 68 | // Init the camera preview and UI components 69 | initView(view); 70 | // Check and request CAMERA and WRITE_EXTERNAL_STORAGE permissions 71 | if (!checkAllPermissions()) { 72 | requestAllPermissions(); 73 | } 74 | } 75 | 76 | @Override 77 | public void onClick(View v) { 78 | switch (v.getId()) { 79 | case R.id.btn_switch: 80 | int new_facing = 1 - facing; 81 | nanodetncnn.closeCamera(); 82 | nanodetncnn.openCamera(new_facing); 83 | facing = new_facing; 84 | break; 85 | case R.id.btn_shutter: 86 | SimpleDateFormat date = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); 87 | synchronized (this) { 88 | savedImagePath = Utils.getDCIMDirectory() + File.separator + date.format(new Date()).toString() + ".png"; 89 | } 90 | Toast.makeText(getActivity(), "Save snapshot to " + savedImagePath, Toast.LENGTH_SHORT).show(); 91 | break; 92 | } 93 | } 94 | 95 | @Override 96 | public void onResume() { 97 | super.onResume(); 98 | nanodetncnn.openCamera(facing); 99 | } 100 | 101 | @Override 102 | public void onPause() { 103 | super.onPause(); 104 | nanodetncnn.closeCamera(); 105 | } 106 | 107 | @Override 108 | public void onDestroy() { 109 | 110 | super.onDestroy(); 111 | } 112 | 113 | public void initView(@NonNull View view) { 114 | // svPreview = (CameraSurfaceView) view.findViewById(R.id.sv_preview); 115 | cameraView = (SurfaceView) view.findViewById(R.id.sv_preview); 116 | cameraView.getHolder().setFormat(PixelFormat.RGBA_8888); 117 | cameraView.getHolder().addCallback(this); 118 | 119 | btnSwitch = (ImageButton) view.findViewById(R.id.btn_switch); 120 | btnSwitch.setOnClickListener(this); 121 | btnShutter = (ImageButton) view.findViewById(R.id.btn_shutter); 122 | btnShutter.setOnClickListener(this); 123 | btnSettings = (ImageButton) view.findViewById(R.id.btn_settings); 124 | btnSettings.setOnClickListener(this); 125 | 126 | spinnerModel = (Spinner) view.findViewById(R.id.spinnerModel); 127 | spinnerModel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 128 | @Override 129 | public void onItemSelected(AdapterView arg0, View arg1, int position, long id) 130 | { 131 | if (position != current_model) 132 | { 133 | current_model = position; 134 | System.out.println("current_model => "+current_model); 135 | reload(); 136 | } 137 | } 138 | 139 | @Override 140 | public void onNothingSelected(AdapterView arg0) 141 | { 142 | } 143 | }); 144 | 145 | spinnerCPUGPU = (Spinner) view.findViewById(R.id.spinnerCPUGPU); 146 | spinnerCPUGPU.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 147 | @Override 148 | public void onItemSelected(AdapterView arg0, View arg1, int position, long id) 149 | { 150 | if (position != current_cpugpu) 151 | { 152 | current_cpugpu = position; 153 | reload(); 154 | } 155 | } 156 | 157 | @Override 158 | public void onNothingSelected(AdapterView arg0) 159 | { 160 | } 161 | }); 162 | 163 | reload(); 164 | } 165 | 166 | private void reload() 167 | { 168 | boolean ret_init = nanodetncnn.loadModel(getActivity().getAssets(), current_model, current_cpugpu); 169 | if (!ret_init) 170 | { 171 | Toast.makeText(getActivity(),"切换模型失败",Toast.LENGTH_LONG).show(); 172 | Log.e("camera", "ncnn loadModel failed"); 173 | }else{ 174 | Toast.makeText(getActivity(),"切换模型成功",Toast.LENGTH_LONG).show(); 175 | } 176 | } 177 | 178 | @Override 179 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 180 | @NonNull int[] grantResults) { 181 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 182 | if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) { 183 | new AlertDialog.Builder(getActivity()) 184 | .setTitle("Permission denied") 185 | .setMessage("Click to force quit the app, then open Settings->Apps & notifications->Target " + 186 | "App->Permissions to grant all of the permissions.") 187 | .setCancelable(false) 188 | .setPositiveButton("Exit", new DialogInterface.OnClickListener() { 189 | @Override 190 | public void onClick(DialogInterface dialog, int which) { 191 | getActivity().finish(); 192 | } 193 | }).show(); 194 | } 195 | } 196 | 197 | private void requestAllPermissions() { 198 | ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, 199 | Manifest.permission.CAMERA}, 0); 200 | } 201 | 202 | private boolean checkAllPermissions() { 203 | return ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED 204 | && ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; 205 | } 206 | 207 | @Override 208 | public void surfaceCreated(@NonNull SurfaceHolder holder) { 209 | nanodetncnn.setOutputWindow(holder.getSurface()); 210 | } 211 | 212 | @Override 213 | public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { 214 | 215 | } 216 | 217 | @Override 218 | public void surfaceDestroyed(@NonNull SurfaceHolder holder) { 219 | 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/picodetncnn/ContentFragment.java: -------------------------------------------------------------------------------- 1 | package com.baidu.picodetncnn; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.fragment.app.Fragment; 10 | import androidx.navigation.fragment.NavHostFragment; 11 | 12 | public class ContentFragment extends Fragment { 13 | 14 | @Override 15 | public View onCreateView( 16 | LayoutInflater inflater, ViewGroup container, 17 | Bundle savedInstanceState 18 | ) { 19 | // Inflate the layout for this fragment 20 | return inflater.inflate(R.layout.fragment_content, container, false); 21 | } 22 | 23 | public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { 24 | super.onViewCreated(view, savedInstanceState); 25 | 26 | view.findViewById(R.id.camera).setOnClickListener(new View.OnClickListener() { 27 | @Override 28 | public void onClick(View view) { 29 | NavHostFragment.findNavController(ContentFragment.this) 30 | .navigate(R.id.action_ContentFragment_to_CameraFragment); 31 | 32 | } 33 | }); 34 | 35 | view.findViewById(R.id.photo).setOnClickListener(new View.OnClickListener() { 36 | @Override 37 | public void onClick(View view) { 38 | NavHostFragment.findNavController(ContentFragment.this) 39 | .navigate(R.id.action_ContentFragment_to_PhotoFragment); 40 | } 41 | }); 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/picodetncnn/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.baidu.picodetncnn; 2 | 3 | import android.os.Bundle; 4 | import android.view.Menu; 5 | import android.view.MenuItem; 6 | 7 | import androidx.appcompat.app.AppCompatActivity; 8 | import androidx.appcompat.widget.Toolbar; 9 | 10 | import com.google.android.material.navigation.NavigationView; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | private NavigationView navigationView; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_main); 19 | Toolbar toolbar = findViewById(R.id.toolbar); 20 | setSupportActionBar(toolbar); 21 | 22 | } 23 | 24 | @Override 25 | public boolean onCreateOptionsMenu(Menu menu) { 26 | // Inflate the menu; this adds items to the action bar if it is present. 27 | getMenuInflater().inflate(R.menu.menu_main, menu); 28 | return true; 29 | } 30 | 31 | @Override 32 | public boolean onOptionsItemSelected(MenuItem item) { 33 | // Handle action bar item clicks here. The action bar will 34 | // automatically handle clicks on the Home/Up button, so long 35 | // as you specify a parent activity in AndroidManifest.xml. 36 | int id = item.getItemId(); 37 | 38 | //noinspection SimplifiableIfStatement 39 | if (id == R.id.action_settings) { 40 | return true; 41 | } 42 | 43 | return super.onOptionsItemSelected(item); 44 | } 45 | } -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/picodetncnn/NanoDetNcnn.java: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | package com.baidu.picodetncnn; 16 | 17 | import android.content.res.AssetManager; 18 | import android.view.Surface; 19 | 20 | public class NanoDetNcnn 21 | { 22 | public native boolean loadModel(AssetManager mgr, int modelid, int cpugpu); 23 | public native boolean openCamera(int facing); 24 | public native boolean closeCamera(); 25 | public native boolean setOutputWindow(Surface surface); 26 | public native double testInferTime(AssetManager mgr, int modelid, int cpugpu); 27 | 28 | public native boolean genVideoByImg(); 29 | 30 | static { 31 | System.loadLibrary("picodetncnn"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/baidu/picodetncnn/PhotoFragment.java: -------------------------------------------------------------------------------- 1 | package com.baidu.picodetncnn; 2 | 3 | import android.app.ProgressDialog; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.HandlerThread; 9 | import android.os.Message; 10 | import android.util.Log; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.AdapterView; 15 | import android.widget.ImageView; 16 | import android.widget.Spinner; 17 | import android.widget.TextView; 18 | import android.widget.Toast; 19 | 20 | import androidx.annotation.NonNull; 21 | import androidx.fragment.app.Fragment; 22 | 23 | import java.io.File; 24 | import java.io.FileOutputStream; 25 | import java.io.InputStream; 26 | import java.text.DecimalFormat; 27 | 28 | 29 | public class PhotoFragment extends Fragment { 30 | 31 | String video_file = "out.mp4"; 32 | // String video_file = "test3.mp4"; 33 | 34 | private static final String TAG = PhotoFragment.class.getSimpleName(); 35 | private Spinner spinnerModel; 36 | private Spinner spinnerCPUGPU; 37 | NanoDetNcnn nanoDetNcnn = new NanoDetNcnn(); 38 | private int current_model = 0; 39 | private int current_cpugpu = 0; 40 | ImageView inferImageView; 41 | TextView fpsTextView; 42 | int count = 0; 43 | int frameCount = 249; 44 | // int frameCount = 630; 45 | boolean isRunThread = true; 46 | 47 | ProgressDialog dialog = null; 48 | protected Handler sender = null; // Send command to worker thread 49 | public static final int REQUEST_RUN_MODEL = 0; 50 | public static final int RESPONSE_RUN_MODEL_SUCCESSED = 2; 51 | public static final int RESPONSE_RUN_MODEL_FAILED = 3; 52 | protected HandlerThread worker = null; // Worker thread to load&run model 53 | public Handler receiver = null; // Receive messages from worker thread 54 | 55 | 56 | @Override 57 | public View onCreateView( 58 | LayoutInflater inflater, ViewGroup container, 59 | Bundle savedInstanceState 60 | ) { 61 | // Inflate the layout for this fragment 62 | return inflater.inflate(R.layout.fragment_photo, container, false); 63 | } 64 | 65 | public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { 66 | super.onViewCreated(view, savedInstanceState); 67 | initView(view); 68 | start_run_model(); 69 | } 70 | 71 | public void start_run_model(){ 72 | dialog = ProgressDialog.show(getActivity(), "", "Running, please wait...", false, false); 73 | sender.sendEmptyMessage(REQUEST_RUN_MODEL); 74 | } 75 | 76 | public boolean run_detect_video(){ 77 | 78 | isRunThread = false; 79 | double inferTime = nanoDetNcnn.testInferTime(getActivity().getAssets(), current_model, current_cpugpu); 80 | double fps = frameCount*1000/inferTime; 81 | DecimalFormat decimalFormat = new DecimalFormat("#.00"); 82 | String fpsStr = decimalFormat.format(fps); 83 | fpsTextView.setText("FPS: "+fpsStr); 84 | isRunThread = true; 85 | getShowImgThread().start(); 86 | return true; 87 | } 88 | 89 | public void initView(@NonNull View view) { 90 | spinnerModel = (Spinner) view.findViewById(R.id.spinnerModel_1); 91 | spinnerCPUGPU = (Spinner) view.findViewById(R.id.spinnerCPUGPU_1); 92 | inferImageView = view.findViewById(R.id.showInferImg); 93 | fpsTextView = view.findViewById(R.id.fpsTextView); 94 | System.out.println("ncnn: copyMP42Cache"); 95 | copyMP42Cache(); 96 | 97 | spinnerModel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 98 | @Override 99 | public void onItemSelected(AdapterView arg0, View arg1, int position, long id) 100 | { 101 | if (position != current_model) 102 | { 103 | isRunThread = false; 104 | current_model = position; 105 | System.out.println("current_model => "+current_model); 106 | try{ 107 | isRunThread = false; 108 | }catch (Exception e){ 109 | Log.d("ncnn: ", "stop thread ..."); 110 | } 111 | 112 | start_run_model(); 113 | } 114 | } 115 | 116 | @Override 117 | public void onNothingSelected(AdapterView arg0) 118 | { 119 | } 120 | }); 121 | // 切换cpu/gpu 122 | spinnerCPUGPU.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 123 | @Override 124 | public void onItemSelected(AdapterView arg0, View arg1, int position, long id) 125 | { 126 | if (position != current_cpugpu) 127 | { 128 | current_cpugpu = position; 129 | System.out.println("current_model => "+current_model); 130 | try{ 131 | isRunThread = false; 132 | }catch (Exception e){ 133 | Log.d("ncnn: ", "stop thread ..."); 134 | } 135 | 136 | start_run_model(); 137 | } 138 | } 139 | 140 | @Override 141 | public void onNothingSelected(AdapterView arg0) 142 | { 143 | } 144 | }); 145 | 146 | receiver = new Handler() { 147 | @Override 148 | public void handleMessage(Message msg) { 149 | switch (msg.what) { 150 | case RESPONSE_RUN_MODEL_SUCCESSED: 151 | dialog.dismiss(); 152 | break; 153 | case RESPONSE_RUN_MODEL_FAILED: 154 | dialog.dismiss(); 155 | Toast.makeText(getActivity(), "Run model failed!", Toast.LENGTH_SHORT).show(); 156 | break; 157 | default: 158 | break; 159 | } 160 | } 161 | }; 162 | 163 | 164 | worker = new HandlerThread("Predictor Worker"); 165 | worker.start(); 166 | sender = new Handler(worker.getLooper()) { 167 | public void handleMessage(Message msg) { 168 | switch (msg.what) { 169 | case REQUEST_RUN_MODEL: 170 | // Run model if model is loaded 171 | if (run_detect_video()) { 172 | receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_SUCCESSED); 173 | } else { 174 | receiver.sendEmptyMessage(RESPONSE_RUN_MODEL_FAILED); 175 | } 176 | break; 177 | default: 178 | break; 179 | } 180 | } 181 | }; 182 | 183 | } 184 | 185 | public Thread getShowImgThread(){ 186 | return new Thread(new Runnable() { 187 | @Override 188 | public void run() { 189 | File fileDir = new File(getActivity().getExternalCacheDir()+""); 190 | Log.e("ncnn:","file path =>"+fileDir.getAbsolutePath()); 191 | while(isRunThread){ 192 | try { 193 | final String imageName = fileDir.list()[count%frameCount]; 194 | count ++; 195 | if(imageName.contains(".jpg")){ 196 | getActivity().runOnUiThread(new Runnable() { 197 | @Override 198 | public void run() { 199 | Bitmap bitmap = BitmapFactory.decodeFile(getActivity().getExternalCacheDir() +"/"+imageName); 200 | inferImageView.setImageBitmap(bitmap); 201 | // inferImageView.setRotation(90); 202 | } 203 | }); 204 | } 205 | Thread.sleep(50); 206 | } catch (Exception e) { 207 | e.printStackTrace(); 208 | } 209 | } 210 | 211 | } 212 | }); 213 | 214 | } 215 | 216 | public void copyMP42Cache() { 217 | File file = new File(getActivity().getExternalCacheDir()+"/"+video_file); 218 | Log.e("ncnn: src video dir => ", file.getAbsolutePath()); 219 | if (!file.exists()) { 220 | try { 221 | InputStream is = getActivity().getAssets().open(video_file); 222 | int size = is.available(); 223 | byte[] buffer = new byte[size]; 224 | is.read(buffer); 225 | is.close(); 226 | FileOutputStream fos = new FileOutputStream(file); 227 | fos.write(buffer); 228 | fos.close(); 229 | } catch (Exception e) { 230 | Log.e("***************ncnn: copy src file to dst file failed => ", file.getAbsolutePath()); 231 | throw new RuntimeException(e); 232 | } 233 | } else { 234 | Log.e("*******************ncnn: dst file exist => ", file.getAbsolutePath()); 235 | } 236 | } 237 | 238 | @Override 239 | public void onResume() { 240 | super.onResume(); 241 | } 242 | 243 | @Override 244 | public void onDestroy() { 245 | super.onDestroy(); 246 | } 247 | } -------------------------------------------------------------------------------- /app/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #project(picodetncnn) 2 | #cmake_minimum_required(VERSION 3.10) 3 | #set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni) 4 | ##set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/aaa/sdk/native/jni) 5 | ##set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv-mobile-4.5.3-android/sdk/native/jni) 6 | ##set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni) 7 | ## jiwei 8 | ##include_directories(${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni/include) 9 | #find_package(OpenCV REQUIRED core imgproc highgui) 10 | #set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn-20210720-android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn) 11 | #find_package(ncnn REQUIRED) 12 | #add_library(picodetncnn SHARED nanodetncnn.cpp nanodet.cpp ndkcamera.cpp) 13 | #target_link_libraries(picodetncnn ncnn ${OpenCV_LIBS} camera2ndk mediandk) 14 | 15 | 16 | 17 | 18 | #project(picodetncnn) 19 | ##include(ndk-stl-config.cmake) 20 | #cmake_minimum_required(VERSION 3.10) 21 | # 22 | ## add name==picodetncnn, source file can be denoted 23 | #include_directories(${CMAKE_SOURCE_DIR}/opencv/native/jni/include) 24 | ##add_library(lib_opencv SHARED IMPORTED) 25 | ##set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/opencv/native/libs/${ANDROID_ABI}/libopencv_java4.so) 26 | # 27 | ## ncnn 28 | #set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn-20210720-android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn) 29 | #find_package(ncnn REQUIRED) 30 | # 31 | ## picodetncnn 32 | #add_library(picodetncnn SHARED nanodetncnn.cpp nanodet.cpp ndkcamera.cpp) 33 | ## 被依赖的库放在依赖的库后面 34 | ##target_link_libraries(picodetncnn ncnn camera2ndk mediandk lib_opencv) 35 | # 36 | #target_link_libraries(picodetncnn ncnn camera2ndk mediandk) 37 | # 38 | # 39 | # 40 | # 41 | # 42 | 43 | project(picodetncnn) 44 | cmake_minimum_required(VERSION 3.10) 45 | 46 | set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni) 47 | #set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/OpenCV-android-sdk/sdk/native/jni) 48 | #find_package(OpenCV REQUIRED core imgproc video videoio highgui) 49 | find_package(OpenCV REQUIRED) 50 | 51 | set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn-20210720-android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn) 52 | find_package(ncnn REQUIRED) 53 | add_library(picodetncnn SHARED nanodetncnn.cpp nanodet.cpp ndkcamera.cpp) 54 | target_link_libraries(picodetncnn ncnn ${OpenCV_LIBS} camera2ndk mediandk) -------------------------------------------------------------------------------- /app/src/main/jni/nanodet.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NANODET_H 16 | #define NANODET_H 17 | 18 | #include 19 | 20 | #include 21 | 22 | 23 | struct Object 24 | { 25 | cv::Rect_ rect; 26 | int label; 27 | float prob; 28 | //yolov5 29 | float x; 30 | float y; 31 | float w; 32 | float h; 33 | // int label; 34 | // float prob; 35 | }; 36 | 37 | class NanoDet 38 | { 39 | public: 40 | NanoDet(); 41 | 42 | int load(const char* modeltype, int target_size, const float* mean_vals, const float* norm_vals, bool use_gpu = false); 43 | 44 | int load(AAssetManager* mgr, const char* modeltype, int target_size, const float* mean_vals, const float* norm_vals, bool use_gpu = false); 45 | 46 | int detect(const cv::Mat& rgb, std::vector& objects, float prob_threshold = 0.5f, float nms_threshold = 0.5f); 47 | 48 | int draw(cv::Mat& rgb, const std::vector& objects); 49 | 50 | int detectPicoDet(const cv::Mat& rgb, std::vector& objects, float prob_threshold = 0.3f, float nms_threshold = 0.5f); 51 | 52 | int detectPicoDetFourHead(const cv::Mat& rgb, std::vector& objects, float prob_threshold = 0.3f, float nms_threshold = 0.5f); 53 | 54 | int detectYolox(const cv::Mat& rgb, std::vector& objects, float prob_threshold = 0.4f, float nms_threshold = 0.5f); 55 | 56 | int detectYoloV5(const cv::Mat& rgb, std::vector& objects, float prob_threshold = 0.3f, float nms_threshold = 0.5f); 57 | 58 | int mode_type = -1; 59 | 60 | double preprocess_time_picodet = 0; 61 | double postprocess_time_picodet = 0; 62 | double infer_time_picodet = 0; 63 | 64 | double preprocess_time_ = 0; 65 | double postprocess_time_ = 0; 66 | double infer_time_ = 0; 67 | 68 | 69 | private: 70 | ncnn::Net nanodet; 71 | int target_size; 72 | float mean_vals[3]; 73 | float norm_vals[3]; 74 | ncnn::UnlockedPoolAllocator blob_pool_allocator; 75 | ncnn::PoolAllocator workspace_pool_allocator; 76 | 77 | 78 | }; 79 | 80 | #endif // NANODET_H 81 | -------------------------------------------------------------------------------- /app/src/main/jni/nanodetncnn.cpp: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "nanodet.h" 26 | #include "ndkcamera.h" 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | void delay(int time){ 36 | // clock_t now = ncnn:getc(); 37 | // while(clock() - now < time); 38 | double now = ncnn::get_current_time(); 39 | while(ncnn::get_current_time() - now < time); 40 | 41 | } 42 | 43 | #if __ARM_NEON 44 | #include 45 | #endif // __ARM_NEON 46 | 47 | #define fps_length 60 48 | 49 | #define mylog(...) __android_log_print 50 | using namespace cv; 51 | static int draw_unsupported(cv::Mat& rgb) 52 | { 53 | const char text[] = "unsupported"; 54 | 55 | int baseLine = 0; 56 | cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 1.0, 1, &baseLine); 57 | 58 | int y = (rgb.rows - label_size.height) / 2; 59 | int x = (rgb.cols - label_size.width) / 2; 60 | 61 | cv::rectangle(rgb, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)), 62 | cv::Scalar(255, 255, 255), -1); 63 | 64 | cv::putText(rgb, text, cv::Point(x, y + label_size.height), 65 | cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0, 0, 0)); 66 | 67 | return 0; 68 | } 69 | 70 | static float fps_history[fps_length] = {0.f}; 71 | 72 | //float prob_threshold = 0.3; 73 | //float nms_threshold = 0.3; 74 | 75 | static void clear_Fps_History(){ 76 | for(int i=0; i= 1; i--) 99 | { 100 | fps_history[i] = fps_history[i - 1]; 101 | } 102 | fps_history[0] = fps; 103 | 104 | if (fps_history[fps_length-1] == 0.f) 105 | { 106 | return 0; 107 | } 108 | 109 | for (int i = 0; i < fps_length; i++) 110 | { 111 | avg_fps += fps_history[i]; 112 | } 113 | avg_fps /= fps_length; 114 | } 115 | 116 | char text[32]; 117 | sprintf(text, "FPS=%.2f", avg_fps); 118 | 119 | int baseLine = 0; 120 | cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); 121 | 122 | int y = 0; 123 | int x = rgb.cols - label_size.width; 124 | 125 | cv::rectangle(rgb, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)), 126 | cv::Scalar(255, 255, 255), -1); 127 | 128 | cv::putText(rgb, text, cv::Point(x, y + label_size.height), 129 | cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0)); 130 | 131 | return 0; 132 | } 133 | 134 | 135 | static NanoDet* g_nanodet = 0; 136 | static ncnn::Mutex lock; 137 | 138 | class MyNdkCamera : public NdkCameraWindow 139 | { 140 | public: 141 | virtual void on_image_render(cv::Mat& rgb) const; 142 | }; 143 | 144 | void MyNdkCamera::on_image_render(cv::Mat& rgb) const 145 | { 146 | // nanodet 147 | { 148 | ncnn::MutexLockGuard g(lock); 149 | if (g_nanodet) 150 | { 151 | std::vector objects; 152 | if(g_nanodet->mode_type == 0){ 153 | g_nanodet->detectPicoDetFourHead(rgb, objects, 0.45,0.55); 154 | } 155 | if(g_nanodet->mode_type == 1){ 156 | // g_nanodet->detectPicoDet(rgb, objects); 157 | g_nanodet->detectPicoDetFourHead(rgb, objects, 0.45,0.55); 158 | } 159 | if(g_nanodet->mode_type == 2){ 160 | g_nanodet->detect(rgb, objects); 161 | 162 | } 163 | if(g_nanodet->mode_type == 3){ 164 | g_nanodet->detectYolox(rgb, objects); 165 | } 166 | if(g_nanodet->mode_type == 4){ 167 | g_nanodet->detectYoloV5(rgb, objects); 168 | } 169 | g_nanodet->draw(rgb, objects); 170 | } 171 | else 172 | { 173 | draw_unsupported(rgb); 174 | } 175 | } 176 | double process_time = g_nanodet->preprocess_time_; 177 | double infer_time = g_nanodet->infer_time_; 178 | double postprocess_time = g_nanodet->postprocess_time_; 179 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: process_time:", "%lf", process_time); 180 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: infer_time:", "%lf", infer_time); 181 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: postprocess_time:", "%lf", postprocess_time); 182 | double all_time = process_time + infer_time + postprocess_time; 183 | 184 | draw_fps(rgb, all_time); 185 | } 186 | // 无法生成图片,可能和opencv的有关 187 | void genVideoByImg(){ 188 | // /storage/emulated/0/Android/data/com.baidu.picodetncnn/cache/out_infer.avi 189 | VideoWriter videoWriter("out_infer.avi", 190 | CV_FOURCC('M', 'J', 'P', 'G'), 191 | 10.0, Size(640, 640)); 192 | for(int frameNum=1;frameNum<61;frameNum++){ 193 | char imgName[100] = {}; 194 | sprintf(imgName,"/storage/emulated/0/Android/data/com.baidu.picodetncnn/cache/%d.jpg",frameNum); 195 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: images","%s", imgName); 196 | cv::Mat img = imread(imgName); 197 | videoWriter<>rgb_out; 221 | if(rgb_out.empty()){ 222 | break; 223 | } 224 | cv::transpose(rgb_out, rgb_in); 225 | cvtColor(rgb_in, rgb, COLOR_BGR2RGB); 226 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: frame number", "%d", frameNum); 227 | char imgName[1000] = {}; 228 | if (g_nanodet) { 229 | std::vector objects; 230 | if (g_nanodet->mode_type == 0) { 231 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "%s","picodet-four"); 232 | read_img_time = read_img_time + (ncnn::get_current_time() - time_idx); 233 | time_idx = ncnn::get_current_time(); 234 | g_nanodet->detectPicoDetFourHead(rgb, objects, 0.45,0.5); 235 | detect_time = detect_time + (ncnn::get_current_time()-time_idx); 236 | objectsNum = objectsNum + objects.size(); 237 | time_idx = ncnn::get_current_time(); 238 | g_nanodet->draw(rgb, objects); 239 | draw_img_time = draw_img_time + (ncnn::get_current_time()-time_idx); 240 | } 241 | if (g_nanodet->mode_type == 1) { // picodet three head 242 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "%s","picodet-four"); 243 | read_img_time = read_img_time + (ncnn::get_current_time() - time_idx); 244 | time_idx = ncnn::get_current_time(); 245 | g_nanodet->detectPicoDetFourHead(rgb, objects, 0.45,0.5); 246 | detect_time = detect_time + (ncnn::get_current_time()-time_idx); 247 | objectsNum = objectsNum + objects.size(); 248 | time_idx = ncnn::get_current_time(); 249 | g_nanodet->draw(rgb, objects); 250 | draw_img_time = draw_img_time + (ncnn::get_current_time()-time_idx); 251 | } 252 | if (g_nanodet->mode_type == 2) { // pciodet four head 253 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "%s","nanodet"); 254 | read_img_time = read_img_time + (ncnn::get_current_time() - time_idx); 255 | time_idx = ncnn::get_current_time(); 256 | g_nanodet->detect(rgb, objects); 257 | detect_time = detect_time + (ncnn::get_current_time()-time_idx); 258 | objectsNum = objectsNum + objects.size(); 259 | time_idx = ncnn::get_current_time(); 260 | g_nanodet->draw(rgb, objects); 261 | draw_img_time = draw_img_time + (ncnn::get_current_time()-time_idx); 262 | } 263 | if (g_nanodet->mode_type == 3) { 264 | read_img_time = read_img_time + (ncnn::get_current_time() - time_idx); 265 | time_idx = ncnn::get_current_time(); 266 | g_nanodet->detectYolox(rgb, objects); 267 | detect_time = detect_time + (ncnn::get_current_time()-time_idx); 268 | objectsNum = objectsNum + objects.size(); 269 | time_idx = ncnn::get_current_time(); 270 | g_nanodet->draw(rgb, objects); 271 | draw_img_time = draw_img_time + (ncnn::get_current_time()-time_idx); 272 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "%s","yolox"); 273 | } 274 | if (g_nanodet->mode_type == 4) { 275 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "%s","detectYoloV5"); 276 | read_img_time = read_img_time + (ncnn::get_current_time() - time_idx); 277 | time_idx = ncnn::get_current_time(); 278 | g_nanodet->detectYoloV5(rgb, objects); 279 | detect_time = detect_time + (ncnn::get_current_time()-time_idx); 280 | objectsNum = objectsNum + objects.size(); 281 | time_idx = ncnn::get_current_time(); 282 | g_nanodet->draw(rgb, objects); 283 | draw_img_time = draw_img_time + (ncnn::get_current_time()-time_idx); 284 | } 285 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "object length = %d",objects.size()); 286 | 287 | } 288 | 289 | time_idx = ncnn::get_current_time(); 290 | sprintf(imgName,"/storage/emulated/0/Android/data/com.baidu.picodetncnn/cache/%d.jpg",frameNum); 291 | cv::imwrite(imgName, rgb); 292 | imwrite_time = imwrite_time + (ncnn::get_current_time() - time_idx); 293 | } 294 | double stop_time = ncnn::get_current_time(); 295 | return stop_time-start_time; 296 | } 297 | 298 | static MyNdkCamera* g_camera = 0; 299 | 300 | extern "C" { 301 | 302 | JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) 303 | { 304 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "JNI_OnLoad"); 305 | 306 | g_camera = new MyNdkCamera; 307 | 308 | return JNI_VERSION_1_4; 309 | } 310 | 311 | JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) 312 | { 313 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn:", "JNI_OnUnload"); 314 | 315 | { 316 | ncnn::MutexLockGuard g(lock); 317 | delete g_nanodet; 318 | g_nanodet = 0; 319 | } 320 | delete g_camera; 321 | g_camera = 0; 322 | } 323 | 324 | // public native boolean loadModel(AssetManager mgr, int modelid, int cpugpu); 325 | JNIEXPORT jboolean JNICALL Java_com_baidu_picodetncnn_NanoDetNcnn_loadModel(JNIEnv* env, jobject thiz, jobject assetManager, jint modelid, jint cpugpu) 326 | { 327 | int curent_model = -1; 328 | if (modelid < 0 || modelid > 5 || cpugpu < 0 || cpugpu > 1) 329 | { 330 | return JNI_FALSE; 331 | } 332 | if(modelid == 0){ 333 | curent_model = 0; 334 | } 335 | if(modelid == 1){ 336 | curent_model = 1; 337 | } 338 | if(modelid == 2){ 339 | curent_model = 2; 340 | } 341 | if(modelid == 3){ 342 | curent_model = 3; 343 | } 344 | if(modelid == 4){ 345 | curent_model = 4; 346 | } 347 | AAssetManager* mgr = AAssetManager_fromJava(env, assetManager); 348 | const char* modeltypes[] = 349 | { 350 | "picodet-s-416", 351 | "picodet-l-640", 352 | "nanodet-m-416", 353 | "yolox-nano", 354 | "yolov5s", 355 | }; 356 | const int target_sizes[] = 357 | { 358 | 416, 359 | 640, 360 | 416, 361 | 416, 362 | 640, 363 | }; 364 | const float mean_vals[][3] = 365 | { 366 | {103.53f, 116.28f, 123.675f}, 367 | {103.53f, 116.28f, 123.675f}, 368 | {103.53f, 116.28f, 123.675f}, 369 | {103.53f, 116.28f, 123.675f}, 370 | {103.53f, 116.28f, 123.675f} 371 | }; 372 | const float norm_vals[][3] = 373 | { 374 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 375 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 376 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 377 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 378 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f} 379 | }; 380 | const char* modeltype = modeltypes[(int)modelid]; 381 | int target_size = target_sizes[(int)modelid]; 382 | bool use_gpu = (int)cpugpu == 1; 383 | // reload 384 | { 385 | ncnn::MutexLockGuard g(lock); 386 | if (use_gpu && ncnn::get_gpu_count() == 0) 387 | { 388 | // no gpu 389 | delete g_nanodet; 390 | g_nanodet = 0; 391 | } 392 | else 393 | { 394 | if (!g_nanodet) 395 | g_nanodet = new NanoDet; 396 | g_nanodet->mode_type = curent_model; 397 | g_nanodet->load(mgr, modeltype, target_size, mean_vals[(int)modelid], norm_vals[(int)modelid], use_gpu); 398 | } 399 | } 400 | clear_Fps_History(); 401 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: current use model", "%s", modeltypes[g_nanodet->mode_type]); 402 | return JNI_TRUE; 403 | } 404 | 405 | // public native boolean openCamera(int facing); 406 | JNIEXPORT jboolean JNICALL Java_com_baidu_picodetncnn_NanoDetNcnn_openCamera(JNIEnv* env, jobject thiz, jint facing) 407 | { 408 | if (facing < 0 || facing > 1) 409 | return JNI_FALSE; 410 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn", "openCamera %d", facing); 411 | g_camera->open((int)facing); 412 | return JNI_TRUE; 413 | } 414 | 415 | // public native boolean closeCamera(); 416 | JNIEXPORT jboolean JNICALL Java_com_baidu_picodetncnn_NanoDetNcnn_closeCamera(JNIEnv* env, jobject thiz) 417 | { 418 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn", "closeCamera"); 419 | g_camera->close(); 420 | return JNI_TRUE; 421 | } 422 | 423 | // public native boolean setOutputWindow(Surface surface); 424 | JNIEXPORT jboolean JNICALL Java_com_baidu_picodetncnn_NanoDetNcnn_setOutputWindow(JNIEnv* env, jobject thiz, jobject surface) 425 | { 426 | ANativeWindow* win = ANativeWindow_fromSurface(env, surface); 427 | 428 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn", "setOutputWindow %p", win); 429 | 430 | g_camera->set_window(win); 431 | 432 | return JNI_TRUE; 433 | } 434 | 435 | JNIEXPORT jdouble JNICALL Java_com_baidu_picodetncnn_NanoDetNcnn_testInferTime(JNIEnv *env, jobject thiz, jobject assetManager, jint modelid, jint cpugpu) { 436 | int curent_model = -1; 437 | if (modelid < 0 || modelid > 5 || cpugpu < 0 || cpugpu > 1) 438 | { 439 | return JNI_FALSE; 440 | } 441 | if(modelid == 0){ 442 | curent_model = 0; 443 | } 444 | if(modelid == 1){ 445 | curent_model = 1; 446 | } 447 | if(modelid == 2){ 448 | curent_model = 2; 449 | } 450 | if(modelid == 3){ 451 | curent_model = 3; 452 | } 453 | if(modelid == 4){ 454 | curent_model = 4; 455 | } 456 | const char* modeltypes[] = 457 | { 458 | "picodet-s-416", 459 | "picodet-l-640", 460 | "nanodet-m-416", 461 | "yolox-nano", 462 | "yolov5s", 463 | }; 464 | 465 | // const int target_sizes[] ={320,320,320,320,320}; 466 | const int target_sizes[] = 467 | { 468 | 416, 469 | 640, 470 | 416, 471 | 416, 472 | 640, 473 | }; 474 | 475 | const float mean_vals[][3] = 476 | { 477 | {103.53f, 116.28f, 123.675f}, 478 | {103.53f, 116.28f, 123.675f}, 479 | {103.53f, 116.28f, 123.675f}, 480 | {103.53f, 116.28f, 123.675f}, 481 | {103.53f, 116.28f, 123.675f} 482 | }; 483 | 484 | const float norm_vals[][3] = 485 | { 486 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 487 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 488 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 489 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f}, 490 | {1.f / 57.375f, 1.f / 57.12f, 1.f / 58.395f} 491 | }; 492 | AAssetManager* mgr = AAssetManager_fromJava(env, assetManager); 493 | const char* modeltype = modeltypes[(int)modelid]; 494 | int target_size = target_sizes[(int)modelid]; 495 | bool use_gpu = (int)cpugpu == 1; 496 | // reload 497 | { 498 | ncnn::MutexLockGuard g(lock); 499 | if (use_gpu && ncnn::get_gpu_count() == 0) 500 | { 501 | // no gpu 502 | delete g_nanodet; 503 | g_nanodet = 0; 504 | } 505 | else 506 | { 507 | if (!g_nanodet) 508 | g_nanodet = new NanoDet; 509 | g_nanodet->mode_type = curent_model; 510 | g_nanodet->load(mgr, modeltype, target_size, mean_vals[(int)modelid], norm_vals[(int)modelid], use_gpu); 511 | } 512 | } 513 | // init params 514 | g_nanodet->postprocess_time_picodet=0; 515 | g_nanodet->infer_time_picodet=0; 516 | g_nanodet->preprocess_time_picodet=0; 517 | read_img_time = 0; 518 | draw_img_time = 0; 519 | detect_time = 0; 520 | imwrite_time = 0; 521 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: current use model", "%s", modeltypes[g_nanodet->mode_type]); 522 | // double infertime1 = analysis_cooc128(); 523 | // double infertime2 = analysis_cooc128(); 524 | // double infertime3 = analysis_cooc128(); 525 | // double infertime = (infertime1+infertime2+infertime3)/3; 526 | double infertime = analysis_cooc128(); 527 | double process_time = g_nanodet->preprocess_time_picodet; 528 | double infer_time = g_nanodet->infer_time_picodet; 529 | double postprocess_time = g_nanodet->postprocess_time_picodet; 530 | 531 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: custome time:", "%lf", infertime); 532 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: process_time:", "%lf", process_time); 533 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: infer_time:", "%lf", infer_time); 534 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: postprocess_time:", "%lf", postprocess_time); 535 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: read_img_time:", "%lf", read_img_time); 536 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: draw_img_time:", "%lf", draw_img_time); 537 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: detect_time:", "%lf", detect_time); 538 | __android_log_print(ANDROID_LOG_DEBUG, "ncnn: imwrite_time:", "%lf", imwrite_time); 539 | // return infertime; 540 | return (process_time+infer_time+postprocess_time); 541 | } 542 | 543 | JNIEXPORT jboolean JNICALL Java_com_baidu_picodetncnn_NanoDetNcnn_genVideoByImg(JNIEnv *env, jobject thiz) { 544 | genVideoByImg(); 545 | } 546 | } 547 | 548 | -------------------------------------------------------------------------------- /app/src/main/jni/ndk-stl-config.cmake: -------------------------------------------------------------------------------- 1 | # Copy shared STL files to Android Studio output directory so they can be 2 | # packaged in the APK. 3 | # Usage: 4 | # 5 | # find_package(ndk-stl REQUIRED) 6 | # 7 | # or 8 | # 9 | # find_package(ndk-stl REQUIRED PATHS ".") 10 | 11 | if(NOT ${ANDROID_STL} MATCHES "_shared") 12 | return() 13 | endif() 14 | 15 | function(configure_shared_stl lib_path so_base) 16 | message("Configuring STL ${so_base} for ${ANDROID_ABI}") 17 | configure_file( 18 | "${ANDROID_NDK}/sources/cxx-stl/${lib_path}/libs/${ANDROID_ABI}/lib${so_base}.so" 19 | "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${so_base}.so" 20 | COPYONLY) 21 | endfunction() 22 | 23 | if("${ANDROID_STL}" STREQUAL "libstdc++") 24 | # The default minimal system C++ runtime library. 25 | elseif("${ANDROID_STL}" STREQUAL "gabi++_shared") 26 | # The GAbi++ runtime (shared). 27 | message(FATAL_ERROR "gabi++_shared was not configured by ndk-stl package") 28 | elseif("${ANDROID_STL}" STREQUAL "stlport_shared") 29 | # The STLport runtime (shared). 30 | configure_shared_stl("stlport" "stlport_shared") 31 | elseif("${ANDROID_STL}" STREQUAL "gnustl_shared") 32 | # The GNU STL (shared). 33 | configure_shared_stl("gnu-libstdc++/4.9" "gnustl_shared") 34 | elseif("${ANDROID_STL}" STREQUAL "c++_shared") 35 | # The LLVM libc++ runtime (static). 36 | configure_shared_stl("llvm-libc++" "c++_shared") 37 | else() 38 | message(FATAL_ERROR "STL configuration ANDROID_STL=${ANDROID_STL} is not supported") 39 | endif() -------------------------------------------------------------------------------- /app/src/main/jni/ndkcamera.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NDKCAMERA_H 16 | #define NDKCAMERA_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | class NdkCamera 29 | { 30 | public: 31 | NdkCamera(); 32 | virtual ~NdkCamera(); 33 | 34 | // facing 0=front 1=back 35 | int open(int camera_facing = 0); 36 | void close(); 37 | 38 | virtual void on_image(const cv::Mat& rgb) const; 39 | 40 | virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const; 41 | 42 | public: 43 | int camera_facing; 44 | int camera_orientation; 45 | 46 | private: 47 | ACameraManager* camera_manager; 48 | ACameraDevice* camera_device; 49 | AImageReader* image_reader; 50 | ANativeWindow* image_reader_surface; 51 | ACameraOutputTarget* image_reader_target; 52 | ACaptureRequest* capture_request; 53 | ACaptureSessionOutputContainer* capture_session_output_container; 54 | ACaptureSessionOutput* capture_session_output; 55 | ACameraCaptureSession* capture_session; 56 | }; 57 | 58 | class NdkCameraWindow : public NdkCamera 59 | { 60 | public: 61 | NdkCameraWindow(); 62 | virtual ~NdkCameraWindow(); 63 | 64 | void set_window(ANativeWindow* win); 65 | 66 | virtual void on_image_render(cv::Mat& rgb) const; 67 | 68 | virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const; 69 | 70 | public: 71 | mutable int accelerometer_orientation; 72 | 73 | private: 74 | ASensorManager* sensor_manager; 75 | mutable ASensorEventQueue* sensor_event_queue; 76 | const ASensor* accelerometer_sensor; 77 | ANativeWindow* win; 78 | }; 79 | 80 | #endif // NDKCAMERA_H 81 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable-v24/camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable-v24/photo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_switch_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable-xxhdpi/btn_switch_default.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_switch_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable-xxhdpi/btn_switch_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable-xxhdpi/camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/paddle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable-xxhdpi/paddle.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable-xxhdpi/photo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_settings_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_settings_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_shutter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_shutter_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_shutter_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_switch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable/camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable/photo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/photo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiweiMaster/PP-PicoDet-Android-Demo/c2d3f41c6cbc03ad46118bc091e46f1b5097edce/app/src/main/res/drawable/photo1.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 20 | 21 | 28 | 29 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 48 | 49 | 55 | 56 | 60 | 61 | 64 | 65 | 76 | 77 | 87 | 88 | 98 | 99 | 100 | 101 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 23 | 24 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_photo.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 20 | 21 | 28 | 29 | 36 | 37 | 38 | 42 | 47 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/navigation/nav_graph.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 25 | 26 | 29 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #1E90FF 6 | #FF000000 7 | #00000000 8 | #00000000 9 | #FFFFFFFF 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 26dp 4 | 36dp 5 | 34dp 6 | 60dp 7 | 16dp 8 | 67dp 9 | 67dp 10 | 56dp 11 | 56dp 12 | 46dp 13 | 46dp 14 | 32dp 15 | 24dp 16 | 16dp 17 | 16dp 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PP-PicoDet 4 | 5 | picodet-s-416 6 | picodet-l-640 7 | nanodet-m-416 8 | yolox-nano-416 9 | yolov5s-640 10 | 11 | 12 | CPU 13 | GPU 14 | 15 | 敬请期待新功能 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 15 | 16 | 20 | 21 |