├── .gitignore ├── README.md ├── app ├── CMakeLists.txt ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── tarmac │ │ └── yolov2Tiny │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── coco.names │ │ ├── yolov3-tiny.bin │ │ └── yolov3-tiny.param │ ├── cpp │ │ ├── include │ │ │ └── ncnn │ │ │ │ ├── allocator.h │ │ │ │ ├── benchmark.h │ │ │ │ ├── blob.h │ │ │ │ ├── command.h │ │ │ │ ├── cpu.h │ │ │ │ ├── datareader.h │ │ │ │ ├── gpu.h │ │ │ │ ├── layer.h │ │ │ │ ├── layer_type.h │ │ │ │ ├── layer_type_enum.h │ │ │ │ ├── mat.h │ │ │ │ ├── modelbin.h │ │ │ │ ├── net.h │ │ │ │ ├── opencv.h │ │ │ │ ├── option.h │ │ │ │ ├── paramdict.h │ │ │ │ ├── pipeline.h │ │ │ │ └── platform.h │ │ └── yolov3-tiny-jni.cpp │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── yolov3tiny │ │ │ ├── MainActivity.java │ │ │ ├── PhotoUtil.java │ │ │ └── yolov3Tiny.java │ ├── jniLibs │ │ └── armeabi-v7a │ │ │ └── libncnn.a │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── tarmac │ └── yolov2Tiny │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshot.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea 42 | .idea/workspace.xml 43 | .idea/tasks.xml 44 | .idea/gradle.xml 45 | .idea/assetWizardSettings.xml 46 | .idea/dictionaries 47 | .idea/libraries 48 | # Android Studio 3 in .gitignore file. 49 | .idea/caches 50 | .idea/modules.xml 51 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 52 | .idea/navEditor.xml 53 | 54 | # Keystore files 55 | # Uncomment the following lines if you do not want to check your keystore files in. 56 | #*.jks 57 | #*.keystore 58 | 59 | # External native build folder generated in Android Studio 2.2 and later 60 | .externalNativeBuild 61 | .cxx/ 62 | 63 | # Google Services (e.g. APIs or Firebase) 64 | # google-services.json 65 | 66 | # Freeline 67 | freeline.py 68 | freeline/ 69 | freeline_project_description.json 70 | 71 | # fastlane 72 | fastlane/report.xml 73 | fastlane/Preview.html 74 | fastlane/screenshots 75 | fastlane/test_output 76 | fastlane/readme.md 77 | 78 | # Version control 79 | vcs.xml 80 | 81 | # lint 82 | lint/intermediates/ 83 | lint/generated/ 84 | lint/outputs/ 85 | lint/tmp/ 86 | # lint/reports/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android demo to use darknet model in ncnn. 2 | 3 | Steps: 4 | 5 | 1. Use [darknet2ncnn](https://github.com/xiangweizeng/darknet2ncnn) to convert darknet model to ncnn model. 6 | 2. Build [xiangweizeng/ncnn](https://github.com/xiangweizeng/ncnn) for android. 7 | 3. Put model, ncnn header files and static lib into project. 8 | 9 | ![screenshot](screenshot.jpg) 10 | 11 | Reference: https://github.com/chehongshu/ncnnforandroid_objectiondetection_Mobilenetssd 12 | 13 | For vulkan support: https://github.com/nihui/ncnn-android-styletransfer 14 | 15 | You can find another user-friendly tool at: https://github.com/Tencent/ncnn/tree/master/tools/darknet 16 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | set(CMAKE_BUILD_TYPE RELEASE) 13 | 14 | include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include/ncnn) 15 | 16 | # openmp 17 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp") 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") 19 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fopenmp") 20 | 21 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer -fstrict-aliasing -ffast-math") 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer -fstrict-aliasing -ffast-math") 23 | 24 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") 25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden") 26 | 27 | # disable rtti and exceptions 28 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") 29 | 30 | add_library (libncnn STATIC IMPORTED) 31 | set_target_properties(libncnn PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libncnn.a) 32 | 33 | set(lib_src ${CMAKE_SOURCE_DIR}/src/main/cpp/yolov3-tiny-jni.cpp) 34 | 35 | add_library( # Sets the name of the library. 36 | yolov3_tiny_jni 37 | 38 | # Sets the library as a shared library. 39 | SHARED 40 | 41 | # Provides a relative path to your source file(s). 42 | ${lib_src}) 43 | 44 | # Searches for a specified prebuilt library and stores the path as a 45 | # variable. Because CMake includes system libraries in the search path by 46 | # default, you only need to specify the name of the public NDK library 47 | # you want to add. CMake verifies that the library exists before 48 | # completing its build. 49 | 50 | find_library( # Sets the name of the path variable. 51 | log-lib 52 | 53 | # Specifies the name of the NDK library that 54 | # you want CMake to locate. 55 | log 56 | android) 57 | #find_library( # Sets the name of the path variable. 58 | #JniGraphics 59 | 60 | # Specifies the name of the NDK library that 61 | # you want CMake to locate. 62 | #jnigraphics) 63 | 64 | # Specifies libraries CMake should link to your target library. You 65 | # can link multiple libraries, such as libraries you define in this 66 | # build script, prebuilt third-party libraries, or system libraries. 67 | 68 | target_link_libraries( # Specifies the target library. 69 | yolov3_tiny_jni 70 | libncnn 71 | android 72 | jnigraphics 73 | # vulkan 74 | # Links the target library to the log library 75 | # included in the NDK. 76 | ${log-lib}) 77 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.example.yolov3Tiny" 7 | minSdkVersion 21 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | externalNativeBuild { 13 | cmake { 14 | cppFlags "-std=c++11 -Ofast -Wno-unused-result -Wfatal-errors -fPIC -fno-rtti -fno-exceptions -fopenmp" 15 | abiFilters "armeabi-v7a" 16 | arguments '-DANDROID_PLATFORM=android-21', 17 | '-DANDROID_ARM_NEON=ON' 18 | } 19 | } 20 | } 21 | buildTypes { 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | externalNativeBuild { 28 | cmake { 29 | path "CMakeLists.txt" 30 | } 31 | } 32 | sourceSets { 33 | main { 34 | jniLibs.srcDirs = ["src/main/jniLibs"] 35 | jni.srcDirs = ['src/cpp'] 36 | } 37 | } 38 | } 39 | 40 | dependencies { 41 | implementation fileTree(dir: 'libs', include: ['*.jar']) 42 | implementation 'com.android.support:appcompat-v7:28.0.0' 43 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 44 | testImplementation 'junit:junit:4.12' 45 | implementation 'com.github.bumptech.glide:glide:4.3.1' 46 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 47 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 48 | } 49 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/tarmac/yolov2Tiny/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.tarmac.yolov2Tiny; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.tarmac.yolov2_tiny", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/assets/coco.names: -------------------------------------------------------------------------------- 1 | background 2 | person 3 | bicycle 4 | car 5 | motorbike 6 | aeroplane 7 | bus 8 | train 9 | truck 10 | boat 11 | traffic light 12 | fire hydrant 13 | stop sign 14 | parking meter 15 | bench 16 | bird 17 | cat 18 | dog 19 | horse 20 | sheep 21 | cow 22 | elephant 23 | bear 24 | zebra 25 | giraffe 26 | backpack 27 | umbrella 28 | handbag 29 | tie 30 | suitcase 31 | frisbee 32 | skis 33 | snowboard 34 | sports ball 35 | kite 36 | baseball bat 37 | baseball glove 38 | skateboard 39 | surfboard 40 | tennis racket 41 | bottle 42 | wine glass 43 | cup 44 | fork 45 | knife 46 | spoon 47 | bowl 48 | banana 49 | apple 50 | sandwich 51 | orange 52 | broccoli 53 | carrot 54 | hot dog 55 | pizza 56 | donut 57 | cake 58 | chair 59 | sofa 60 | pottedplant 61 | bed 62 | diningtable 63 | toilet 64 | tvmonitor 65 | laptop 66 | mouse 67 | remote 68 | keyboard 69 | cell phone 70 | microwave 71 | oven 72 | toaster 73 | sink 74 | refrigerator 75 | book 76 | clock 77 | vase 78 | scissors 79 | teddy bear 80 | hair drier 81 | toothbrush 82 | -------------------------------------------------------------------------------- /app/src/main/assets/yolov3-tiny.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paleomoon/darknet-ncnn-android/dea4cc0b128eb5054ff3f69af20d473f874558d2/app/src/main/assets/yolov3-tiny.bin -------------------------------------------------------------------------------- /app/src/main/assets/yolov3-tiny.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 50 52 3 | Input data 0 1 data 0=416 1=416 2=3 4 | Convolution conv_0 1 1 data conv_0 0=16 1=3 2=1 3=1 4=1 5=0 6=432 5 | BatchNorm conv_0_batch_norm 1 1 conv_0 conv_0_batch_norm 0=16 1=0.00001 6 | ReLU conv_0_activation 1 1 conv_0_batch_norm conv_0_activation 0=0.1 7 | Pooling maxpool_1 1 1 conv_0_activation maxpool_1 0=0 1=2 2=2 3=0 5=1 13=0 14=1 15=1 8 | Convolution conv_2 1 1 maxpool_1 conv_2 0=32 1=3 2=1 3=1 4=1 5=0 6=4608 9 | BatchNorm conv_2_batch_norm 1 1 conv_2 conv_2_batch_norm 0=32 1=0.00001 10 | ReLU conv_2_activation 1 1 conv_2_batch_norm conv_2_activation 0=0.1 11 | Pooling maxpool_3 1 1 conv_2_activation maxpool_3 0=0 1=2 2=2 3=0 5=1 13=0 14=1 15=1 12 | Convolution conv_4 1 1 maxpool_3 conv_4 0=64 1=3 2=1 3=1 4=1 5=0 6=18432 13 | BatchNorm conv_4_batch_norm 1 1 conv_4 conv_4_batch_norm 0=64 1=0.00001 14 | ReLU conv_4_activation 1 1 conv_4_batch_norm conv_4_activation 0=0.1 15 | Pooling maxpool_5 1 1 conv_4_activation maxpool_5 0=0 1=2 2=2 3=0 5=1 13=0 14=1 15=1 16 | Convolution conv_6 1 1 maxpool_5 conv_6 0=128 1=3 2=1 3=1 4=1 5=0 6=73728 17 | BatchNorm conv_6_batch_norm 1 1 conv_6 conv_6_batch_norm 0=128 1=0.00001 18 | ReLU conv_6_activation 1 1 conv_6_batch_norm conv_6_activation 0=0.1 19 | Pooling maxpool_7 1 1 conv_6_activation maxpool_7 0=0 1=2 2=2 3=0 5=1 13=0 14=1 15=1 20 | Convolution conv_8 1 1 maxpool_7 conv_8 0=256 1=3 2=1 3=1 4=1 5=0 6=294912 21 | BatchNorm conv_8_batch_norm 1 1 conv_8 conv_8_batch_norm 0=256 1=0.00001 22 | ReLU conv_8_activation 1 1 conv_8_batch_norm conv_8_activation 0=0.1 23 | Split conv_8_activation_split 1 2 conv_8_activation conv_8_activation_split_0 conv_8_activation_split_1 24 | Pooling maxpool_9 1 1 conv_8_activation_split_0 maxpool_9 0=0 1=2 2=2 3=0 5=1 13=0 14=1 15=1 25 | Convolution conv_10 1 1 maxpool_9 conv_10 0=512 1=3 2=1 3=1 4=1 5=0 6=1179648 26 | BatchNorm conv_10_batch_norm 1 1 conv_10 conv_10_batch_norm 0=512 1=0.00001 27 | ReLU conv_10_activation 1 1 conv_10_batch_norm conv_10_activation 0=0.1 28 | Pooling maxpool_11 1 1 conv_10_activation maxpool_11 0=0 1=2 2=1 3=0 5=1 13=0 14=1 15=1 29 | Convolution conv_12 1 1 maxpool_11 conv_12 0=1024 1=3 2=1 3=1 4=1 5=0 6=4718592 30 | BatchNorm conv_12_batch_norm 1 1 conv_12 conv_12_batch_norm 0=1024 1=0.00001 31 | ReLU conv_12_activation 1 1 conv_12_batch_norm conv_12_activation 0=0.1 32 | Convolution conv_13 1 1 conv_12_activation conv_13 0=256 1=1 2=1 3=1 4=0 5=0 6=262144 33 | BatchNorm conv_13_batch_norm 1 1 conv_13 conv_13_batch_norm 0=256 1=0.00001 34 | ReLU conv_13_activation 1 1 conv_13_batch_norm conv_13_activation 0=0.1 35 | Split conv_13_activation_split 1 2 conv_13_activation conv_13_activation_split_0 conv_13_activation_split_1 36 | Convolution conv_14 1 1 conv_13_activation_split_0 conv_14 0=512 1=3 2=1 3=1 4=1 5=0 6=1179648 37 | BatchNorm conv_14_batch_norm 1 1 conv_14 conv_14_batch_norm 0=512 1=0.00001 38 | ReLU conv_14_activation 1 1 conv_14_batch_norm conv_14_activation 0=0.1 39 | Convolution conv_15 1 1 conv_14_activation conv_15 0=255 1=1 2=1 3=1 4=0 5=1 6=130560 40 | DarknetActivation conv_15_activation 1 1 conv_15 conv_15_activation 0=3 41 | Concat route_17 1 1 conv_13_activation_split_1 route_17 0=0 42 | Convolution conv_18 1 1 route_17 conv_18 0=128 1=1 2=1 3=1 4=0 5=0 6=32768 43 | BatchNorm conv_18_batch_norm 1 1 conv_18 conv_18_batch_norm 0=128 1=0.00001 44 | ReLU conv_18_activation 1 1 conv_18_batch_norm conv_18_activation 0=0.1 45 | Interp upsample_19 1 1 conv_18_activation upsample_19 0=1 1=2.f 2=2.f 46 | Concat route_20 2 1 upsample_19 conv_8_activation_split_1 route_20 0=0 47 | Convolution conv_21 1 1 route_20 conv_21 0=256 1=3 2=1 3=1 4=1 5=0 6=884736 48 | BatchNorm conv_21_batch_norm 1 1 conv_21 conv_21_batch_norm 0=256 1=0.00001 49 | ReLU conv_21_activation 1 1 conv_21_batch_norm conv_21_activation 0=0.1 50 | Convolution conv_22 1 1 conv_21_activation conv_22 0=255 1=1 2=1 3=1 4=0 5=1 6=65280 51 | DarknetActivation conv_22_activation 1 1 conv_22 conv_22_activation 0=3 52 | Yolov3Detection yolo_23 2 1 conv_15_activation conv_22_activation yolo_23 0=80 1=6 2=0 3=0.25f 4=0.45f 5=416 6=416 -23307=12,81.000000,82.000000,135.000000,169.000000,344.000000,319.000000,10.000000,14.000000,23.000000,27.000000,37.000000,58.000000 53 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/allocator.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2018 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 NCNN_ALLOCATOR_H 16 | #define NCNN_ALLOCATOR_H 17 | 18 | #ifdef _WIN32 19 | #define WIN32_LEAN_AND_MEAN 20 | #include 21 | #else 22 | #include 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | #include "platform.h" 29 | 30 | #if NCNN_VULKAN 31 | #include 32 | #include "gpu.h" 33 | #endif // NCNN_VULKAN 34 | 35 | namespace ncnn { 36 | 37 | // the alignment of all the allocated buffers 38 | #define MALLOC_ALIGN 16 39 | 40 | // Aligns a pointer to the specified number of bytes 41 | // ptr Aligned pointer 42 | // n Alignment size that must be a power of two 43 | template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) 44 | { 45 | return (_Tp*)(((size_t)ptr + n-1) & -n); 46 | } 47 | 48 | // Aligns a buffer size to the specified number of bytes 49 | // The function returns the minimum number that is greater or equal to sz and is divisible by n 50 | // sz Buffer size to align 51 | // n Alignment size that must be a power of two 52 | static inline size_t alignSize(size_t sz, int n) 53 | { 54 | return (sz + n-1) & -n; 55 | } 56 | 57 | static inline void* fastMalloc(size_t size) 58 | { 59 | #if _MSC_VER 60 | return _aligned_malloc(size, MALLOC_ALIGN); 61 | #elif _POSIX_C_SOURCE >= 200112L || (__ANDROID__ && __ANDROID_API__ >= 17) 62 | void* ptr = 0; 63 | if (posix_memalign(&ptr, MALLOC_ALIGN, size)) 64 | ptr = 0; 65 | return ptr; 66 | #elif __ANDROID__ && __ANDROID_API__ < 17 67 | return memalign(MALLOC_ALIGN, size); 68 | #else 69 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 70 | if (!udata) 71 | return 0; 72 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 73 | adata[-1] = udata; 74 | return adata; 75 | #endif 76 | } 77 | 78 | static inline void fastFree(void* ptr) 79 | { 80 | if (ptr) 81 | { 82 | #if _MSC_VER 83 | _aligned_free(ptr); 84 | #elif _POSIX_C_SOURCE >= 200112L || (__ANDROID__ && __ANDROID_API__ >= 17) 85 | free(ptr); 86 | #elif __ANDROID__ && __ANDROID_API__ < 17 87 | free(ptr); 88 | #else 89 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 90 | free(udata); 91 | #endif 92 | } 93 | } 94 | 95 | // exchange-add operation for atomic operations on reference counters 96 | #if defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) 97 | // atomic increment on the linux version of the Intel(tm) compiler 98 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta) 99 | #elif defined __GNUC__ 100 | # if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) 101 | # ifdef __ATOMIC_ACQ_REL 102 | # define NCNN_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) 103 | # else 104 | # define NCNN_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), delta, 4) 105 | # endif 106 | # else 107 | # if defined __ATOMIC_ACQ_REL && !defined __clang__ 108 | // version for gcc >= 4.7 109 | # define NCNN_XADD(addr, delta) (int)__atomic_fetch_add((unsigned*)(addr), (unsigned)(delta), __ATOMIC_ACQ_REL) 110 | # else 111 | # define NCNN_XADD(addr, delta) (int)__sync_fetch_and_add((unsigned*)(addr), (unsigned)(delta)) 112 | # endif 113 | # endif 114 | #elif defined _MSC_VER && !defined RC_INVOKED 115 | # include 116 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta) 117 | #else 118 | // thread-unsafe branch 119 | static inline int NCNN_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; } 120 | #endif 121 | 122 | class Allocator 123 | { 124 | public: 125 | virtual ~Allocator(); 126 | virtual void* fastMalloc(size_t size) = 0; 127 | virtual void fastFree(void* ptr) = 0; 128 | }; 129 | 130 | class PoolAllocator : public Allocator 131 | { 132 | public: 133 | PoolAllocator(); 134 | ~PoolAllocator(); 135 | 136 | // ratio range 0 ~ 1 137 | // default cr = 0.75 138 | void set_size_compare_ratio(float scr); 139 | 140 | // release all budgets immediately 141 | void clear(); 142 | 143 | virtual void* fastMalloc(size_t size); 144 | virtual void fastFree(void* ptr); 145 | 146 | private: 147 | Mutex budgets_lock; 148 | Mutex payouts_lock; 149 | unsigned int size_compare_ratio;// 0~256 150 | std::list< std::pair > budgets; 151 | std::list< std::pair > payouts; 152 | }; 153 | 154 | class UnlockedPoolAllocator : public Allocator 155 | { 156 | public: 157 | UnlockedPoolAllocator(); 158 | ~UnlockedPoolAllocator(); 159 | 160 | // ratio range 0 ~ 1 161 | // default cr = 0.75 162 | void set_size_compare_ratio(float scr); 163 | 164 | // release all budgets immediately 165 | void clear(); 166 | 167 | virtual void* fastMalloc(size_t size); 168 | virtual void fastFree(void* ptr); 169 | 170 | private: 171 | unsigned int size_compare_ratio;// 0~256 172 | std::list< std::pair > budgets; 173 | std::list< std::pair > payouts; 174 | }; 175 | 176 | #if NCNN_VULKAN 177 | 178 | class VkBufferMemory 179 | { 180 | public: 181 | VkBuffer buffer; 182 | 183 | // the base offset assigned by allocator 184 | size_t offset; 185 | size_t capacity; 186 | 187 | VkDeviceMemory memory; 188 | void* mapped_ptr; 189 | 190 | // buffer state, modified by command functions internally 191 | // 0=null 192 | // 1=created 193 | // 2=transfer 194 | // 3=compute 195 | // 4=readonly 196 | mutable int state; 197 | 198 | // initialize and modified by mat 199 | int refcount; 200 | }; 201 | 202 | class VkAllocator 203 | { 204 | public: 205 | VkAllocator(const VulkanDevice* _vkdev); 206 | virtual ~VkAllocator() { clear(); } 207 | virtual void clear() {} 208 | virtual VkBufferMemory* fastMalloc(size_t size) = 0; 209 | virtual void fastFree(VkBufferMemory* ptr) = 0; 210 | 211 | public: 212 | const VulkanDevice* vkdev; 213 | uint32_t memory_type_index; 214 | bool mappable; 215 | 216 | protected: 217 | VkBuffer create_buffer(size_t size, VkBufferUsageFlags usage); 218 | VkDeviceMemory allocate_memory(size_t size); 219 | VkDeviceMemory allocate_dedicated_memory(size_t size, VkBuffer buffer); 220 | }; 221 | 222 | class VkBlobBufferAllocator : public VkAllocator 223 | { 224 | public: 225 | VkBlobBufferAllocator(const VulkanDevice* vkdev); 226 | virtual ~VkBlobBufferAllocator(); 227 | 228 | public: 229 | // release all budgets immediately 230 | virtual void clear(); 231 | 232 | virtual VkBufferMemory* fastMalloc(size_t size); 233 | virtual void fastFree(VkBufferMemory* ptr); 234 | 235 | private: 236 | size_t block_size; 237 | size_t buffer_offset_alignment; 238 | std::vector< std::list< std::pair > > budgets; 239 | std::vector buffer_blocks; 240 | }; 241 | 242 | class VkWeightBufferAllocator : public VkAllocator 243 | { 244 | public: 245 | VkWeightBufferAllocator(const VulkanDevice* vkdev); 246 | virtual ~VkWeightBufferAllocator(); 247 | 248 | public: 249 | // release all blocks immediately 250 | virtual void clear(); 251 | 252 | public: 253 | virtual VkBufferMemory* fastMalloc(size_t size); 254 | virtual void fastFree(VkBufferMemory* ptr); 255 | 256 | private: 257 | size_t block_size; 258 | size_t buffer_offset_alignment; 259 | std::vector buffer_block_free_spaces; 260 | std::vector buffer_blocks; 261 | std::vector dedicated_buffer_blocks; 262 | }; 263 | 264 | class VkStagingBufferAllocator : public VkAllocator 265 | { 266 | public: 267 | VkStagingBufferAllocator(const VulkanDevice* vkdev); 268 | virtual ~VkStagingBufferAllocator(); 269 | 270 | public: 271 | // ratio range 0 ~ 1 272 | // default cr = 0.75 273 | void set_size_compare_ratio(float scr); 274 | 275 | // release all budgets immediately 276 | virtual void clear(); 277 | 278 | virtual VkBufferMemory* fastMalloc(size_t size); 279 | virtual void fastFree(VkBufferMemory* ptr); 280 | 281 | private: 282 | unsigned int size_compare_ratio;// 0~256 283 | std::list budgets; 284 | }; 285 | 286 | class VkWeightStagingBufferAllocator : public VkAllocator 287 | { 288 | public: 289 | VkWeightStagingBufferAllocator(const VulkanDevice* vkdev); 290 | virtual ~VkWeightStagingBufferAllocator(); 291 | 292 | public: 293 | virtual VkBufferMemory* fastMalloc(size_t size); 294 | virtual void fastFree(VkBufferMemory* ptr); 295 | 296 | private: 297 | }; 298 | 299 | #endif // NCNN_VULKAN 300 | 301 | } // namespace ncnn 302 | 303 | #endif // NCNN_ALLOCATOR_H 304 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/benchmark.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_BENCHMARK_H 16 | #define NCNN_BENCHMARK_H 17 | 18 | #include "platform.h" 19 | #include "mat.h" 20 | #include "layer.h" 21 | 22 | namespace ncnn { 23 | 24 | // get now timestamp in ms 25 | double get_current_time(); 26 | 27 | #if NCNN_BENCHMARK 28 | 29 | void benchmark(const Layer* layer, double start, double end); 30 | void benchmark(const Layer* layer, const Mat& bottom_blob, Mat& top_blob, double start, double end); 31 | 32 | #endif // NCNN_BENCHMARK 33 | 34 | } // namespace ncnn 35 | 36 | #endif // NCNN_BENCHMARK_H 37 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/blob.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_BLOB_H 16 | #define NCNN_BLOB_H 17 | 18 | #include 19 | #include 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Blob 25 | { 26 | public: 27 | // empty 28 | Blob(); 29 | 30 | public: 31 | #if NCNN_STRING 32 | // blob name 33 | std::string name; 34 | #endif // NCNN_STRING 35 | // layer index which produce this blob as output 36 | int producer; 37 | // layer index which need this blob as input 38 | std::vector consumers; 39 | }; 40 | 41 | } // namespace ncnn 42 | 43 | #endif // NCNN_BLOB_H 44 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/command.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2018 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 NCNN_COMMAND_H 16 | #define NCNN_COMMAND_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_VULKAN 21 | 22 | #include 23 | #include 24 | #include "mat.h" 25 | #include "pipeline.h" 26 | 27 | namespace ncnn { 28 | 29 | class Command 30 | { 31 | public: 32 | Command(const VulkanDevice* vkdev, uint32_t queue_family_index); 33 | virtual ~Command(); 34 | 35 | protected: 36 | int create_command_pool(); 37 | int create_command_buffer(); 38 | 39 | // record issue 40 | int begin_command_buffer(); 41 | int end_command_buffer(); 42 | int queue_submit_and_wait_fence(); 43 | 44 | protected: 45 | const VulkanDevice* vkdev; 46 | uint32_t queue_family_index; 47 | 48 | VkCommandPool command_pool; 49 | VkCommandBuffer command_buffer; 50 | 51 | VkFence fence; 52 | }; 53 | 54 | class VkCompute : public Command 55 | { 56 | public: 57 | VkCompute(const VulkanDevice* vkdev); 58 | ~VkCompute(); 59 | 60 | void record_upload(const VkMat& m); 61 | 62 | void record_download(const VkMat& m); 63 | 64 | void record_clone(const VkMat& src, const VkMat& dst); 65 | 66 | void record_copy_region(const VkMat& src, const VkMat& dst, const VkBufferCopy& region); 67 | 68 | void record_copy_regions(const VkMat& src, const VkMat& dst, const std::vector& regions); 69 | 70 | void record_pipeline(const Pipeline* pipeline, const std::vector& bindings, const std::vector& constants, const VkMat& m); 71 | 72 | void record_write_timestamp(uint32_t query); 73 | 74 | #if __ANDROID_API__ >= 26 75 | void record_import_android_hardware_buffer(const ImportAndroidHardwareBufferPipeline* pipeline, VkImage image, VkImageView imageView, const VkMat& m); 76 | #endif // __ANDROID_API__ >= 26 77 | 78 | int submit_and_wait(); 79 | 80 | int reset(); 81 | 82 | #if NCNN_BENCHMARK 83 | int create_query_pool(uint32_t query_count); 84 | 85 | int get_query_pool_results(uint32_t first_query, uint32_t query_count, std::vector& results); 86 | #endif // NCNN_BENCHMARK 87 | 88 | protected: 89 | // record pipeline things 90 | void record_bind_pipeline(VkPipeline pipeline); 91 | void record_update_bindings(VkPipelineLayout pipeline_layout, VkDescriptorSetLayout descriptorset_layout, VkDescriptorUpdateTemplateKHR descriptor_update_template, const std::vector& bindings); 92 | void record_push_constants(VkPipelineLayout pipeline_layout, const std::vector& constants); 93 | void record_dispatch(const uint32_t* group_count_xyz); 94 | 95 | // record barrier things 96 | void record_transfer_compute_barrier(const VkMat& m); 97 | void record_compute_transfer_barrier(const VkMat& m); 98 | void record_compute_compute_barrier(const VkMat& m); 99 | void record_transfer_transfer_barrier(const VkMat& m); 100 | 101 | // record prepare things 102 | void record_prepare_transfer_barrier(const VkMat& m); 103 | void record_prepare_compute_barrier(const VkMat& m); 104 | 105 | void record_initial_image_compute_barrier(VkImage image); 106 | 107 | #if __ANDROID_API__ >= 26 108 | void record_update_import_android_hardware_buffer_bindings(VkPipelineLayout pipeline_layout, VkDescriptorSetLayout descriptorset_layout, VkDescriptorUpdateTemplateKHR descriptor_update_template, VkSampler sampler, VkImageView imageView, const VkMat& m); 109 | #endif // __ANDROID_API__ >= 26 110 | 111 | #if NCNN_BENCHMARK 112 | void reset_query_pool(); 113 | #endif // NCNN_BENCHMARK 114 | 115 | protected: 116 | // recording issue 117 | void copy_buffer(VkBuffer src, size_t src_offset, VkBuffer dst, size_t dst_offset, size_t size); 118 | void copy_buffer_regions(VkBuffer src, VkBuffer dst, const std::vector& regions); 119 | void bind_pipeline(VkPipeline pipeline); 120 | void bind_descriptorset(VkPipelineLayout pipeline_layout, VkDescriptorSet descriptorset); 121 | void update_bindings(VkPipelineLayout pipeline_layout, VkDescriptorUpdateTemplateKHR descriptor_update_template, const std::vector& descriptorBufferInfos); 122 | void push_constants(VkPipelineLayout pipeline_layout, const std::vector& constants); 123 | void dispatch(const uint32_t* group_count_xyz); 124 | void transfer_compute_barrier(VkBuffer buffer, size_t offset, size_t size); 125 | void compute_transfer_barrier(VkBuffer buffer, size_t offset, size_t size); 126 | void compute_compute_barrier(VkBuffer buffer, size_t offset, size_t size); 127 | void transfer_transfer_barrier(VkBuffer buffer, size_t offset, size_t size); 128 | void initial_image_compute_barrier(VkImage image); 129 | #if __ANDROID_API__ >= 26 130 | void update_import_android_hardware_buffer_bindings(VkPipelineLayout pipeline_layout, VkDescriptorUpdateTemplateKHR descriptor_update_template, const VkDescriptorImageInfo& descriptorImageInfo, const VkDescriptorBufferInfo& descriptorBufferInfo); 131 | #endif // __ANDROID_API__ >= 26 132 | #if NCNN_BENCHMARK 133 | void write_timestamp(uint32_t query); 134 | #endif // NCNN_BENCHMARK 135 | 136 | protected: 137 | // delayed record 138 | // the good-old path for device without VK_KHR_push_descriptor 139 | std::vector descriptor_pools; 140 | std::vector descriptorsets; 141 | struct record_type 142 | { 143 | // 0=copy 144 | // 1=copy regions 145 | // 2=bind pipeline 146 | // 3=bind descriptorset 147 | // 4=push constants 148 | // 5=dispatch 149 | // 6=transfer-compute barrier 150 | // 7=compute-transfer barrier 151 | // 8=compute-compute barrier 152 | // 9=transfer-transfer barrier 153 | // 10=write timestamp 154 | // 11=initial image compute barrier 155 | int type; 156 | 157 | union 158 | { 159 | struct { VkBuffer src; size_t src_offset; VkBuffer dst; size_t dst_offset; size_t size; } copy; 160 | struct { VkBuffer src; VkBuffer dst; } copy_regions; 161 | struct { VkPipeline pipeline; } bind_pipeline; 162 | struct { VkPipelineLayout pipeline_layout; VkDescriptorSet descriptorset; } bind_descriptorset; 163 | struct { VkPipelineLayout pipeline_layout; } push_constants; 164 | struct { uint32_t group_count_xyz[3]; } dispatch; 165 | struct { VkBuffer buffer; size_t offset; size_t size; } transfer_compute_barrier; 166 | struct { VkBuffer buffer; size_t offset; size_t size; } compute_transfer_barrier; 167 | struct { VkBuffer buffer; size_t offset; size_t size; } compute_compute_barrier; 168 | struct { VkBuffer buffer; size_t offset; size_t size; } transfer_transfer_barrier; 169 | #if NCNN_BENCHMARK 170 | struct { uint32_t query; } write_timestamp; 171 | #endif // NCNN_BENCHMARK 172 | struct { VkImage image; } initial_image_compute_barrier; 173 | }; 174 | 175 | std::vector regions; 176 | std::vector constants; 177 | }; 178 | std::vector delayed_records; 179 | 180 | #if NCNN_BENCHMARK 181 | uint32_t query_count; 182 | VkQueryPool query_pool; 183 | #endif // NCNN_BENCHMARK 184 | }; 185 | 186 | class VkTransfer : public Command 187 | { 188 | public: 189 | VkTransfer(const VulkanDevice* vkdev); 190 | ~VkTransfer(); 191 | 192 | void record_upload(const Mat& src, VkMat& dst, const Option& opt); 193 | 194 | int submit_and_wait(); 195 | 196 | public: 197 | VkAllocator* weight_vkallocator; 198 | VkAllocator* staging_vkallocator; 199 | 200 | protected: 201 | // recording issue 202 | void copy_buffer(VkBuffer src, size_t src_offset, VkBuffer dst, size_t dst_offset, size_t size); 203 | void copy_buffer_regions(VkBuffer src, VkBuffer dst, const std::vector& regions); 204 | 205 | protected: 206 | size_t buffer_offset_alignment; 207 | VkBufferMemory* staging_data; 208 | 209 | // delayed record 210 | struct record_type 211 | { 212 | size_t size; 213 | Mat mat; 214 | VkMat vkmat; 215 | }; 216 | std::vector delayed_records; 217 | }; 218 | 219 | } // namespace ncnn 220 | 221 | #endif // NCNN_VULKAN 222 | 223 | #endif // NCNN_COMMAND_H 224 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/cpu.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_CPU_H 16 | #define NCNN_CPU_H 17 | 18 | namespace ncnn { 19 | 20 | // test optional cpu features 21 | // neon = armv7 neon or aarch64 asimd 22 | int cpu_support_arm_neon(); 23 | // vfpv4 = armv7 fp16 + fma 24 | int cpu_support_arm_vfpv4(); 25 | // asimdhp = aarch64 asimd half precision 26 | int cpu_support_arm_asimdhp(); 27 | 28 | // cpu info 29 | int get_cpu_count(); 30 | 31 | // bind all threads on little clusters if powersave enabled 32 | // affacts HMP arch cpu like ARM big.LITTLE 33 | // only implemented on android at the moment 34 | // switching powersave is expensive and not thread-safe 35 | // 0 = all cores enabled(default) 36 | // 1 = only little clusters enabled 37 | // 2 = only big clusters enabled 38 | // return 0 if success for setter function 39 | int get_cpu_powersave(); 40 | int set_cpu_powersave(int powersave); 41 | 42 | // misc function wrapper for openmp routines 43 | int get_omp_num_threads(); 44 | void set_omp_num_threads(int num_threads); 45 | 46 | int get_omp_dynamic(); 47 | void set_omp_dynamic(int dynamic); 48 | 49 | } // namespace ncnn 50 | 51 | #endif // NCNN_CPU_H 52 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/datareader.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2019 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 NCNN_DATAREADER_H 16 | #define NCNN_DATAREADER_H 17 | 18 | #include 19 | #include "platform.h" 20 | 21 | #if __ANDROID_API__ >= 9 22 | #include 23 | #endif 24 | 25 | namespace ncnn { 26 | 27 | // data read wrapper 28 | class DataReader 29 | { 30 | public: 31 | virtual ~DataReader(); 32 | 33 | #if NCNN_STRING 34 | // parse plain param text 35 | // return 1 if scan success 36 | virtual int scan(const char* format, void* p) const; 37 | #endif // NCNN_STRING 38 | 39 | // read binary param and model data 40 | // return bytes read 41 | virtual int read(void* buf, int size) const; 42 | }; 43 | 44 | #if NCNN_STDIO 45 | class DataReaderFromStdio : public DataReader 46 | { 47 | public: 48 | DataReaderFromStdio(FILE* fp); 49 | 50 | #if NCNN_STRING 51 | virtual int scan(const char* format, void* p) const; 52 | #endif // NCNN_STRING 53 | virtual int read(void* buf, int size) const; 54 | 55 | protected: 56 | FILE* fp; 57 | }; 58 | #endif // NCNN_STDIO 59 | 60 | class DataReaderFromMemory : public DataReader 61 | { 62 | public: 63 | DataReaderFromMemory(const unsigned char*& mem); 64 | 65 | #if NCNN_STRING 66 | virtual int scan(const char* format, void* p) const; 67 | #endif // NCNN_STRING 68 | virtual int read(void* buf, int size) const; 69 | 70 | protected: 71 | const unsigned char*& mem; 72 | }; 73 | 74 | #if __ANDROID_API__ >= 9 75 | class DataReaderFromAndroidAsset : public DataReader 76 | { 77 | public: 78 | DataReaderFromAndroidAsset(AAsset* asset); 79 | 80 | #if NCNN_STRING 81 | virtual int scan(const char* format, void* p) const; 82 | #endif // NCNN_STRING 83 | virtual int read(void* buf, int size) const; 84 | 85 | protected: 86 | AAsset* asset; 87 | mutable const unsigned char* mem; 88 | }; 89 | #endif // __ANDROID_API__ >= 9 90 | 91 | } // namespace ncnn 92 | 93 | #endif // NCNN_DATAREADER_H 94 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/gpu.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2018 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 NCNN_GPU_H 16 | #define NCNN_GPU_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_VULKAN 21 | 22 | #include 23 | #include 24 | 25 | namespace ncnn { 26 | 27 | // instance 28 | int create_gpu_instance(); 29 | void destroy_gpu_instance(); 30 | 31 | // instance extension capability 32 | extern int support_VK_KHR_external_memory_capabilities; 33 | extern int support_VK_KHR_get_physical_device_properties2; 34 | extern int support_VK_KHR_get_surface_capabilities2; 35 | extern int support_VK_KHR_surface; 36 | extern int support_VK_EXT_debug_utils; 37 | #if __ANDROID_API__ >= 26 38 | extern int support_VK_KHR_android_surface; 39 | #endif // __ANDROID_API__ >= 26 40 | 41 | // VK_KHR_external_memory_capabilities 42 | extern PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR vkGetPhysicalDeviceExternalBufferPropertiesKHR; 43 | 44 | // VK_KHR_get_physical_device_properties2 45 | extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; 46 | extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; 47 | extern PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; 48 | extern PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR; 49 | extern PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR; 50 | extern PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; 51 | extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR vkGetPhysicalDeviceSparseImageFormatProperties2KHR; 52 | 53 | // VK_KHR_get_surface_capabilities2 54 | extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR; 55 | extern PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR; 56 | 57 | // VK_KHR_surface 58 | extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; 59 | extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; 60 | extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; 61 | extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; 62 | extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; 63 | 64 | #if __ANDROID_API__ >= 26 65 | // VK_KHR_android_surface 66 | extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; 67 | #endif // __ANDROID_API__ >= 26 68 | 69 | // get info 70 | int get_gpu_count(); 71 | int get_default_gpu_index(); 72 | 73 | class GpuInfo 74 | { 75 | public: 76 | // vulkan physical device 77 | VkPhysicalDevice physical_device; 78 | 79 | // memory properties 80 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 81 | 82 | // info 83 | uint32_t api_version; 84 | uint32_t driver_version; 85 | uint32_t vendor_id; 86 | uint32_t device_id; 87 | uint8_t pipeline_cache_uuid[VK_UUID_SIZE]; 88 | 89 | // 0 = discrete gpu 90 | // 1 = integrated gpu 91 | // 2 = virtual gpu 92 | // 3 = cpu 93 | int type; 94 | 95 | // hardware capability 96 | uint32_t max_shared_memory_size; 97 | uint32_t max_workgroup_count[3]; 98 | uint32_t max_workgroup_invocations; 99 | uint32_t max_workgroup_size[3]; 100 | size_t memory_map_alignment; 101 | size_t buffer_offset_alignment; 102 | float timestamp_period; 103 | 104 | // runtime 105 | uint32_t compute_queue_family_index; 106 | uint32_t graphics_queue_family_index; 107 | uint32_t transfer_queue_family_index; 108 | 109 | uint32_t compute_queue_count; 110 | uint32_t graphics_queue_count; 111 | uint32_t transfer_queue_count; 112 | 113 | // fp16 and int8 feature 114 | bool support_fp16_packed; 115 | bool support_fp16_storage; 116 | bool support_fp16_arithmetic; 117 | bool support_int8_storage; 118 | bool support_int8_arithmetic; 119 | 120 | // ycbcr conversion feature 121 | bool support_ycbcr_conversion; 122 | 123 | // extension capability 124 | int support_VK_KHR_8bit_storage; 125 | int support_VK_KHR_16bit_storage; 126 | int support_VK_KHR_bind_memory2; 127 | int support_VK_KHR_dedicated_allocation; 128 | int support_VK_KHR_descriptor_update_template; 129 | int support_VK_KHR_external_memory; 130 | int support_VK_KHR_get_memory_requirements2; 131 | int support_VK_KHR_maintenance1; 132 | int support_VK_KHR_push_descriptor; 133 | int support_VK_KHR_sampler_ycbcr_conversion; 134 | int support_VK_KHR_shader_float16_int8; 135 | int support_VK_KHR_shader_float_controls; 136 | int support_VK_KHR_storage_buffer_storage_class; 137 | int support_VK_KHR_swapchain; 138 | int support_VK_EXT_queue_family_foreign; 139 | #if __ANDROID_API__ >= 26 140 | int support_VK_ANDROID_external_memory_android_hardware_buffer; 141 | #endif // __ANDROID_API__ >= 26 142 | }; 143 | 144 | const GpuInfo& get_gpu_info(int device_index = get_default_gpu_index()); 145 | 146 | class VkAllocator; 147 | class VulkanDevice 148 | { 149 | public: 150 | VulkanDevice(int device_index = get_default_gpu_index()); 151 | ~VulkanDevice(); 152 | 153 | const GpuInfo& info; 154 | 155 | VkDevice vkdevice() const { return device; } 156 | 157 | VkShaderModule get_shader_module(const char* name) const; 158 | 159 | VkShaderModule compile_shader_module(const uint32_t* spv_data, size_t spv_data_size) const; 160 | 161 | uint32_t find_memory_index(uint32_t memory_type_bits, VkFlags required, VkFlags preferred, VkFlags preferred_not) const; 162 | bool is_mappable(uint32_t memory_type_index) const; 163 | 164 | VkQueue acquire_queue(uint32_t queue_family_index) const; 165 | void reclaim_queue(uint32_t queue_family_index, VkQueue queue) const; 166 | 167 | // allocator on this device 168 | VkAllocator* acquire_blob_allocator() const; 169 | void reclaim_blob_allocator(VkAllocator* allocator) const; 170 | 171 | VkAllocator* acquire_staging_allocator() const; 172 | void reclaim_staging_allocator(VkAllocator* allocator) const; 173 | 174 | // VK_KHR_bind_memory2 175 | PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR; 176 | PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; 177 | 178 | // VK_KHR_descriptor_update_template 179 | PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR; 180 | PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR; 181 | PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR; 182 | 183 | // VK_KHR_get_memory_requirements2 184 | PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; 185 | PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR; 186 | PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR; 187 | 188 | // VK_KHR_maintenance1 189 | PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR; 190 | 191 | // VK_KHR_push_descriptor 192 | PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR; 193 | PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; 194 | 195 | // VK_KHR_sampler_ycbcr_conversion 196 | PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; 197 | PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; 198 | 199 | // VK_KHR_swapchain 200 | PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; 201 | PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; 202 | PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; 203 | PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; 204 | PFN_vkQueuePresentKHR vkQueuePresentKHR; 205 | 206 | #if __ANDROID_API__ >= 26 207 | // VK_ANDROID_external_memory_android_hardware_buffer 208 | PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID; 209 | PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; 210 | #endif // __ANDROID_API__ >= 26 211 | 212 | protected: 213 | // shader management 214 | int create_shader_module(); 215 | void destroy_shader_module(); 216 | 217 | // device extension 218 | int init_device_extension(); 219 | 220 | private: 221 | VkDevice device; 222 | std::vector shader_modules; 223 | 224 | // hardware queue 225 | mutable std::vector compute_queues; 226 | mutable std::vector graphics_queues; 227 | mutable std::vector transfer_queues; 228 | mutable Mutex queue_lock; 229 | 230 | // default blob allocator for each queue 231 | mutable std::vector blob_allocators; 232 | mutable Mutex blob_allocator_lock; 233 | 234 | // default staging allocator for each queue 235 | mutable std::vector staging_allocators; 236 | mutable Mutex staging_allocator_lock; 237 | }; 238 | 239 | VulkanDevice* get_gpu_device(int device_index = get_default_gpu_index()); 240 | 241 | } // namespace ncnn 242 | 243 | #endif // NCNN_VULKAN 244 | 245 | #endif // NCNN_GPU_H 246 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/layer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_LAYER_H 16 | #define NCNN_LAYER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "platform.h" 23 | #include "mat.h" 24 | #include "modelbin.h" 25 | #include "option.h" 26 | #include "paramdict.h" 27 | 28 | #if NCNN_VULKAN 29 | #include 30 | #include "command.h" 31 | #include "pipeline.h" 32 | #endif // NCNN_VULKAN 33 | 34 | namespace ncnn { 35 | 36 | class Layer 37 | { 38 | public: 39 | // empty 40 | Layer(); 41 | // virtual destructor 42 | virtual ~Layer(); 43 | 44 | // load layer specific parameter from parsed dict 45 | // return 0 if success 46 | virtual int load_param(const ParamDict& pd); 47 | 48 | // load layer specific weight data from model binary 49 | // return 0 if success 50 | virtual int load_model(const ModelBin& mb); 51 | 52 | // layer implementation specific setup 53 | // return 0 if success 54 | virtual int create_pipeline(const Option& opt); 55 | 56 | // layer implementation specific clean 57 | // return 0 if success 58 | virtual int destroy_pipeline(const Option& opt); 59 | 60 | public: 61 | // one input and one output blob 62 | bool one_blob_only; 63 | 64 | // support inplace inference 65 | bool support_inplace; 66 | 67 | // support vulkan compute 68 | bool support_vulkan; 69 | 70 | // accept input blob with packed storage 71 | bool support_packing; 72 | 73 | public: 74 | // implement inference 75 | // return 0 if success 76 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs, const Option& opt) const; 77 | virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const; 78 | 79 | // implement inplace inference 80 | // return 0 if success 81 | virtual int forward_inplace(std::vector& bottom_top_blobs, const Option& opt) const; 82 | virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; 83 | 84 | #if NCNN_VULKAN 85 | public: 86 | // upload weight blob from host to device 87 | virtual int upload_model(VkTransfer& cmd, const Option& opt); 88 | 89 | public: 90 | // implement inference 91 | // return 0 if success 92 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs, VkCompute& cmd, const Option& opt) const; 93 | virtual int forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt) const; 94 | 95 | // implement inplace inference 96 | // return 0 if success 97 | virtual int forward_inplace(std::vector& bottom_top_blobs, VkCompute& cmd, const Option& opt) const; 98 | virtual int forward_inplace(VkMat& bottom_top_blob, VkCompute& cmd, const Option& opt) const; 99 | 100 | public: 101 | // assigned immediately after creating this layer 102 | const VulkanDevice* vkdev; 103 | #endif // NCNN_VULKAN 104 | 105 | public: 106 | // layer type index 107 | int typeindex; 108 | #if NCNN_STRING 109 | // layer type name 110 | std::string type; 111 | // layer name 112 | std::string name; 113 | #endif // NCNN_STRING 114 | // blob index which this layer needs as input 115 | std::vector bottoms; 116 | // blob index which this layer produces as output 117 | std::vector tops; 118 | }; 119 | 120 | // layer factory function 121 | typedef Layer* (*layer_creator_func)(); 122 | 123 | struct layer_registry_entry 124 | { 125 | #if NCNN_STRING 126 | // layer type name 127 | const char* name; 128 | #endif // NCNN_STRING 129 | // layer factory entry 130 | layer_creator_func creator; 131 | }; 132 | 133 | #if NCNN_STRING 134 | // get layer type from type name 135 | int layer_to_index(const char* type); 136 | // create layer from type name 137 | Layer* create_layer(const char* type); 138 | #endif // NCNN_STRING 139 | // create layer from layer type 140 | Layer* create_layer(int index); 141 | 142 | #define DEFINE_LAYER_CREATOR(name) \ 143 | ::ncnn::Layer* name##_layer_creator() { return new name; } 144 | 145 | } // namespace ncnn 146 | 147 | #endif // NCNN_LAYER_H 148 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/layer_type.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_LAYER_TYPE_H 16 | #define NCNN_LAYER_TYPE_H 17 | 18 | namespace ncnn { 19 | 20 | namespace LayerType { 21 | enum 22 | { 23 | #include "layer_type_enum.h" 24 | CustomBit = (1<<8), 25 | }; 26 | } // namespace LayerType 27 | 28 | } // namespace ncnn 29 | 30 | #endif // NCNN_LAYER_TYPE_H 31 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/layer_type_enum.h: -------------------------------------------------------------------------------- 1 | // Layer Type Enum header 2 | // 3 | // This file is auto-generated by cmake, don't edit it. 4 | 5 | AbsVal = 0, 6 | ArgMax = 1, 7 | BatchNorm = 2, 8 | Bias = 3, 9 | BNLL = 4, 10 | Concat = 5, 11 | Convolution = 6, 12 | Crop = 7, 13 | Deconvolution = 8, 14 | Dropout = 9, 15 | Eltwise = 10, 16 | ELU = 11, 17 | Embed = 12, 18 | Exp = 13, 19 | Flatten = 14, 20 | InnerProduct = 15, 21 | Input = 16, 22 | Log = 17, 23 | LRN = 18, 24 | MemoryData = 19, 25 | MVN = 20, 26 | Pooling = 21, 27 | Power = 22, 28 | PReLU = 23, 29 | Proposal = 24, 30 | Reduction = 25, 31 | ReLU = 26, 32 | Reshape = 27, 33 | ROIPooling = 28, 34 | Scale = 29, 35 | Sigmoid = 30, 36 | Slice = 31, 37 | Softmax = 32, 38 | Split = 33, 39 | SPP = 34, 40 | TanH = 35, 41 | Threshold = 36, 42 | Tile = 37, 43 | RNN = 38, 44 | LSTM = 39, 45 | BinaryOp = 40, 46 | UnaryOp = 41, 47 | ConvolutionDepthWise = 42, 48 | Padding = 43, 49 | Squeeze = 44, 50 | ExpandDims = 45, 51 | Normalize = 46, 52 | Permute = 47, 53 | PriorBox = 48, 54 | DetectionOutput = 49, 55 | Interp = 50, 56 | DeconvolutionDepthWise = 51, 57 | ShuffleChannel = 52, 58 | InstanceNorm = 53, 59 | Clip = 54, 60 | Reorg = 55, 61 | YoloDetectionOutput = 56, 62 | Quantize = 57, 63 | Dequantize = 58, 64 | Yolov3DetectionOutput = 59, 65 | PSROIPooling = 60, 66 | ROIAlign = 61, 67 | Packing = 62, 68 | Requantize = 63, 69 | Cast = 64, 70 | HardSigmoid = 65, 71 | SELU = 66, 72 | HardSwish = 67, 73 | Noop = 68, 74 | DarknetActivation = 69, 75 | DarknetShortcut = 70, 76 | Yolov1Detection = 71, 77 | Yolov3Detection = 72, 78 | 79 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/mat.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_MAT_H 16 | #define NCNN_MAT_H 17 | 18 | #include 19 | #include 20 | #include 21 | #if __ARM_NEON 22 | #include 23 | #endif 24 | #include "platform.h" 25 | #include "allocator.h" 26 | #include "option.h" 27 | #include "gpu.h" 28 | 29 | #if NCNN_VULKAN 30 | #include 31 | #endif // NCNN_VULKAN 32 | 33 | #if NCNN_PIXEL 34 | #if __ANDROID_API__ >= 9 35 | #include 36 | #include 37 | #endif // __ANDROID_API__ >= 9 38 | #endif // NCNN_PIXEL 39 | 40 | namespace ncnn { 41 | 42 | #if NCNN_VULKAN 43 | class VkMat; 44 | #endif // NCNN_VULKAN 45 | 46 | // the three dimension matrix 47 | class Mat 48 | { 49 | public: 50 | // empty 51 | Mat(); 52 | // vec 53 | Mat(int w, size_t elemsize = 4u, Allocator* allocator = 0); 54 | // image 55 | Mat(int w, int h, size_t elemsize = 4u, Allocator* allocator = 0); 56 | // dim 57 | Mat(int w, int h, int c, size_t elemsize = 4u, Allocator* allocator = 0); 58 | // packed vec 59 | Mat(int w, size_t elemsize, int elempack, Allocator* allocator = 0); 60 | // packed image 61 | Mat(int w, int h, size_t elemsize, int elempack, Allocator* allocator = 0); 62 | // packed dim 63 | Mat(int w, int h, int c, size_t elemsize, int elempack, Allocator* allocator = 0); 64 | // copy 65 | Mat(const Mat& m); 66 | // external vec 67 | Mat(int w, void* data, size_t elemsize = 4u, Allocator* allocator = 0); 68 | // external image 69 | Mat(int w, int h, void* data, size_t elemsize = 4u, Allocator* allocator = 0); 70 | // external dim 71 | Mat(int w, int h, int c, void* data, size_t elemsize = 4u, Allocator* allocator = 0); 72 | // external packed vec 73 | Mat(int w, void* data, size_t elemsize, int elempack, Allocator* allocator = 0); 74 | // external packed image 75 | Mat(int w, int h, void* data, size_t elemsize, int elempack, Allocator* allocator = 0); 76 | // external packed dim 77 | Mat(int w, int h, int c, void* data, size_t elemsize, int elempack, Allocator* allocator = 0); 78 | // release 79 | ~Mat(); 80 | // assign 81 | Mat& operator=(const Mat& m); 82 | // set all 83 | void fill(float v); 84 | void fill(int v); 85 | #if __ARM_NEON 86 | void fill(float32x4_t _v); 87 | #endif // __ARM_NEON 88 | template void fill(T v); 89 | // deep copy 90 | Mat clone(Allocator* allocator = 0) const; 91 | // reshape vec 92 | Mat reshape(int w, Allocator* allocator = 0) const; 93 | // reshape image 94 | Mat reshape(int w, int h, Allocator* allocator = 0) const; 95 | // reshape dim 96 | Mat reshape(int w, int h, int c, Allocator* allocator = 0) const; 97 | // allocate vec 98 | void create(int w, size_t elemsize = 4u, Allocator* allocator = 0); 99 | // allocate image 100 | void create(int w, int h, size_t elemsize = 4u, Allocator* allocator = 0); 101 | // allocate dim 102 | void create(int w, int h, int c, size_t elemsize = 4u, Allocator* allocator = 0); 103 | // allocate packed vec 104 | void create(int w, size_t elemsize, int elempack, Allocator* allocator = 0); 105 | // allocate packed image 106 | void create(int w, int h, size_t elemsize, int elempack, Allocator* allocator = 0); 107 | // allocate packed dim 108 | void create(int w, int h, int c, size_t elemsize, int elempack, Allocator* allocator = 0); 109 | // allocate like 110 | void create_like(const Mat& m, Allocator* allocator = 0); 111 | #if NCNN_VULKAN 112 | // allocate like 113 | void create_like(const VkMat& m, Allocator* allocator = 0); 114 | #endif // NCNN_VULKAN 115 | // refcount++ 116 | void addref(); 117 | // refcount-- 118 | void release(); 119 | 120 | bool empty() const; 121 | size_t total() const; 122 | 123 | // data reference 124 | Mat channel(int c); 125 | const Mat channel(int c) const; 126 | float* row(int y); 127 | const float* row(int y) const; 128 | template T* row(int y); 129 | template const T* row(int y) const; 130 | 131 | // range reference 132 | Mat channel_range(int c, int channels); 133 | const Mat channel_range(int c, int channels) const; 134 | Mat row_range(int y, int rows); 135 | const Mat row_range(int y, int rows) const; 136 | Mat range(int x, int n); 137 | const Mat range(int x, int n) const; 138 | 139 | // access raw data 140 | template operator T*(); 141 | template operator const T*() const; 142 | 143 | // convenient access float vec element 144 | float& operator[](int i); 145 | const float& operator[](int i) const; 146 | 147 | #if NCNN_PIXEL 148 | enum 149 | { 150 | PIXEL_CONVERT_SHIFT = 16, 151 | PIXEL_FORMAT_MASK = 0x0000ffff, 152 | PIXEL_CONVERT_MASK = 0xffff0000, 153 | 154 | PIXEL_RGB = 1, 155 | PIXEL_BGR = 2, 156 | PIXEL_GRAY = 3, 157 | PIXEL_RGBA = 4, 158 | 159 | PIXEL_RGB2BGR = PIXEL_RGB | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 160 | PIXEL_RGB2GRAY = PIXEL_RGB | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 161 | PIXEL_RGB2RGBA = PIXEL_RGB | (PIXEL_RGBA << PIXEL_CONVERT_SHIFT), 162 | 163 | PIXEL_BGR2RGB = PIXEL_BGR | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 164 | PIXEL_BGR2GRAY = PIXEL_BGR | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 165 | PIXEL_BGR2RGBA = PIXEL_BGR | (PIXEL_RGBA << PIXEL_CONVERT_SHIFT), 166 | 167 | PIXEL_GRAY2RGB = PIXEL_GRAY | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 168 | PIXEL_GRAY2BGR = PIXEL_GRAY | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 169 | PIXEL_GRAY2RGBA = PIXEL_GRAY | (PIXEL_RGBA << PIXEL_CONVERT_SHIFT), 170 | 171 | PIXEL_RGBA2RGB = PIXEL_RGBA | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 172 | PIXEL_RGBA2BGR = PIXEL_RGBA | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 173 | PIXEL_RGBA2GRAY = PIXEL_RGBA | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 174 | }; 175 | // convenient construct from pixel data 176 | static Mat from_pixels(const unsigned char* pixels, int type, int w, int h, Allocator* allocator = 0); 177 | // convenient construct from pixel data with stride(bytes-per-row) parameter 178 | static Mat from_pixels(const unsigned char* pixels, int type, int w, int h, int stride, Allocator* allocator = 0); 179 | // convenient construct from pixel data and resize to specific size 180 | static Mat from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int target_width, int target_height, Allocator* allocator = 0); 181 | // convenient construct from pixel data and resize to specific size with stride(bytes-per-row) parameter 182 | static Mat from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int stride, int target_width, int target_height, Allocator* allocator = 0); 183 | 184 | // convenient export to pixel data 185 | void to_pixels(unsigned char* pixels, int type) const; 186 | // convenient export to pixel data with stride(bytes-per-row) parameter 187 | void to_pixels(unsigned char* pixels, int type, int stride) const; 188 | // convenient export to pixel data and resize to specific size 189 | void to_pixels_resize(unsigned char* pixels, int type, int target_width, int target_height) const; 190 | // convenient export to pixel data and resize to specific size with stride(bytes-per-row) parameter 191 | void to_pixels_resize(unsigned char* pixels, int type, int target_width, int target_height, int target_stride) const; 192 | 193 | #if __ANDROID_API__ >= 9 194 | // convenient construct from android Bitmap 195 | static Mat from_android_bitmap(JNIEnv* env, jobject bitmap, int type_to, Allocator* allocator = 0); 196 | // convenient construct from android Bitmap and resize to specific size 197 | static Mat from_android_bitmap_resize(JNIEnv* env, jobject bitmap, int type_to, int target_width, int target_height, Allocator* allocator = 0); 198 | // convenient export to android Bitmap and resize to the android Bitmap size 199 | void to_android_bitmap(JNIEnv* env, jobject bitmap, int type_from) const; 200 | #endif // __ANDROID_API__ >= 9 201 | #endif // NCNN_PIXEL 202 | 203 | // substract channel-wise mean values, then multiply by normalize values, pass 0 to skip 204 | void substract_mean_normalize(const float* mean_vals, const float* norm_vals); 205 | 206 | // convenient construct from half precisoin floating point data 207 | static Mat from_float16(const unsigned short* data, int size); 208 | 209 | // pointer to the data 210 | void* data; 211 | 212 | // pointer to the reference counter 213 | // when points to user-allocated data, the pointer is NULL 214 | int* refcount; 215 | 216 | // element size in bytes 217 | // 4 = float32/int32 218 | // 2 = float16 219 | // 1 = int8/uint8 220 | // 0 = empty 221 | size_t elemsize; 222 | 223 | // packed count inside element 224 | // c/1-h-w-1 h/1-w-1 w/1-1 scalar 225 | // c/4-h-w-4 h/4-w-4 w/4-4 sse/neon 226 | // c/8-h-w-8 h/8-w-8 w/8-8 avx/fp16 227 | int elempack; 228 | 229 | // the allocator 230 | Allocator* allocator; 231 | 232 | // the dimensionality 233 | int dims; 234 | 235 | int w; 236 | int h; 237 | int c; 238 | 239 | size_t cstep; 240 | }; 241 | 242 | #if NCNN_VULKAN 243 | 244 | // the three dimension matrix, vulkan version 245 | class VkMat 246 | { 247 | public: 248 | // empty 249 | VkMat(); 250 | // vec 251 | VkMat(int w, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 252 | // image 253 | VkMat(int w, int h, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 254 | // dim 255 | VkMat(int w, int h, int c, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 256 | // packed vec 257 | VkMat(int w, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 258 | // packed image 259 | VkMat(int w, int h, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 260 | // packed dim 261 | VkMat(int w, int h, int c, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 262 | // copy 263 | VkMat(const VkMat& m); 264 | // external vec 265 | VkMat(int w, VkBufferMemory* data, size_t offset, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 266 | // external image 267 | VkMat(int w, int h, VkBufferMemory* data, size_t offset, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 268 | // external dim 269 | VkMat(int w, int h, int c, VkBufferMemory* data, size_t offset, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 270 | // external packed vec 271 | VkMat(int w, VkBufferMemory* data, size_t offset, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 272 | // external packed image 273 | VkMat(int w, int h, VkBufferMemory* data, size_t offset, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 274 | // external packed dim 275 | VkMat(int w, int h, int c, VkBufferMemory* data, size_t offset, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 276 | // release 277 | ~VkMat(); 278 | // assign 279 | VkMat& operator=(const VkMat& m); 280 | // allocate vec 281 | void create(int w, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 282 | // allocate image 283 | void create(int w, int h, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 284 | // allocate dim 285 | void create(int w, int h, int c, size_t elemsize, VkAllocator* allocator, VkAllocator* staging_allocator); 286 | // allocate packed vec 287 | void create(int w, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 288 | // allocate packed image 289 | void create(int w, int h, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 290 | // allocate packed dim 291 | void create(int w, int h, int c, size_t elemsize, int elempack, VkAllocator* allocator, VkAllocator* staging_allocator); 292 | // allocate like 293 | void create_like(const Mat& m, VkAllocator* allocator, VkAllocator* staging_allocator); 294 | // allocate like 295 | void create_like(const VkMat& m, VkAllocator* allocator, VkAllocator* staging_allocator); 296 | 297 | // staging buffer 298 | void prepare_staging_buffer(); 299 | void discard_staging_buffer(); 300 | 301 | // copy 302 | void upload(const Mat& m); 303 | void download(Mat& m) const; 304 | 305 | // mapped 306 | Mat mapped() const; 307 | void* mapped_ptr() const; 308 | 309 | // refcount++ 310 | void addref(); 311 | // refcount-- 312 | void release(); 313 | 314 | bool empty() const; 315 | size_t total() const; 316 | 317 | // data reference 318 | VkMat channel(int c); 319 | const VkMat channel(int c) const; 320 | 321 | // range reference 322 | VkMat channel_range(int c, int channels); 323 | const VkMat channel_range(int c, int channels) const; 324 | VkMat row_range(int y, int rows); 325 | const VkMat row_range(int y, int rows) const; 326 | VkMat range(int x, int n); 327 | const VkMat range(int x, int n) const; 328 | 329 | // low-level reference 330 | VkBuffer buffer() const; 331 | size_t buffer_offset() const; 332 | VkBuffer staging_buffer() const; 333 | size_t staging_buffer_offset() const; 334 | 335 | // device buffer 336 | VkBufferMemory* data; 337 | // subrange offset 338 | size_t offset; 339 | 340 | // staging buffer 341 | VkBufferMemory* staging_data; 342 | 343 | // pointer to the reference counter 344 | // when points to user-allocated data, the pointer is NULL 345 | int* refcount; 346 | int* staging_refcount; 347 | 348 | // element size in bytes 349 | // 4 = float32/int32 350 | // 2 = float16 351 | // 1 = int8/uint8 352 | // 0 = empty 353 | size_t elemsize; 354 | 355 | // packed count inside element 356 | // c/1-h-w-1 h/1-w-1 w/1-1 scalar 357 | // c/4-h-w-4 h/4-w-4 w/4-4 sse/neon 358 | // c/8-h-w-8 h/8-w-8 w/8-8 avx/fp16 359 | int elempack; 360 | 361 | // the allocator 362 | VkAllocator* allocator; 363 | VkAllocator* staging_allocator; 364 | 365 | // the dimensionality 366 | int dims; 367 | 368 | int w; 369 | int h; 370 | int c; 371 | 372 | size_t cstep; 373 | }; 374 | 375 | // type for vulkan specialization constant and push constant 376 | union vk_specialization_type { int i; float f; uint32_t u32; }; 377 | union vk_constant_type { int i; float f; }; 378 | #endif // NCNN_VULKAN 379 | 380 | // misc function 381 | #if NCNN_PIXEL 382 | // convert yuv420sp(nv21) to rgb, the fast approximate version 383 | void yuv420sp2rgb(const unsigned char* yuv420sp, int w, int h, unsigned char* rgb); 384 | // image pixel bilinear resize 385 | void resize_bilinear_c1(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 386 | void resize_bilinear_c2(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 387 | void resize_bilinear_c3(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 388 | void resize_bilinear_c4(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 389 | // image pixel bilinear resize with stride(bytes-per-row) parameter 390 | void resize_bilinear_c1(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride); 391 | void resize_bilinear_c2(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride); 392 | void resize_bilinear_c3(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride); 393 | void resize_bilinear_c4(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride); 394 | // image pixel bilinear resize, convenient wrapper for yuv420sp(nv21) 395 | void resize_bilinear_yuv420sp(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 396 | #endif // NCNN_PIXEL 397 | #if NCNN_PIXEL_ROTATE 398 | // type is the from type, 6 means rotating from 6 to 1 399 | // 400 | // 1 2 3 4 5 6 7 8 401 | // 402 | // 888888 888888 88 88 8888888888 88 88 8888888888 403 | // 88 88 88 88 88 88 88 88 88 88 88 88 404 | // 8888 8888 8888 8888 88 8888888888 8888888888 88 405 | // 88 88 88 88 406 | // 88 88 888888 888888 407 | // 408 | // ref http://sylvana.net/jpegcrop/exif_orientation.html 409 | // image pixel kanna rotate 410 | void kanna_rotate_c1(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h, int type); 411 | void kanna_rotate_c2(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h, int type); 412 | void kanna_rotate_c3(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h, int type); 413 | void kanna_rotate_c4(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h, int type); 414 | // image pixel kanna rotate with stride(bytes-per-row) parameter 415 | void kanna_rotate_c1(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride, int type); 416 | void kanna_rotate_c2(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride, int type); 417 | void kanna_rotate_c3(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride, int type); 418 | void kanna_rotate_c4(const unsigned char* src, int srcw, int srch, int srcstride, unsigned char* dst, int w, int h, int stride, int type); 419 | // image pixel kanna rotate, convenient wrapper for yuv420sp(nv21) 420 | void kanna_rotate_yuv420sp(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h, int type); 421 | #endif // NCNN_PIXEL_ROTATE 422 | 423 | // mat process 424 | enum 425 | { 426 | BORDER_CONSTANT = 0, 427 | BORDER_REPLICATE = 1, 428 | }; 429 | void copy_make_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int type, float v, const Option& opt = Option()); 430 | void copy_cut_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, const Option& opt = Option()); 431 | void resize_bilinear(const Mat& src, Mat& dst, int w, int h, const Option& opt = Option()); 432 | void resize_bicubic(const Mat& src, Mat& dst, int w, int h, const Option& opt = Option()); 433 | void convert_packing(const Mat& src, Mat& dst, int elempack, const Option& opt = Option()); 434 | void cast_float32_to_float16(const Mat& src, Mat& dst, const Option& opt = Option()); 435 | void cast_float16_to_float32(const Mat& src, Mat& dst, const Option& opt = Option()); 436 | 437 | inline Mat::Mat() 438 | : data(0), refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 439 | { 440 | } 441 | 442 | inline Mat::Mat(int _w, size_t _elemsize, Allocator* _allocator) 443 | : data(0), refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 444 | { 445 | create(_w, _elemsize, _allocator); 446 | } 447 | 448 | inline Mat::Mat(int _w, int _h, size_t _elemsize, Allocator* _allocator) 449 | : data(0), refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 450 | { 451 | create(_w, _h, _elemsize, _allocator); 452 | } 453 | 454 | inline Mat::Mat(int _w, int _h, int _c, size_t _elemsize, Allocator* _allocator) 455 | : data(0), refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 456 | { 457 | create(_w, _h, _c, _elemsize, _allocator); 458 | } 459 | 460 | inline Mat::Mat(int _w, size_t _elemsize, int _elempack, Allocator* _allocator) 461 | : data(0), refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 462 | { 463 | create(_w, _elemsize, _elempack, _allocator); 464 | } 465 | 466 | inline Mat::Mat(int _w, int _h, size_t _elemsize, int _elempack, Allocator* _allocator) 467 | : data(0), refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 468 | { 469 | create(_w, _h, _elemsize, _elempack, _allocator); 470 | } 471 | 472 | inline Mat::Mat(int _w, int _h, int _c, size_t _elemsize, int _elempack, Allocator* _allocator) 473 | : data(0), refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 474 | { 475 | create(_w, _h, _c, _elemsize, _elempack, _allocator); 476 | } 477 | 478 | inline Mat::Mat(const Mat& m) 479 | : data(m.data), refcount(m.refcount), elemsize(m.elemsize), elempack(m.elempack), allocator(m.allocator), dims(m.dims), w(m.w), h(m.h), c(m.c), cstep(m.cstep) 480 | { 481 | if (refcount) 482 | NCNN_XADD(refcount, 1); 483 | } 484 | 485 | inline Mat::Mat(int _w, void* _data, size_t _elemsize, Allocator* _allocator) 486 | : data(_data), refcount(0), elemsize(_elemsize), elempack(1), allocator(_allocator), dims(1), w(_w), h(1), c(1) 487 | { 488 | cstep = w; 489 | } 490 | 491 | inline Mat::Mat(int _w, int _h, void* _data, size_t _elemsize, Allocator* _allocator) 492 | : data(_data), refcount(0), elemsize(_elemsize), elempack(1), allocator(_allocator), dims(2), w(_w), h(_h), c(1) 493 | { 494 | cstep = w * h; 495 | } 496 | 497 | inline Mat::Mat(int _w, int _h, int _c, void* _data, size_t _elemsize, Allocator* _allocator) 498 | : data(_data), refcount(0), elemsize(_elemsize), elempack(1), allocator(_allocator), dims(3), w(_w), h(_h), c(_c) 499 | { 500 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 501 | } 502 | 503 | inline Mat::Mat(int _w, void* _data, size_t _elemsize, int _elempack, Allocator* _allocator) 504 | : data(_data), refcount(0), elemsize(_elemsize), elempack(_elempack), allocator(_allocator), dims(1), w(_w), h(1), c(1) 505 | { 506 | cstep = w; 507 | } 508 | 509 | inline Mat::Mat(int _w, int _h, void* _data, size_t _elemsize, int _elempack, Allocator* _allocator) 510 | : data(_data), refcount(0), elemsize(_elemsize), elempack(_elempack), allocator(_allocator), dims(2), w(_w), h(_h), c(1) 511 | { 512 | cstep = w * h; 513 | } 514 | 515 | inline Mat::Mat(int _w, int _h, int _c, void* _data, size_t _elemsize, int _elempack, Allocator* _allocator) 516 | : data(_data), refcount(0), elemsize(_elemsize), elempack(_elempack), allocator(_allocator), dims(3), w(_w), h(_h), c(_c) 517 | { 518 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 519 | } 520 | 521 | inline Mat::~Mat() 522 | { 523 | release(); 524 | } 525 | 526 | inline Mat& Mat::operator=(const Mat& m) 527 | { 528 | if (this == &m) 529 | return *this; 530 | 531 | if (m.refcount) 532 | NCNN_XADD(m.refcount, 1); 533 | 534 | release(); 535 | 536 | data = m.data; 537 | refcount = m.refcount; 538 | elemsize = m.elemsize; 539 | elempack = m.elempack; 540 | allocator = m.allocator; 541 | 542 | dims = m.dims; 543 | w = m.w; 544 | h = m.h; 545 | c = m.c; 546 | 547 | cstep = m.cstep; 548 | 549 | return *this; 550 | } 551 | 552 | inline void Mat::fill(float _v) 553 | { 554 | int size = (int)total(); 555 | float* ptr = (float*)data; 556 | 557 | #if __ARM_NEON 558 | int nn = size >> 2; 559 | int remain = size - (nn << 2); 560 | #else 561 | int remain = size; 562 | #endif // __ARM_NEON 563 | 564 | #if __ARM_NEON 565 | float32x4_t _c = vdupq_n_f32(_v); 566 | #if __aarch64__ 567 | if (nn > 0) 568 | { 569 | asm volatile ( 570 | "0: \n" 571 | "subs %w0, %w0, #1 \n" 572 | "st1 {%4.4s}, [%1], #16 \n" 573 | "bne 0b \n" 574 | : "=r"(nn), // %0 575 | "=r"(ptr) // %1 576 | : "0"(nn), 577 | "1"(ptr), 578 | "w"(_c) // %4 579 | : "cc", "memory" 580 | ); 581 | } 582 | #else 583 | if (nn > 0) 584 | { 585 | asm volatile( 586 | "0: \n" 587 | "subs %0, #1 \n" 588 | "vst1.f32 {%e4-%f4}, [%1 :128]!\n" 589 | "bne 0b \n" 590 | : "=r"(nn), // %0 591 | "=r"(ptr) // %1 592 | : "0"(nn), 593 | "1"(ptr), 594 | "w"(_c) // %4 595 | : "cc", "memory" 596 | ); 597 | } 598 | #endif // __aarch64__ 599 | #endif // __ARM_NEON 600 | for (; remain>0; remain--) 601 | { 602 | *ptr++ = _v; 603 | } 604 | } 605 | 606 | inline void Mat::fill(int _v) 607 | { 608 | int size = (int)total(); 609 | int* ptr = (int*)data; 610 | 611 | #if __ARM_NEON 612 | int nn = size >> 2; 613 | int remain = size - (nn << 2); 614 | #else 615 | int remain = size; 616 | #endif // __ARM_NEON 617 | 618 | #if __ARM_NEON 619 | int32x4_t _c = vdupq_n_s32(_v); 620 | #if __aarch64__ 621 | if (nn > 0) 622 | { 623 | asm volatile ( 624 | "0: \n" 625 | "subs %w0, %w0, #1 \n" 626 | "st1 {%4.4s}, [%1], #16 \n" 627 | "bne 0b \n" 628 | : "=r"(nn), // %0 629 | "=r"(ptr) // %1 630 | : "0"(nn), 631 | "1"(ptr), 632 | "w"(_c) // %4 633 | : "cc", "memory" 634 | ); 635 | } 636 | #else 637 | if (nn > 0) 638 | { 639 | asm volatile( 640 | "0: \n" 641 | "subs %0, #1 \n" 642 | "vst1.s32 {%e4-%f4}, [%1 :128]!\n" 643 | "bne 0b \n" 644 | : "=r"(nn), // %0 645 | "=r"(ptr) // %1 646 | : "0"(nn), 647 | "1"(ptr), 648 | "w"(_c) // %4 649 | : "cc", "memory" 650 | ); 651 | } 652 | #endif // __aarch64__ 653 | #endif // __ARM_NEON 654 | for (; remain>0; remain--) 655 | { 656 | *ptr++ = _v; 657 | } 658 | } 659 | 660 | #if __ARM_NEON 661 | inline void Mat::fill(float32x4_t _v) 662 | { 663 | int size = total(); 664 | float* ptr = (float*)data; 665 | for (int i=0; i 674 | inline void Mat::fill(T _v) 675 | { 676 | int size = total(); 677 | T* ptr = (T*)data; 678 | for (int i=0; i 0) 698 | { 699 | memcpy(m.data, data, total() * elemsize); 700 | } 701 | 702 | return m; 703 | } 704 | 705 | inline Mat Mat::reshape(int _w, Allocator* _allocator) const 706 | { 707 | if (w * h * c != _w) 708 | return Mat(); 709 | 710 | if (dims == 3 && cstep != (size_t)w * h) 711 | { 712 | Mat m; 713 | m.create(_w, elemsize, elempack, _allocator); 714 | 715 | // flatten 716 | for (int i=0; i 0) 832 | { 833 | size_t totalsize = alignSize(total() * elemsize, 4); 834 | if (allocator) 835 | data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount)); 836 | else 837 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 838 | refcount = (int*)(((unsigned char*)data) + totalsize); 839 | *refcount = 1; 840 | } 841 | } 842 | 843 | inline void Mat::create(int _w, int _h, size_t _elemsize, Allocator* _allocator) 844 | { 845 | if (dims == 2 && w == _w && h == _h && elemsize == _elemsize && elempack == 1 && allocator == _allocator) 846 | return; 847 | 848 | release(); 849 | 850 | elemsize = _elemsize; 851 | elempack = 1; 852 | allocator = _allocator; 853 | 854 | dims = 2; 855 | w = _w; 856 | h = _h; 857 | c = 1; 858 | 859 | cstep = w * h; 860 | 861 | if (total() > 0) 862 | { 863 | size_t totalsize = alignSize(total() * elemsize, 4); 864 | if (allocator) 865 | data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount)); 866 | else 867 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 868 | refcount = (int*)(((unsigned char*)data) + totalsize); 869 | *refcount = 1; 870 | } 871 | } 872 | 873 | inline void Mat::create(int _w, int _h, int _c, size_t _elemsize, Allocator* _allocator) 874 | { 875 | if (dims == 3 && w == _w && h == _h && c == _c && elemsize == _elemsize && elempack == 1 && allocator == _allocator) 876 | return; 877 | 878 | release(); 879 | 880 | elemsize = _elemsize; 881 | elempack = 1; 882 | allocator = _allocator; 883 | 884 | dims = 3; 885 | w = _w; 886 | h = _h; 887 | c = _c; 888 | 889 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 890 | 891 | if (total() > 0) 892 | { 893 | size_t totalsize = alignSize(total() * elemsize, 4); 894 | if (allocator) 895 | data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount)); 896 | else 897 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 898 | refcount = (int*)(((unsigned char*)data) + totalsize); 899 | *refcount = 1; 900 | } 901 | } 902 | 903 | inline void Mat::create(int _w, size_t _elemsize, int _elempack, Allocator* _allocator) 904 | { 905 | if (dims == 1 && w == _w && elemsize == _elemsize && elempack == _elempack && allocator == _allocator) 906 | return; 907 | 908 | release(); 909 | 910 | elemsize = _elemsize; 911 | elempack = _elempack; 912 | allocator = _allocator; 913 | 914 | dims = 1; 915 | w = _w; 916 | h = 1; 917 | c = 1; 918 | 919 | cstep = w; 920 | 921 | if (total() > 0) 922 | { 923 | size_t totalsize = alignSize(total() * elemsize, 4); 924 | if (allocator) 925 | data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount)); 926 | else 927 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 928 | refcount = (int*)(((unsigned char*)data) + totalsize); 929 | *refcount = 1; 930 | } 931 | } 932 | 933 | inline void Mat::create(int _w, int _h, size_t _elemsize, int _elempack, Allocator* _allocator) 934 | { 935 | if (dims == 2 && w == _w && h == _h && elemsize == _elemsize && elempack == _elempack && allocator == _allocator) 936 | return; 937 | 938 | release(); 939 | 940 | elemsize = _elemsize; 941 | elempack = _elempack; 942 | allocator = _allocator; 943 | 944 | dims = 2; 945 | w = _w; 946 | h = _h; 947 | c = 1; 948 | 949 | cstep = w * h; 950 | 951 | if (total() > 0) 952 | { 953 | size_t totalsize = alignSize(total() * elemsize, 4); 954 | if (allocator) 955 | data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount)); 956 | else 957 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 958 | refcount = (int*)(((unsigned char*)data) + totalsize); 959 | *refcount = 1; 960 | } 961 | } 962 | 963 | inline void Mat::create(int _w, int _h, int _c, size_t _elemsize, int _elempack, Allocator* _allocator) 964 | { 965 | if (dims == 3 && w == _w && h == _h && c == _c && elemsize == _elemsize && elempack == _elempack && allocator == _allocator) 966 | return; 967 | 968 | release(); 969 | 970 | elemsize = _elemsize; 971 | elempack = _elempack; 972 | allocator = _allocator; 973 | 974 | dims = 3; 975 | w = _w; 976 | h = _h; 977 | c = _c; 978 | 979 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 980 | 981 | if (total() > 0) 982 | { 983 | size_t totalsize = alignSize(total() * elemsize, 4); 984 | if (allocator) 985 | data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount)); 986 | else 987 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 988 | refcount = (int*)(((unsigned char*)data) + totalsize); 989 | *refcount = 1; 990 | } 991 | } 992 | 993 | inline void Mat::create_like(const Mat& m, Allocator* _allocator) 994 | { 995 | if (m.dims == 1) 996 | create(m.w, m.elemsize, m.elempack, _allocator); 997 | else if (m.dims == 2) 998 | create(m.w, m.h, m.elemsize, m.elempack, _allocator); 999 | else if (m.dims == 3) 1000 | create(m.w, m.h, m.c, m.elemsize, m.elempack, _allocator); 1001 | } 1002 | 1003 | #if NCNN_VULKAN 1004 | inline void Mat::create_like(const VkMat& m, Allocator* _allocator) 1005 | { 1006 | if (m.dims == 1) 1007 | create(m.w, m.elemsize, m.elempack, _allocator); 1008 | else if (m.dims == 2) 1009 | create(m.w, m.h, m.elemsize, m.elempack, _allocator); 1010 | else if (m.dims == 3) 1011 | create(m.w, m.h, m.c, m.elemsize, m.elempack, _allocator); 1012 | } 1013 | #endif // NCNN_VULKAN 1014 | 1015 | inline void Mat::addref() 1016 | { 1017 | if (refcount) 1018 | NCNN_XADD(refcount, 1); 1019 | } 1020 | 1021 | inline void Mat::release() 1022 | { 1023 | if (refcount && NCNN_XADD(refcount, -1) == 1) 1024 | { 1025 | if (allocator) 1026 | allocator->fastFree(data); 1027 | else 1028 | fastFree(data); 1029 | } 1030 | 1031 | data = 0; 1032 | 1033 | elemsize = 0; 1034 | elempack = 0; 1035 | 1036 | dims = 0; 1037 | w = 0; 1038 | h = 0; 1039 | c = 0; 1040 | 1041 | cstep = 0; 1042 | 1043 | refcount = 0; 1044 | } 1045 | 1046 | inline bool Mat::empty() const 1047 | { 1048 | return data == 0 || total() == 0; 1049 | } 1050 | 1051 | inline size_t Mat::total() const 1052 | { 1053 | return cstep * c; 1054 | } 1055 | 1056 | inline Mat Mat::channel(int _c) 1057 | { 1058 | return Mat(w, h, (unsigned char*)data + cstep * _c * elemsize, elemsize, elempack, allocator); 1059 | } 1060 | 1061 | inline const Mat Mat::channel(int _c) const 1062 | { 1063 | return Mat(w, h, (unsigned char*)data + cstep * _c * elemsize, elemsize, elempack, allocator); 1064 | } 1065 | 1066 | inline float* Mat::row(int y) 1067 | { 1068 | return (float*)((unsigned char*)data + w * y * elemsize); 1069 | } 1070 | 1071 | inline const float* Mat::row(int y) const 1072 | { 1073 | return (const float*)((unsigned char*)data + w * y * elemsize); 1074 | } 1075 | 1076 | template 1077 | inline T* Mat::row(int y) 1078 | { 1079 | return (T*)((unsigned char*)data + w * y * elemsize); 1080 | } 1081 | 1082 | template 1083 | inline const T* Mat::row(int y) const 1084 | { 1085 | return (const T*)((unsigned char*)data + w * y * elemsize); 1086 | } 1087 | 1088 | inline Mat Mat::channel_range(int _c, int channels) 1089 | { 1090 | return Mat(w, h, channels, (unsigned char*)data + cstep * _c * elemsize, elemsize, elempack, allocator); 1091 | } 1092 | 1093 | inline const Mat Mat::channel_range(int _c, int channels) const 1094 | { 1095 | return Mat(w, h, channels, (unsigned char*)data + cstep * _c * elemsize, elemsize, elempack, allocator); 1096 | } 1097 | 1098 | inline Mat Mat::row_range(int y, int rows) 1099 | { 1100 | return Mat(w, rows, (unsigned char*)data + w * y * elemsize, elemsize, elempack, allocator); 1101 | } 1102 | 1103 | inline const Mat Mat::row_range(int y, int rows) const 1104 | { 1105 | return Mat(w, rows, (unsigned char*)data + w * y * elemsize, elemsize, elempack, allocator); 1106 | } 1107 | 1108 | inline Mat Mat::range(int x, int n) 1109 | { 1110 | return Mat(n, (unsigned char*)data + x * elemsize, elemsize, elempack, allocator); 1111 | } 1112 | 1113 | inline const Mat Mat::range(int x, int n) const 1114 | { 1115 | return Mat(n, (unsigned char*)data + x * elemsize, elemsize, elempack, allocator); 1116 | } 1117 | 1118 | template 1119 | inline Mat::operator T*() 1120 | { 1121 | return (T*)data; 1122 | } 1123 | 1124 | template 1125 | inline Mat::operator const T*() const 1126 | { 1127 | return (const T*)data; 1128 | } 1129 | 1130 | inline float& Mat::operator[](int i) 1131 | { 1132 | return ((float*)data)[i]; 1133 | } 1134 | 1135 | inline const float& Mat::operator[](int i) const 1136 | { 1137 | return ((const float*)data)[i]; 1138 | } 1139 | 1140 | #if NCNN_VULKAN 1141 | 1142 | inline VkMat::VkMat() 1143 | : data(0), offset(0), staging_data(0), refcount(0), staging_refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 1144 | { 1145 | } 1146 | 1147 | inline VkMat::VkMat(int _w, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1148 | : data(0), offset(0), staging_data(0), refcount(0), staging_refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 1149 | { 1150 | create(_w, _elemsize, _allocator, _staging_allocator); 1151 | } 1152 | 1153 | inline VkMat::VkMat(int _w, int _h, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1154 | : data(0), offset(0), staging_data(0), refcount(0), staging_refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 1155 | { 1156 | create(_w, _h, _elemsize, _allocator, _staging_allocator); 1157 | } 1158 | 1159 | inline VkMat::VkMat(int _w, int _h, int _c, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1160 | : data(0), offset(0), staging_data(0), refcount(0), staging_refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 1161 | { 1162 | create(_w, _h, _c, _elemsize, _allocator, _staging_allocator); 1163 | } 1164 | 1165 | inline VkMat::VkMat(int _w, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1166 | : data(0), offset(0), staging_data(0), refcount(0), staging_refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 1167 | { 1168 | create(_w, _elemsize, _elempack, _allocator, _staging_allocator); 1169 | } 1170 | 1171 | inline VkMat::VkMat(int _w, int _h, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1172 | : data(0), offset(0), staging_data(0), refcount(0), staging_refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 1173 | { 1174 | create(_w, _h, _elemsize, _elempack, _allocator, _staging_allocator); 1175 | } 1176 | 1177 | inline VkMat::VkMat(int _w, int _h, int _c, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1178 | : data(0), offset(0), staging_data(0), refcount(0), staging_refcount(0), elemsize(0), elempack(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0) 1179 | { 1180 | create(_w, _h, _c, _elemsize, _elempack, _allocator, _staging_allocator); 1181 | } 1182 | 1183 | inline VkMat::VkMat(const VkMat& m) 1184 | : data(m.data), offset(m.offset), staging_data(m.staging_data), refcount(m.refcount), staging_refcount(m.staging_refcount), elemsize(m.elemsize), elempack(m.elempack), allocator(m.allocator), staging_allocator(m.staging_allocator), dims(m.dims), w(m.w), h(m.h), c(m.c) 1185 | { 1186 | if (refcount) 1187 | NCNN_XADD(refcount, 1); 1188 | 1189 | if (staging_refcount) 1190 | NCNN_XADD(staging_refcount, 1); 1191 | 1192 | cstep = m.cstep; 1193 | } 1194 | 1195 | inline VkMat::VkMat(int _w, VkBufferMemory* _data, size_t _offset, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1196 | : data(_data), offset(_offset), staging_data(0), refcount(0), staging_refcount(0), elemsize(_elemsize), elempack(1), allocator(_allocator), staging_allocator(_staging_allocator), dims(1), w(_w), h(1), c(1) 1197 | { 1198 | cstep = w; 1199 | } 1200 | 1201 | inline VkMat::VkMat(int _w, int _h, VkBufferMemory* _data, size_t _offset, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1202 | : data(_data), offset(_offset), staging_data(0), refcount(0), staging_refcount(0), elemsize(_elemsize), elempack(1), allocator(_allocator), staging_allocator(_staging_allocator), dims(2), w(_w), h(_h), c(1) 1203 | { 1204 | cstep = w * h; 1205 | } 1206 | 1207 | inline VkMat::VkMat(int _w, int _h, int _c, VkBufferMemory* _data, size_t _offset, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1208 | : data(_data), offset(_offset), staging_data(0), refcount(0), staging_refcount(0), elemsize(_elemsize), elempack(1), allocator(_allocator), staging_allocator(_staging_allocator), dims(3), w(_w), h(_h), c(_c) 1209 | { 1210 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 1211 | } 1212 | 1213 | inline VkMat::VkMat(int _w, VkBufferMemory* _data, size_t _offset, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1214 | : data(_data), offset(_offset), staging_data(0), refcount(0), staging_refcount(0), elemsize(_elemsize), elempack(_elempack), allocator(_allocator), staging_allocator(_staging_allocator), dims(1), w(_w), h(1), c(1) 1215 | { 1216 | cstep = w; 1217 | } 1218 | 1219 | inline VkMat::VkMat(int _w, int _h, VkBufferMemory* _data, size_t _offset, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1220 | : data(_data), offset(_offset), staging_data(0), refcount(0), staging_refcount(0), elemsize(_elemsize), elempack(_elempack), allocator(_allocator), staging_allocator(_staging_allocator), dims(2), w(_w), h(_h), c(1) 1221 | { 1222 | cstep = w * h; 1223 | } 1224 | 1225 | inline VkMat::VkMat(int _w, int _h, int _c, VkBufferMemory* _data, size_t _offset, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1226 | : data(_data), offset(_offset), staging_data(0), refcount(0), staging_refcount(0), elemsize(_elemsize), elempack(_elempack), allocator(_allocator), staging_allocator(_staging_allocator), dims(3), w(_w), h(_h), c(_c) 1227 | { 1228 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 1229 | } 1230 | 1231 | inline VkMat::~VkMat() 1232 | { 1233 | release(); 1234 | } 1235 | 1236 | inline VkMat& VkMat::operator=(const VkMat& m) 1237 | { 1238 | if (this == &m) 1239 | return *this; 1240 | 1241 | if (m.refcount) 1242 | NCNN_XADD(m.refcount, 1); 1243 | 1244 | if (m.staging_refcount) 1245 | NCNN_XADD(m.staging_refcount, 1); 1246 | 1247 | release(); 1248 | 1249 | data = m.data; 1250 | offset = m.offset; 1251 | staging_data = m.staging_data; 1252 | refcount = m.refcount; 1253 | staging_refcount = m.staging_refcount; 1254 | elemsize = m.elemsize; 1255 | elempack = m.elempack; 1256 | allocator = m.allocator; 1257 | staging_allocator = m.staging_allocator; 1258 | 1259 | dims = m.dims; 1260 | w = m.w; 1261 | h = m.h; 1262 | c = m.c; 1263 | 1264 | cstep = m.cstep; 1265 | 1266 | return *this; 1267 | } 1268 | 1269 | inline void VkMat::create(int _w, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1270 | { 1271 | if (dims == 1 && w == _w && elemsize == _elemsize && elempack == 1 && allocator == _allocator && staging_allocator == _staging_allocator) 1272 | return; 1273 | 1274 | release(); 1275 | 1276 | elemsize = _elemsize; 1277 | elempack = 1; 1278 | allocator = _allocator; 1279 | staging_allocator = _staging_allocator; 1280 | 1281 | dims = 1; 1282 | w = _w; 1283 | h = 1; 1284 | c = 1; 1285 | 1286 | cstep = w; 1287 | 1288 | if (total() > 0) 1289 | { 1290 | size_t totalsize = alignSize(total() * elemsize, 4); 1291 | 1292 | data = allocator->fastMalloc(totalsize); 1293 | offset = 0; 1294 | 1295 | refcount = (int*)((unsigned char*)data + offsetof(VkBufferMemory, refcount)); 1296 | *refcount = 1; 1297 | } 1298 | } 1299 | 1300 | inline void VkMat::create(int _w, int _h, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1301 | { 1302 | if (dims == 2 && w == _w && h == _h && elemsize == _elemsize && elempack == 1 && allocator == _allocator && staging_allocator == _staging_allocator) 1303 | return; 1304 | 1305 | release(); 1306 | 1307 | elemsize = _elemsize; 1308 | elempack = 1; 1309 | allocator = _allocator; 1310 | staging_allocator = _staging_allocator; 1311 | 1312 | dims = 2; 1313 | w = _w; 1314 | h = _h; 1315 | c = 1; 1316 | 1317 | cstep = w * h; 1318 | 1319 | if (total() > 0) 1320 | { 1321 | size_t totalsize = alignSize(total() * elemsize, 4); 1322 | 1323 | data = allocator->fastMalloc(totalsize); 1324 | offset = 0; 1325 | 1326 | refcount = (int*)((unsigned char*)data + offsetof(VkBufferMemory, refcount)); 1327 | *refcount = 1; 1328 | } 1329 | } 1330 | 1331 | inline void VkMat::create(int _w, int _h, int _c, size_t _elemsize, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1332 | { 1333 | if (dims == 3 && w == _w && h == _h && c == _c && elemsize == _elemsize && elempack == 1 && allocator == _allocator && staging_allocator == _staging_allocator) 1334 | return; 1335 | 1336 | release(); 1337 | 1338 | elemsize = _elemsize; 1339 | elempack = 1; 1340 | allocator = _allocator; 1341 | staging_allocator = _staging_allocator; 1342 | 1343 | dims = 3; 1344 | w = _w; 1345 | h = _h; 1346 | c = _c; 1347 | 1348 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 1349 | 1350 | if (total() > 0) 1351 | { 1352 | size_t totalsize = alignSize(total() * elemsize, 4); 1353 | 1354 | data = allocator->fastMalloc(totalsize); 1355 | offset = 0; 1356 | 1357 | refcount = (int*)((unsigned char*)data + offsetof(VkBufferMemory, refcount)); 1358 | *refcount = 1; 1359 | } 1360 | } 1361 | 1362 | inline void VkMat::create(int _w, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1363 | { 1364 | if (dims == 1 && w == _w && elemsize == _elemsize && elempack == _elempack && allocator == _allocator && staging_allocator == _staging_allocator) 1365 | return; 1366 | 1367 | release(); 1368 | 1369 | elemsize = _elemsize; 1370 | elempack = _elempack; 1371 | allocator = _allocator; 1372 | staging_allocator = _staging_allocator; 1373 | 1374 | dims = 1; 1375 | w = _w; 1376 | h = 1; 1377 | c = 1; 1378 | 1379 | cstep = w; 1380 | 1381 | if (total() > 0) 1382 | { 1383 | size_t totalsize = alignSize(total() * elemsize, 4); 1384 | 1385 | data = allocator->fastMalloc(totalsize); 1386 | offset = 0; 1387 | 1388 | refcount = (int*)((unsigned char*)data + offsetof(VkBufferMemory, refcount)); 1389 | *refcount = 1; 1390 | } 1391 | } 1392 | 1393 | inline void VkMat::create(int _w, int _h, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1394 | { 1395 | if (dims == 2 && w == _w && h == _h && elemsize == _elemsize && elempack == _elempack && allocator == _allocator && staging_allocator == _staging_allocator) 1396 | return; 1397 | 1398 | release(); 1399 | 1400 | elemsize = _elemsize; 1401 | elempack = _elempack; 1402 | allocator = _allocator; 1403 | staging_allocator = _staging_allocator; 1404 | 1405 | dims = 2; 1406 | w = _w; 1407 | h = _h; 1408 | c = 1; 1409 | 1410 | cstep = w * h; 1411 | 1412 | if (total() > 0) 1413 | { 1414 | size_t totalsize = alignSize(total() * elemsize, 4); 1415 | 1416 | data = allocator->fastMalloc(totalsize); 1417 | offset = 0; 1418 | 1419 | refcount = (int*)((unsigned char*)data + offsetof(VkBufferMemory, refcount)); 1420 | *refcount = 1; 1421 | } 1422 | } 1423 | 1424 | inline void VkMat::create(int _w, int _h, int _c, size_t _elemsize, int _elempack, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1425 | { 1426 | if (dims == 3 && w == _w && h == _h && c == _c && elemsize == _elemsize && elempack == _elempack && allocator == _allocator && staging_allocator == _staging_allocator) 1427 | return; 1428 | 1429 | release(); 1430 | 1431 | elemsize = _elemsize; 1432 | elempack = _elempack; 1433 | allocator = _allocator; 1434 | staging_allocator = _staging_allocator; 1435 | 1436 | dims = 3; 1437 | w = _w; 1438 | h = _h; 1439 | c = _c; 1440 | 1441 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 1442 | 1443 | if (total() > 0) 1444 | { 1445 | size_t totalsize = alignSize(total() * elemsize, 4); 1446 | 1447 | data = allocator->fastMalloc(totalsize); 1448 | offset = 0; 1449 | 1450 | refcount = (int*)((unsigned char*)data + offsetof(VkBufferMemory, refcount)); 1451 | *refcount = 1; 1452 | } 1453 | } 1454 | 1455 | inline void VkMat::create_like(const Mat& m, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1456 | { 1457 | if (m.dims == 1) 1458 | create(m.w, m.elemsize, m.elempack, _allocator, _staging_allocator); 1459 | else if (m.dims == 2) 1460 | create(m.w, m.h, m.elemsize, m.elempack, _allocator, _staging_allocator); 1461 | else if (m.dims == 3) 1462 | create(m.w, m.h, m.c, m.elemsize, m.elempack, _allocator, _staging_allocator); 1463 | } 1464 | 1465 | inline void VkMat::create_like(const VkMat& m, VkAllocator* _allocator, VkAllocator* _staging_allocator) 1466 | { 1467 | if (m.dims == 1) 1468 | create(m.w, m.elemsize, m.elempack, _allocator, _staging_allocator); 1469 | else if (m.dims == 2) 1470 | create(m.w, m.h, m.elemsize, m.elempack, _allocator, _staging_allocator); 1471 | else if (m.dims == 3) 1472 | create(m.w, m.h, m.c, m.elemsize, m.elempack, _allocator, _staging_allocator); 1473 | } 1474 | 1475 | inline void VkMat::prepare_staging_buffer() 1476 | { 1477 | if (allocator->mappable) 1478 | return; 1479 | 1480 | if (staging_allocator && staging_data) 1481 | return; 1482 | 1483 | size_t totalsize = alignSize(total() * elemsize, 4); 1484 | staging_data = staging_allocator->fastMalloc(totalsize); 1485 | 1486 | staging_refcount = (int*)((unsigned char*)staging_data + offsetof(VkBufferMemory, refcount)); 1487 | *staging_refcount = 1; 1488 | } 1489 | 1490 | inline void VkMat::discard_staging_buffer() 1491 | { 1492 | if (allocator->mappable) 1493 | return; 1494 | 1495 | if (staging_refcount && NCNN_XADD(staging_refcount, -1) == 1) 1496 | { 1497 | if (staging_allocator && staging_data) 1498 | { 1499 | staging_allocator->fastFree(staging_data); 1500 | } 1501 | } 1502 | 1503 | staging_data = 0; 1504 | staging_refcount = 0; 1505 | } 1506 | 1507 | inline void VkMat::upload(const Mat& m) 1508 | { 1509 | memcpy(mapped_ptr(), m.data, m.total() * m.elemsize); 1510 | } 1511 | 1512 | inline void VkMat::download(Mat& m) const 1513 | { 1514 | memcpy(m.data, mapped_ptr(), total() * elemsize); 1515 | } 1516 | 1517 | inline Mat VkMat::mapped() const 1518 | { 1519 | if (dims == 1) 1520 | return Mat(w, mapped_ptr(), elemsize, elempack, 0); 1521 | 1522 | if (dims == 2) 1523 | return Mat(w, h, mapped_ptr(), elemsize, elempack, 0); 1524 | 1525 | if (dims == 3) 1526 | return Mat(w, h, c, mapped_ptr(), elemsize, elempack, 0); 1527 | 1528 | return Mat(); 1529 | } 1530 | 1531 | inline void* VkMat::mapped_ptr() const 1532 | { 1533 | VkBufferMemory* mappable_data = allocator->mappable ? data : staging_data; 1534 | return (unsigned char*)mappable_data->mapped_ptr + mappable_data->offset + offset; 1535 | } 1536 | 1537 | inline void VkMat::addref() 1538 | { 1539 | if (refcount) 1540 | NCNN_XADD(refcount, 1); 1541 | 1542 | if (staging_refcount) 1543 | NCNN_XADD(staging_refcount, 1); 1544 | } 1545 | 1546 | inline void VkMat::release() 1547 | { 1548 | if (refcount && NCNN_XADD(refcount, -1) == 1) 1549 | { 1550 | if (allocator && data) 1551 | { 1552 | allocator->fastFree(data); 1553 | } 1554 | } 1555 | 1556 | if (staging_refcount && NCNN_XADD(staging_refcount, -1) == 1) 1557 | { 1558 | if (staging_allocator && staging_data) 1559 | { 1560 | staging_allocator->fastFree(staging_data); 1561 | } 1562 | } 1563 | 1564 | data = 0; 1565 | offset = 0; 1566 | staging_data = 0; 1567 | 1568 | elemsize = 0; 1569 | elempack = 0; 1570 | 1571 | dims = 0; 1572 | w = 0; 1573 | h = 0; 1574 | c = 0; 1575 | 1576 | cstep = 0; 1577 | 1578 | refcount = 0; 1579 | staging_refcount = 0; 1580 | } 1581 | 1582 | inline bool VkMat::empty() const 1583 | { 1584 | return data == 0 || total() == 0; 1585 | } 1586 | 1587 | inline size_t VkMat::total() const 1588 | { 1589 | return cstep * c; 1590 | } 1591 | 1592 | inline VkMat VkMat::channel(int _c) 1593 | { 1594 | return VkMat(w, h, data, cstep * _c * elemsize, elemsize, elempack, allocator, staging_allocator); 1595 | } 1596 | 1597 | inline const VkMat VkMat::channel(int _c) const 1598 | { 1599 | return VkMat(w, h, data, cstep * _c * elemsize, elemsize, elempack, allocator, staging_allocator); 1600 | } 1601 | 1602 | inline VkMat VkMat::channel_range(int _c, int channels) 1603 | { 1604 | return VkMat(w, h, channels, data, cstep * _c * elemsize, elemsize, elempack, allocator, staging_allocator); 1605 | } 1606 | 1607 | inline const VkMat VkMat::channel_range(int _c, int channels) const 1608 | { 1609 | return VkMat(w, h, channels, data, cstep * _c * elemsize, elemsize, elempack, allocator, staging_allocator); 1610 | } 1611 | 1612 | inline VkMat VkMat::row_range(int y, int rows) 1613 | { 1614 | return VkMat(w, rows, data, w * y * elemsize, elemsize, elempack, allocator, staging_allocator); 1615 | } 1616 | 1617 | inline const VkMat VkMat::row_range(int y, int rows) const 1618 | { 1619 | return VkMat(w, rows, data, w * y * elemsize, elemsize, elempack, allocator, staging_allocator); 1620 | } 1621 | 1622 | inline VkMat VkMat::range(int x, int n) 1623 | { 1624 | return VkMat(n, data, x * elemsize, elemsize, elempack, allocator, staging_allocator); 1625 | } 1626 | 1627 | inline const VkMat VkMat::range(int x, int n) const 1628 | { 1629 | return VkMat(n, data, x * elemsize, elemsize, elempack, allocator, staging_allocator); 1630 | } 1631 | 1632 | inline VkBuffer VkMat::buffer() const 1633 | { 1634 | return data->buffer; 1635 | } 1636 | 1637 | inline size_t VkMat::buffer_offset() const 1638 | { 1639 | return data->offset + offset; 1640 | } 1641 | 1642 | inline VkBuffer VkMat::staging_buffer() const 1643 | { 1644 | return staging_data->buffer; 1645 | } 1646 | 1647 | inline size_t VkMat::staging_buffer_offset() const 1648 | { 1649 | return staging_data->offset; 1650 | } 1651 | #endif // NCNN_VULKAN 1652 | 1653 | } // namespace ncnn 1654 | 1655 | #endif // NCNN_MAT_H 1656 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/modelbin.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_MODELBIN_H 16 | #define NCNN_MODELBIN_H 17 | 18 | #include "mat.h" 19 | 20 | namespace ncnn { 21 | 22 | class DataReader; 23 | class ModelBin 24 | { 25 | public: 26 | virtual ~ModelBin(); 27 | // element type 28 | // 0 = auto 29 | // 1 = float32 30 | // 2 = float16 31 | // 3 = int8 32 | // load vec 33 | virtual Mat load(int w, int type) const = 0; 34 | // load image 35 | virtual Mat load(int w, int h, int type) const; 36 | // load dim 37 | virtual Mat load(int w, int h, int c, int type) const; 38 | }; 39 | 40 | class ModelBinFromDataReader : public ModelBin 41 | { 42 | public: 43 | ModelBinFromDataReader(const DataReader& dr); 44 | 45 | virtual Mat load(int w, int type) const; 46 | 47 | protected: 48 | const DataReader& dr; 49 | }; 50 | 51 | class ModelBinFromMatArray : public ModelBin 52 | { 53 | public: 54 | // construct from weight blob array 55 | ModelBinFromMatArray(const Mat* weights); 56 | 57 | virtual Mat load(int w, int type) const; 58 | 59 | protected: 60 | mutable const Mat* weights; 61 | }; 62 | 63 | } // namespace ncnn 64 | 65 | #endif // NCNN_MODELBIN_H 66 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/net.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_NET_H 16 | #define NCNN_NET_H 17 | 18 | #include 19 | #include 20 | #include "platform.h" 21 | #include "blob.h" 22 | #include "layer.h" 23 | #include "mat.h" 24 | #include "option.h" 25 | 26 | #if __ANDROID_API__ >= 9 27 | #include 28 | #endif // __ANDROID_API__ >= 9 29 | 30 | namespace ncnn { 31 | 32 | #if NCNN_VULKAN 33 | class VkCompute; 34 | #endif // NCNN_VULKAN 35 | class DataReader; 36 | class Extractor; 37 | class Net 38 | { 39 | public: 40 | // empty init 41 | Net(); 42 | // clear and destroy 43 | ~Net(); 44 | 45 | public: 46 | // option can be changed before loading 47 | Option opt; 48 | 49 | #if NCNN_VULKAN 50 | // set gpu device by index 51 | void set_vulkan_device(int device_index); 52 | 53 | // set gpu device by device handle, no owner transfer 54 | void set_vulkan_device(const VulkanDevice* vkdev); 55 | 56 | const VulkanDevice* vulkan_device() const; 57 | #endif // NCNN_VULKAN 58 | 59 | #if NCNN_STRING 60 | // register custom layer by layer type name 61 | // return 0 if success 62 | int register_custom_layer(const char* type, layer_creator_func creator); 63 | #endif // NCNN_STRING 64 | // register custom layer by layer type 65 | // return 0 if success 66 | int register_custom_layer(int index, layer_creator_func creator); 67 | 68 | #if NCNN_STRING 69 | int load_param(const DataReader& dr); 70 | #endif // NCNN_STRING 71 | 72 | int load_param_bin(const DataReader& dr); 73 | 74 | int load_model(const DataReader& dr); 75 | 76 | #if NCNN_STDIO 77 | #if NCNN_STRING 78 | // load network structure from plain param file 79 | // return 0 if success 80 | int load_param(FILE* fp); 81 | int load_param(const char* protopath); 82 | int load_param_mem(const char* mem); 83 | #endif // NCNN_STRING 84 | // load network structure from binary param file 85 | // return 0 if success 86 | int load_param_bin(FILE* fp); 87 | int load_param_bin(const char* protopath); 88 | 89 | // load network weight data from model file 90 | // return 0 if success 91 | int load_model(FILE* fp); 92 | int load_model(const char* modelpath); 93 | #endif // NCNN_STDIO 94 | 95 | // load network structure from external memory 96 | // memory pointer must be 32-bit aligned 97 | // return bytes consumed 98 | int load_param(const unsigned char* mem); 99 | 100 | // reference network weight data from external memory 101 | // weight data is not copied but referenced 102 | // so external memory should be retained when used 103 | // memory pointer must be 32-bit aligned 104 | // return bytes consumed 105 | int load_model(const unsigned char* mem); 106 | 107 | #if __ANDROID_API__ >= 9 108 | #if NCNN_STRING 109 | // convenient load network structure from android asset plain param file 110 | int load_param(AAsset* asset); 111 | int load_param(AAssetManager* mgr, const char* assetpath); 112 | #endif // NCNN_STRING 113 | // convenient load network structure from android asset binary param file 114 | int load_param_bin(AAsset* asset); 115 | int load_param_bin(AAssetManager* mgr, const char* assetpath); 116 | 117 | // convenient load network weight data from android asset model file 118 | int load_model(AAsset* asset); 119 | int load_model(AAssetManager* mgr, const char* assetpath); 120 | #endif // __ANDROID_API__ >= 9 121 | 122 | // unload network structure and weight data 123 | void clear(); 124 | 125 | // construct an Extractor from network 126 | Extractor create_extractor() const; 127 | 128 | protected: 129 | // parse the structure of network 130 | // fuse int8 op dequantize and quantize by requantize 131 | int fuse_network(); 132 | 133 | #if NCNN_VULKAN 134 | 135 | int upload_model(); 136 | 137 | int create_pipeline(); 138 | 139 | int destroy_pipeline(); 140 | 141 | #endif // NCNN_VULKAN 142 | 143 | friend class Extractor; 144 | #if NCNN_STRING 145 | int find_blob_index_by_name(const char* name) const; 146 | int find_layer_index_by_name(const char* name) const; 147 | int custom_layer_to_index(const char* type); 148 | Layer* create_custom_layer(const char* type); 149 | #endif // NCNN_STRING 150 | Layer* create_custom_layer(int index); 151 | int forward_layer(int layer_index, std::vector& blob_mats, Option& opt) const; 152 | 153 | #if NCNN_VULKAN 154 | int forward_layer(int layer_index, std::vector& blob_mats, std::vector& blob_mats_gpu, VkCompute& cmd, Option& opt) const; 155 | #endif // NCNN_VULKAN 156 | 157 | protected: 158 | std::vector blobs; 159 | std::vector layers; 160 | 161 | std::vector custom_layer_registry; 162 | 163 | #if NCNN_VULKAN 164 | const VulkanDevice* vkdev; 165 | 166 | VkAllocator* weight_vkallocator; 167 | VkAllocator* weight_staging_vkallocator; 168 | 169 | ncnn::Layer* cast_float32_to_float16; 170 | ncnn::Layer* cast_float16_to_float32; 171 | ncnn::Layer* packing_pack1; 172 | ncnn::Layer* packing_pack4; 173 | #endif // NCNN_VULKAN 174 | }; 175 | 176 | class Extractor 177 | { 178 | public: 179 | // enable light mode 180 | // intermediate blob will be recycled when enabled 181 | // enabled by default 182 | void set_light_mode(bool enable); 183 | 184 | // set thread count for this extractor 185 | // this will overwrite the global setting 186 | // default count is system depended 187 | void set_num_threads(int num_threads); 188 | 189 | // set blob memory allocator 190 | void set_blob_allocator(Allocator* allocator); 191 | 192 | // set workspace memory allocator 193 | void set_workspace_allocator(Allocator* allocator); 194 | 195 | #if NCNN_VULKAN 196 | void set_vulkan_compute(bool enable); 197 | 198 | void set_blob_vkallocator(VkAllocator* allocator); 199 | 200 | void set_workspace_vkallocator(VkAllocator* allocator); 201 | 202 | void set_staging_vkallocator(VkAllocator* allocator); 203 | #endif // NCNN_VULKAN 204 | 205 | #if NCNN_STRING 206 | // set input by blob name 207 | // return 0 if success 208 | int input(const char* blob_name, const Mat& in); 209 | 210 | // get result by blob name 211 | // return 0 if success 212 | int extract(const char* blob_name, Mat& feat); 213 | #endif // NCNN_STRING 214 | 215 | // set input by blob index 216 | // return 0 if success 217 | int input(int blob_index, const Mat& in); 218 | 219 | // get result by blob index 220 | // return 0 if success 221 | int extract(int blob_index, Mat& feat); 222 | 223 | #if NCNN_VULKAN 224 | #if NCNN_STRING 225 | // set input by blob name 226 | // return 0 if success 227 | int input(const char* blob_name, const VkMat& in); 228 | 229 | // get result by blob name 230 | // return 0 if success 231 | int extract(const char* blob_name, VkMat& feat, VkCompute& cmd); 232 | #endif // NCNN_STRING 233 | 234 | // set input by blob index 235 | // return 0 if success 236 | int input(int blob_index, const VkMat& in); 237 | 238 | // get result by blob index 239 | // return 0 if success 240 | int extract(int blob_index, VkMat& feat, VkCompute& cmd); 241 | #endif // NCNN_VULKAN 242 | 243 | protected: 244 | friend Extractor Net::create_extractor() const; 245 | Extractor(const Net* net, int blob_count); 246 | 247 | private: 248 | const Net* net; 249 | std::vector blob_mats; 250 | Option opt; 251 | 252 | #if NCNN_VULKAN 253 | std::vector blob_mats_gpu; 254 | #endif // NCNN_VULKAN 255 | }; 256 | 257 | } // namespace ncnn 258 | 259 | #endif // NCNN_NET_H 260 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/opencv.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_OPENCV_H 16 | #define NCNN_OPENCV_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_OPENCV 21 | 22 | #include 23 | #include 24 | #include "mat.h" 25 | 26 | #if defined(_MSC_VER) || defined(__GNUC__) 27 | #pragma push_macro("min") 28 | #pragma push_macro("max") 29 | #undef min 30 | #undef max 31 | #endif 32 | 33 | // minimal opencv style data structure implementation 34 | namespace cv 35 | { 36 | 37 | struct Size 38 | { 39 | Size() : width(0), height(0) {} 40 | Size(int _w, int _h) : width(_w), height(_h) {} 41 | 42 | int width; 43 | int height; 44 | }; 45 | 46 | template 47 | struct Rect_ 48 | { 49 | Rect_() : x(0), y(0), width(0), height(0) {} 50 | Rect_(_Tp _x, _Tp _y, _Tp _w, _Tp _h) : x(_x), y(_y), width(_w), height(_h) {} 51 | 52 | _Tp x; 53 | _Tp y; 54 | _Tp width; 55 | _Tp height; 56 | 57 | // area 58 | _Tp area() const 59 | { 60 | return width * height; 61 | } 62 | }; 63 | 64 | template static inline Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 65 | { 66 | _Tp x1 = std::max(a.x, b.x), y1 = std::max(a.y, b.y); 67 | a.width = std::min(a.x + a.width, b.x + b.width) - x1; 68 | a.height = std::min(a.y + a.height, b.y + b.height) - y1; 69 | a.x = x1; a.y = y1; 70 | if( a.width <= 0 || a.height <= 0 ) 71 | a = Rect_<_Tp>(); 72 | return a; 73 | } 74 | 75 | template static inline Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 76 | { 77 | _Tp x1 = std::min(a.x, b.x), y1 = std::min(a.y, b.y); 78 | a.width = std::max(a.x + a.width, b.x + b.width) - x1; 79 | a.height = std::max(a.y + a.height, b.y + b.height) - y1; 80 | a.x = x1; a.y = y1; 81 | return a; 82 | } 83 | 84 | template static inline Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 85 | { 86 | Rect_<_Tp> c = a; 87 | return c &= b; 88 | } 89 | 90 | template static inline Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 91 | { 92 | Rect_<_Tp> c = a; 93 | return c |= b; 94 | } 95 | 96 | typedef Rect_ Rect; 97 | typedef Rect_ Rect2f; 98 | 99 | template 100 | struct Point_ 101 | { 102 | Point_() : x(0), y(0) {} 103 | Point_(_Tp _x, _Tp _y) : x(_x), y(_y) {} 104 | 105 | _Tp x; 106 | _Tp y; 107 | }; 108 | 109 | typedef Point_ Point; 110 | typedef Point_ Point2f; 111 | 112 | #define CV_8UC1 1 113 | #define CV_8UC3 3 114 | #define CV_8UC4 4 115 | #define CV_32FC1 4 116 | 117 | struct Mat 118 | { 119 | Mat() : data(0), refcount(0), rows(0), cols(0), c(0) {} 120 | 121 | Mat(int _rows, int _cols, int flags) : data(0), refcount(0) 122 | { 123 | create(_rows, _cols, flags); 124 | } 125 | 126 | // copy 127 | Mat(const Mat& m) : data(m.data), refcount(m.refcount) 128 | { 129 | if (refcount) 130 | NCNN_XADD(refcount, 1); 131 | 132 | rows = m.rows; 133 | cols = m.cols; 134 | c = m.c; 135 | } 136 | 137 | Mat(int _rows, int _cols, int flags, void* _data) : data((unsigned char*)_data), refcount(0) 138 | { 139 | rows = _rows; 140 | cols = _cols; 141 | c = flags; 142 | } 143 | 144 | ~Mat() 145 | { 146 | release(); 147 | } 148 | 149 | // assign 150 | Mat& operator=(const Mat& m) 151 | { 152 | if (this == &m) 153 | return *this; 154 | 155 | if (m.refcount) 156 | NCNN_XADD(m.refcount, 1); 157 | 158 | release(); 159 | 160 | data = m.data; 161 | refcount = m.refcount; 162 | 163 | rows = m.rows; 164 | cols = m.cols; 165 | c = m.c; 166 | 167 | return *this; 168 | } 169 | 170 | void create(int _rows, int _cols, int flags) 171 | { 172 | release(); 173 | 174 | rows = _rows; 175 | cols = _cols; 176 | c = flags; 177 | 178 | if (total() > 0) 179 | { 180 | // refcount address must be aligned, so we expand totalsize here 181 | size_t totalsize = (total() + 3) >> 2 << 2; 182 | data = (unsigned char*)ncnn::fastMalloc(totalsize + (int)sizeof(*refcount)); 183 | refcount = (int*)(((unsigned char*)data) + totalsize); 184 | *refcount = 1; 185 | } 186 | } 187 | 188 | void release() 189 | { 190 | if (refcount && NCNN_XADD(refcount, -1) == 1) 191 | ncnn::fastFree(data); 192 | 193 | data = 0; 194 | 195 | rows = 0; 196 | cols = 0; 197 | c = 0; 198 | 199 | refcount = 0; 200 | } 201 | 202 | Mat clone() const 203 | { 204 | if (empty()) 205 | return Mat(); 206 | 207 | Mat m(rows, cols, c); 208 | 209 | if (total() > 0) 210 | { 211 | memcpy(m.data, data, total()); 212 | } 213 | 214 | return m; 215 | } 216 | 217 | bool empty() const { return data == 0 || total() == 0; } 218 | 219 | int channels() const { return c; } 220 | 221 | size_t total() const { return cols * rows * c; } 222 | 223 | const unsigned char* ptr(int y) const { return data + y * cols * c; } 224 | 225 | unsigned char* ptr(int y) { return data + y * cols * c; } 226 | 227 | // roi 228 | Mat operator()( const Rect& roi ) const 229 | { 230 | if (empty()) 231 | return Mat(); 232 | 233 | Mat m(roi.height, roi.width, c); 234 | 235 | int sy = roi.y; 236 | for (int y = 0; y < roi.height; y++) 237 | { 238 | const unsigned char* sptr = ptr(sy) + roi.x * c; 239 | unsigned char* dptr = m.ptr(y); 240 | memcpy(dptr, sptr, roi.width * c); 241 | sy++; 242 | } 243 | 244 | return m; 245 | } 246 | 247 | unsigned char* data; 248 | 249 | // pointer to the reference counter; 250 | // when points to user-allocated data, the pointer is NULL 251 | int* refcount; 252 | 253 | int rows; 254 | int cols; 255 | 256 | int c; 257 | 258 | }; 259 | 260 | #define CV_LOAD_IMAGE_GRAYSCALE 1 261 | #define CV_LOAD_IMAGE_COLOR 3 262 | Mat imread(const std::string& path, int flags); 263 | void imwrite(const std::string& path, const Mat& m); 264 | 265 | #if NCNN_PIXEL 266 | void resize(const Mat& src, Mat& dst, const Size& size, float sw = 0.f, float sh = 0.f, int flags = 0); 267 | #endif // NCNN_PIXEL 268 | 269 | } // namespace cv 270 | 271 | #if defined(_MSC_VER) || defined(__GNUC__) 272 | #pragma pop_macro("min") 273 | #pragma pop_macro("max") 274 | #endif 275 | 276 | #endif // NCNN_OPENCV 277 | 278 | #endif // NCNN_OPENCV_H 279 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/option.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2019 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 NCNN_OPTION_H 16 | #define NCNN_OPTION_H 17 | 18 | #include "platform.h" 19 | 20 | namespace ncnn { 21 | 22 | #if NCNN_VULKAN 23 | class VkAllocator; 24 | #endif // NCNN_VULKAN 25 | 26 | class Allocator; 27 | class Option 28 | { 29 | public: 30 | // default option 31 | Option(); 32 | 33 | public: 34 | // light mode 35 | // intermediate blob will be recycled when enabled 36 | // enabled by default 37 | bool lightmode; 38 | 39 | // thread count 40 | // default value is the one returned by get_cpu_count() 41 | int num_threads; 42 | 43 | // blob memory allocator 44 | Allocator* blob_allocator; 45 | 46 | // workspace memory allocator 47 | Allocator* workspace_allocator; 48 | 49 | #if NCNN_VULKAN 50 | // blob memory allocator 51 | VkAllocator* blob_vkallocator; 52 | 53 | // workspace memory allocator 54 | VkAllocator* workspace_vkallocator; 55 | 56 | // staging memory allocator 57 | VkAllocator* staging_vkallocator; 58 | #endif // NCNN_VULKAN 59 | 60 | // enable winograd convolution optimization 61 | // improve convolution 3x3 stride1 performace, may consume more memory 62 | // changes should be applied before loading network structure and weight 63 | // enabled by default 64 | bool use_winograd_convolution; 65 | 66 | // enable sgemm convolution optimization 67 | // improve convolution 1x1 stride1 performace, may consume more memory 68 | // changes should be applied before loading network structure and weight 69 | // enabled by default 70 | bool use_sgemm_convolution; 71 | 72 | // enable quantized int8 inference 73 | // use low-precision int8 path for quantized model 74 | // changes should be applied before loading network structure and weight 75 | // enabled by default 76 | bool use_int8_inference; 77 | 78 | // enable vulkan compute 79 | bool use_vulkan_compute; 80 | 81 | // enable options for gpu inference 82 | bool use_fp16_packed; 83 | bool use_fp16_storage; 84 | bool use_fp16_arithmetic; 85 | bool use_int8_storage; 86 | bool use_int8_arithmetic; 87 | 88 | // 89 | bool use_packing_layout; 90 | }; 91 | 92 | } // namespace ncnn 93 | 94 | #endif // NCNN_OPTION_H 95 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/paramdict.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_PARAMDICT_H 16 | #define NCNN_PARAMDICT_H 17 | 18 | #include "mat.h" 19 | 20 | // at most 32 parameters 21 | #define NCNN_MAX_PARAM_COUNT 32 22 | 23 | namespace ncnn { 24 | 25 | class DataReader; 26 | class Net; 27 | class ParamDict 28 | { 29 | public: 30 | // empty 31 | ParamDict(); 32 | 33 | // get int 34 | int get(int id, int def) const; 35 | // get float 36 | float get(int id, float def) const; 37 | // get array 38 | Mat get(int id, const Mat& def) const; 39 | 40 | // set int 41 | void set(int id, int i); 42 | // set float 43 | void set(int id, float f); 44 | // set array 45 | void set(int id, const Mat& v); 46 | 47 | protected: 48 | friend class Net; 49 | 50 | void clear(); 51 | 52 | int load_param(const DataReader& dr); 53 | int load_param_bin(const DataReader& dr); 54 | 55 | protected: 56 | struct 57 | { 58 | // 0 = null 59 | // 1 = int/float 60 | // 2 = int 61 | // 3 = float 62 | // 4 = array of int/float 63 | // 5 = array of int 64 | // 6 = array of float 65 | int type; 66 | union { int i; float f; }; 67 | Mat v; 68 | } params[NCNN_MAX_PARAM_COUNT]; 69 | }; 70 | 71 | } // namespace ncnn 72 | 73 | #endif // NCNN_PARAMDICT_H 74 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/pipeline.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2019 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 NCNN_PIPELINE_H 16 | #define NCNN_PIPELINE_H 17 | 18 | #include "platform.h" 19 | #include "mat.h" 20 | #if NCNN_VULKAN 21 | #include 22 | #include "gpu.h" 23 | #endif // NCNN_VULKAN 24 | 25 | namespace ncnn { 26 | 27 | #if NCNN_VULKAN 28 | class Option; 29 | class Pipeline 30 | { 31 | public: 32 | Pipeline(const VulkanDevice* vkdev); 33 | ~Pipeline(); 34 | 35 | public: 36 | void set_optimal_local_size_xyz(int w = 32, int h = 32, int c = 32); 37 | void set_local_size_xyz(int w, int h, int c); 38 | 39 | int create(const uint32_t* spv_data, size_t spv_data_size, const char* entry_name, 40 | const std::vector& specializations, int binding_count, int push_constant_count); 41 | int create(VkShaderModule shader_module, const char* entry_name, 42 | const std::vector& specializations, int binding_count, int push_constant_count); 43 | int create(const char* name, const Option& opt, const std::vector& specializations, 44 | int binding_count, int push_constant_count); 45 | void destroy(); 46 | 47 | protected: 48 | int create_descriptorset_layout(int binding_count); 49 | int create_pipeline_layout(int push_constant_count); 50 | int create_pipeline(VkShaderModule shader_module, const char* entry_name, const std::vector& specializations); 51 | int create_descriptor_update_template(int binding_count); 52 | 53 | public: 54 | const VulkanDevice* vkdev; 55 | 56 | // local shader module 57 | VkShaderModule local_shader_module; 58 | 59 | VkDescriptorSetLayout descriptorset_layout; 60 | VkPipelineLayout pipeline_layout; 61 | 62 | // op forward TODO use pipeline cache ? 63 | VkPipeline pipeline; 64 | 65 | VkDescriptorUpdateTemplateKHR descriptor_update_template; 66 | 67 | uint32_t local_size_x; 68 | uint32_t local_size_y; 69 | uint32_t local_size_z; 70 | }; 71 | 72 | #if __ANDROID_API__ >= 26 73 | class VkCompute; 74 | class ImportAndroidHardwareBufferPipeline : private Pipeline 75 | { 76 | public: 77 | ImportAndroidHardwareBufferPipeline(const VulkanDevice* vkdev); 78 | ~ImportAndroidHardwareBufferPipeline(); 79 | 80 | int create(AHardwareBuffer* hb, int type_to, int rotate_from, const Option& opt); 81 | void destroy(); 82 | 83 | int create_image_memory_imageview(AHardwareBuffer* hb, VkImage* image, VkDeviceMemory* memory, VkImageView* imageView); 84 | 85 | friend class VkCompute; 86 | 87 | protected: 88 | int create_sampler(); 89 | int create_descriptorset_layout(); 90 | int create_descriptor_update_template(); 91 | 92 | public: 93 | int w; 94 | int h; 95 | int outw; 96 | int outh; 97 | int outc; 98 | size_t out_elemsize; 99 | int out_elempack; 100 | int type_to; 101 | int rotate_from; 102 | VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties; 103 | VkAndroidHardwareBufferPropertiesANDROID bufferProperties; 104 | 105 | VkSamplerYcbcrConversionKHR samplerYcbcrConversion; 106 | VkSampler sampler; 107 | }; 108 | #endif // __ANDROID_API__ >= 26 109 | #endif // NCNN_VULKAN 110 | 111 | } // namespace ncnn 112 | 113 | #endif // NCNN_PIPELINE_H 114 | -------------------------------------------------------------------------------- /app/src/main/cpp/include/ncnn/platform.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 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 NCNN_PLATFORM_H 16 | #define NCNN_PLATFORM_H 17 | 18 | #define NCNN_STDIO 1 19 | #define NCNN_STRING 1 20 | #define NCNN_OPENCV 0 21 | #define NCNN_BENCHMARK 0 22 | #define NCNN_PIXEL 1 23 | #define NCNN_PIXEL_ROTATE 1 24 | #define NCNN_VULKAN 0 25 | #define NCNN_REQUANT 0 26 | #define NCNN_AVX2 0 27 | 28 | #ifdef _WIN32 29 | #define WIN32_LEAN_AND_MEAN 30 | #include 31 | #include 32 | #else 33 | #include 34 | #endif 35 | 36 | #if __ANDROID_API__ >= 26 37 | #define VK_USE_PLATFORM_ANDROID_KHR 38 | #endif // __ANDROID_API__ >= 26 39 | 40 | namespace ncnn { 41 | 42 | #ifdef _WIN32 43 | class Mutex 44 | { 45 | public: 46 | Mutex() { InitializeSRWLock(&srwlock); } 47 | ~Mutex() {} 48 | void lock() { AcquireSRWLockExclusive(&srwlock); } 49 | void unlock() { ReleaseSRWLockExclusive(&srwlock); } 50 | private: 51 | friend class ConditionVariable; 52 | // NOTE SRWLock is available from windows vista 53 | SRWLOCK srwlock; 54 | }; 55 | #else // _WIN32 56 | class Mutex 57 | { 58 | public: 59 | Mutex() { pthread_mutex_init(&mutex, 0); } 60 | ~Mutex() { pthread_mutex_destroy(&mutex); } 61 | void lock() { pthread_mutex_lock(&mutex); } 62 | void unlock() { pthread_mutex_unlock(&mutex); } 63 | private: 64 | friend class ConditionVariable; 65 | pthread_mutex_t mutex; 66 | }; 67 | #endif // _WIN32 68 | 69 | class MutexLockGuard 70 | { 71 | public: 72 | MutexLockGuard(Mutex& _mutex) : mutex(_mutex) { mutex.lock(); } 73 | ~MutexLockGuard() { mutex.unlock(); } 74 | private: 75 | Mutex& mutex; 76 | }; 77 | 78 | #if _WIN32 79 | class ConditionVariable 80 | { 81 | public: 82 | ConditionVariable() { InitializeConditionVariable(&condvar); } 83 | ~ConditionVariable() {} 84 | void wait(Mutex& mutex) { SleepConditionVariableSRW(&condvar, &mutex.srwlock, INFINITE, 0); } 85 | void broadcast() { WakeAllConditionVariable(&condvar); } 86 | void signal() { WakeConditionVariable(&condvar); } 87 | private: 88 | CONDITION_VARIABLE condvar; 89 | }; 90 | #else // _WIN32 91 | class ConditionVariable 92 | { 93 | public: 94 | ConditionVariable() { pthread_cond_init(&cond, 0); } 95 | ~ConditionVariable() { pthread_cond_destroy(&cond); } 96 | void wait(Mutex& mutex) { pthread_cond_wait(&cond, &mutex.mutex); } 97 | void broadcast() { pthread_cond_broadcast(&cond); } 98 | void signal() { pthread_cond_signal(&cond); } 99 | private: 100 | pthread_cond_t cond; 101 | }; 102 | #endif // _WIN32 103 | 104 | #if _WIN32 105 | static unsigned __stdcall start_wrapper(void* args); 106 | class Thread 107 | { 108 | public: 109 | Thread(void* (*start)(void*), void* args = 0) { _start = start; _args = args; handle = (HANDLE)_beginthreadex(0, 0, start_wrapper, this, 0, 0); } 110 | ~Thread() {} 111 | void join() { WaitForSingleObject(handle, INFINITE); CloseHandle(handle); } 112 | private: 113 | friend unsigned __stdcall start_wrapper(void* args) 114 | { 115 | Thread* t = (Thread*)args; 116 | t->_start(t->_args); 117 | return 0; 118 | } 119 | HANDLE handle; 120 | void* (*_start)(void*); 121 | void* _args; 122 | }; 123 | 124 | #else // _WIN32 125 | class Thread 126 | { 127 | public: 128 | Thread(void* (*start)(void*), void* args = 0) { pthread_create(&t, 0, start, args); } 129 | ~Thread() {} 130 | void join() { pthread_join(t, 0); } 131 | private: 132 | pthread_t t; 133 | }; 134 | #endif // _WIN32 135 | 136 | } // namespace ncnn 137 | 138 | #endif // NCNN_PLATFORM_H 139 | -------------------------------------------------------------------------------- /app/src/main/cpp/yolov3-tiny-jni.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "platform.h" 15 | #include "net.h" 16 | #if NCNN_VULKAN 17 | #include "gpu.h" 18 | #endif // NCNN_VULKAN 19 | 20 | extern "C" { 21 | 22 | static ncnn::Net yolov3; 23 | 24 | //struct Object 25 | //{ 26 | // cv::Rect_ rect; 27 | // int label; 28 | // float prob; 29 | //}; 30 | 31 | JNIEXPORT jboolean JNICALL 32 | Java_com_example_yolov3tiny_yolov3Tiny_Init(JNIEnv *env, jobject obj, jstring param, jstring bin) { 33 | __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "enter the jni func"); 34 | 35 | #if NCNN_VULKAN 36 | yolov3.opt.use_vulkan_compute = true; 37 | #endif // NCNN_VULKAN 38 | 39 | const char *param_path = env->GetStringUTFChars( param, NULL); 40 | if(param_path == NULL) 41 | return JNI_FALSE; 42 | __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "load_param %s", param_path); 43 | 44 | int ret = yolov3.load_param(param_path); 45 | __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "load_param result %d", ret); 46 | env->ReleaseStringUTFChars( param, param_path); 47 | 48 | const char *bin_path = env->GetStringUTFChars( bin, NULL); 49 | if(bin_path == NULL) 50 | return JNI_FALSE; 51 | __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "load_model %s", bin_path); 52 | 53 | int ret2 = yolov3.load_model(bin_path); 54 | __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "load_model result %d", ret2); 55 | env->ReleaseStringUTFChars( bin, bin_path); 56 | return JNI_TRUE; 57 | } 58 | 59 | JNIEXPORT jfloatArray JNICALL Java_com_example_yolov3tiny_yolov3Tiny_Detect(JNIEnv* env, jobject thiz, jobject bitmap) 60 | { 61 | const int target_size = 416; //input size 62 | 63 | AndroidBitmapInfo info; 64 | AndroidBitmap_getInfo(env, bitmap, &info); 65 | int width = info.width; 66 | int height = info.height; 67 | if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) 68 | return NULL; 69 | 70 | void* indata; 71 | AndroidBitmap_lockPixels(env, bitmap, &indata); 72 | 73 | // const char *img_path = env->GetStringUTFChars( imgPath, NULL); 74 | // if(img_path == NULL) 75 | // return JNI_FALSE; 76 | // __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "load_img %s", img_path); 77 | // 78 | // cv::Mat m = cv::imread(img_path, CV_LOAD_IMAGE_COLOR); 79 | // env->ReleaseStringUTFChars( imgPath, img_path); 80 | // ncnn::Mat in = ncnn::Mat::from_pixels_resize(m.data, ncnn::Mat::PIXEL_BGR2RGB, m.cols, m.rows, input->w, input->h); 81 | 82 | //you can resize image in this cpp, or when reading image in java. 83 | //ncnn::Mat in = ncnn::Mat::from_pixels_resize((const unsigned char*)indata, ncnn::Mat::PIXEL_RGBA2RGB, width, height, target_size, target_size); 84 | ncnn::Mat in = ncnn::Mat::from_pixels((const unsigned char*)indata, ncnn::Mat::PIXEL_RGBA2RGB, width, height); 85 | __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "yolov3_predict_has_input1, in.w: %d; in.h: %d", in.w, in.h); 86 | AndroidBitmap_unlockPixels(env, bitmap); 87 | 88 | const float norm_vals[3] = {1 / 255.0, 1 / 255.0, 1 / 255.0}; 89 | in.substract_mean_normalize(0, norm_vals); 90 | ncnn::Extractor ex = yolov3.create_extractor(); 91 | ex.input("data",in); 92 | ex.set_light_mode(false); 93 | ex.set_num_threads(4); 94 | 95 | ncnn::Mat out; 96 | int result = ex.extract("yolo_23", out); //yolo_23 is the out_blob name in param file 97 | __android_log_print(ANDROID_LOG_DEBUG, "yolov3tinyJni", "extract result %d", result); 98 | if (result != 0) 99 | return NULL; 100 | 101 | int output_wsize = out.w; 102 | int output_hsize = out.h; 103 | jfloat *output[output_wsize * output_hsize]; 104 | for(int i = 0; i< out.h; i++) { 105 | for (int j = 0; j < out.w; j++) { 106 | output[i*output_wsize + j] = &out.row(i)[j]; 107 | } 108 | } 109 | jfloatArray jOutputData = env->NewFloatArray(output_wsize * output_hsize); 110 | if (jOutputData == nullptr) return nullptr; 111 | env->SetFloatArrayRegion(jOutputData, 0, output_wsize * output_hsize, 112 | reinterpret_cast(*output)); // copy 113 | 114 | return jOutputData; 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/yolov3tiny/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.yolov3tiny; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.content.pm.PackageManager; 7 | import android.content.res.AssetManager; 8 | import android.graphics.Bitmap; 9 | import android.graphics.Canvas; 10 | import android.graphics.Color; 11 | import android.graphics.Paint; 12 | import android.net.Uri; 13 | import android.os.Bundle; 14 | import android.support.annotation.NonNull; 15 | import android.support.annotation.Nullable; 16 | import android.support.v4.app.ActivityCompat; 17 | import android.support.v4.content.ContextCompat; 18 | import android.text.method.ScrollingMovementMethod; 19 | import android.util.Log; 20 | import android.view.View; 21 | import android.widget.Button; 22 | import android.widget.ImageView; 23 | import android.widget.TextView; 24 | import android.widget.Toast; 25 | 26 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 27 | import com.bumptech.glide.request.RequestOptions; 28 | 29 | import java.io.BufferedReader; 30 | import java.io.File; 31 | import java.io.FileOutputStream; 32 | import java.io.IOException; 33 | import java.io.InputStream; 34 | import java.io.InputStreamReader; 35 | import java.util.ArrayList; 36 | import java.util.Arrays; 37 | import java.util.List; 38 | 39 | 40 | public class MainActivity extends Activity { 41 | private static final String TAG = MainActivity.class.getName(); 42 | private static final int SELECT_IMAGE = 1; 43 | private ImageView show_image; 44 | private TextView result_text; 45 | private boolean load_result = false; 46 | private int[] ddims = {1, 3, 416, 416}; 47 | private int model_index = 1; 48 | private List resultLabel = new ArrayList<>(); 49 | private yolov3Tiny yolov3tiny = new yolov3Tiny(); 50 | 51 | @Override 52 | public void onCreate(Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | setContentView(R.layout.activity_main); 55 | try { 56 | initYolov3Tiny(); 57 | } catch (IOException e) { 58 | Log.e(TAG, "initYolov3Tiny error"); 59 | } 60 | initView(); 61 | readCacheLabelFromLocalFile(); 62 | } 63 | 64 | //get assets file path 65 | private String getPathFromAssets(String assetsFileName){ 66 | File f = new File(getCacheDir()+"/"+assetsFileName); 67 | //if (!f.exists()) 68 | try { 69 | InputStream is = getAssets().open(assetsFileName); 70 | int size = is.available(); 71 | byte[] buffer = new byte[size]; 72 | is.read(buffer); 73 | is.close(); 74 | FileOutputStream fos = new FileOutputStream(f); 75 | fos.write(buffer); 76 | fos.close(); 77 | } catch (Exception e) { throw new RuntimeException(e); } 78 | return f.getPath(); 79 | } 80 | 81 | private void initYolov3Tiny() throws IOException { 82 | // byte[] param = null; 83 | // byte[] bin = null; 84 | // { 85 | // InputStream assetsInputStream = getAssets().open("yolov3-tiny.param.bin"); 86 | // int available = assetsInputStream.available(); 87 | // param = new byte[available]; 88 | // int byteCode = assetsInputStream.read(param); 89 | // assetsInputStream.close(); 90 | // } 91 | // { 92 | // InputStream assetsInputStream = getAssets().open("yolov3-tiny.bin"); 93 | // int available = assetsInputStream.available(); 94 | // bin = new byte[available]; 95 | // int byteCode = assetsInputStream.read(bin); 96 | // assetsInputStream.close(); 97 | // } 98 | 99 | String paramPath=getPathFromAssets("yolov3-tiny.param"); 100 | String binPath=getPathFromAssets("yolov3-tiny.bin"); 101 | 102 | load_result = yolov3tiny.Init(paramPath, binPath); 103 | Log.d(TAG, "yolov3tiny_load_model_result:" + load_result); 104 | } 105 | 106 | // initialize view 107 | private void initView() { 108 | request_permissions(); 109 | show_image = (ImageView) findViewById(R.id.show_image); 110 | result_text = (TextView) findViewById(R.id.result_text); 111 | result_text.setMovementMethod(ScrollingMovementMethod.getInstance()); 112 | Button use_photo = (Button) findViewById(R.id.use_photo); 113 | // use photo click 114 | use_photo.setOnClickListener(new View.OnClickListener() { 115 | @Override 116 | public void onClick(View view) { 117 | if (!load_result) { 118 | Toast.makeText(MainActivity.this, "never load model", Toast.LENGTH_SHORT).show(); 119 | return; 120 | } 121 | PhotoUtil.use_photo(MainActivity.this, SELECT_IMAGE); 122 | } 123 | }); 124 | } 125 | 126 | // load label's name 127 | private void readCacheLabelFromLocalFile() { 128 | try { 129 | AssetManager assetManager = getApplicationContext().getAssets(); 130 | BufferedReader reader = new BufferedReader(new InputStreamReader(assetManager.open("coco.names"))); 131 | String readLine = null; 132 | while ((readLine = reader.readLine()) != null) { 133 | resultLabel.add(readLine); 134 | } 135 | reader.close(); 136 | } catch (Exception e) { 137 | Log.e("labelCache", "error " + e); 138 | } 139 | } 140 | 141 | @Override 142 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { 143 | String image_path; 144 | RequestOptions options = new RequestOptions().skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE); 145 | if (resultCode == Activity.RESULT_OK) { 146 | switch (requestCode) { 147 | case SELECT_IMAGE: 148 | if (data == null) { 149 | Log.w(TAG, "user photo data is null"); 150 | return; 151 | } 152 | Uri image_uri = data.getData(); 153 | 154 | //Glide.with(MainActivity.this).load(image_uri).apply(options).into(show_image); 155 | 156 | // get image path from uri 157 | image_path = PhotoUtil.get_path_from_URI(MainActivity.this, image_uri); 158 | // predict image 159 | predict_image(image_path); 160 | break; 161 | } 162 | } 163 | } 164 | 165 | // predict image 166 | private void predict_image(String image_path) { 167 | // picture to float array 168 | Bitmap bmp = PhotoUtil.getScaleBitmap(image_path); 169 | Bitmap rgba = bmp.copy(Bitmap.Config.ARGB_8888, true); 170 | // resize to 416x416 171 | Bitmap input_bmp = Bitmap.createScaledBitmap(rgba, ddims[2], ddims[3], false); 172 | try { 173 | // Data format conversion takes too long 174 | // Log.d("inputData", Arrays.toString(inputData)); 175 | long start = System.currentTimeMillis(); 176 | // get predict result 177 | float[] result = yolov3tiny.Detect(input_bmp); 178 | if ( result==null ) { 179 | result_text.setText("predict result is null"); 180 | Log.d(TAG, " predict result is null"); 181 | show_image.setImageBitmap(input_bmp); 182 | return; 183 | } 184 | long end = System.currentTimeMillis(); 185 | Log.d(TAG, "origin predict result:" + Arrays.toString(result)); 186 | long time = end - start; 187 | Log.d("result length", "length of result: " + String.valueOf(result.length)); 188 | // show predict result and time 189 | //float[] r = get_max_result(result); 190 | 191 | String show_text = "time:" + time + "ms\n\n" ; 192 | Canvas canvas = new Canvas(input_bmp); 193 | //图像上画矩形 194 | Paint paint = new Paint(); 195 | 196 | float finalResult[][] = convertArray(result); 197 | int object_num = result.length/6;// number of object 198 | //continue to draw rect 199 | for(int index = 0; index < object_num; index++){ 200 | // 画框 201 | paint.setColor(Color.RED); 202 | paint.setStyle(Paint.Style.STROKE);//不填充 203 | paint.setStrokeWidth(2); //线的宽度 204 | canvas.drawRect(finalResult[index][2] * input_bmp.getWidth(), finalResult[index][3] * input_bmp.getHeight(), 205 | finalResult[index][4] * input_bmp.getWidth(), finalResult[index][5] * input_bmp.getHeight(), paint); 206 | 207 | //prob 208 | paint.setColor(Color.YELLOW); 209 | paint.setStyle(Paint.Style.FILL); 210 | paint.setStrokeWidth(4); //线的宽度 211 | String text = resultLabel.get((int) finalResult[index][0]) + " " + finalResult[index][1]; 212 | canvas.drawText(text, 213 | finalResult[index][2]*input_bmp.getWidth(),finalResult[index][3]*input_bmp.getHeight(),paint); 214 | show_text+=text+"\n"; 215 | } 216 | show_image.setImageBitmap(input_bmp); 217 | result_text.setText(show_text); 218 | 219 | } catch (Exception e) { 220 | e.printStackTrace(); 221 | } 222 | } 223 | 224 | //结果一维数组转化为二维数组 225 | public static float[][] convertArray(float[] inputfloat){ 226 | int n = inputfloat.length; 227 | int num = inputfloat.length/6; 228 | float[][] outputfloat = new float[num][6]; 229 | int k = 0; 230 | for(int i = 0; i < num ; i++) 231 | { 232 | int j = 0; 233 | while(j<6) 234 | { 235 | outputfloat[i][j] = inputfloat[k]; 236 | k++; 237 | j++; 238 | } 239 | } 240 | return outputfloat; 241 | } 242 | 243 | 244 | // get max probability label 245 | private float[] get_max_result(float[] result) { 246 | int num_rs = result.length / 6; 247 | float maxProp = result[1]; 248 | int maxI = 0; 249 | for(int i = 1; i permissionList = new ArrayList<>(); 265 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 266 | permissionList.add(Manifest.permission.CAMERA); 267 | } 268 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 269 | permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); 270 | } 271 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 272 | permissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE); 273 | } 274 | // if list is not empty will request permissions 275 | if (!permissionList.isEmpty()) { 276 | ActivityCompat.requestPermissions(this, permissionList.toArray(new String[permissionList.size()]), 1); 277 | } 278 | } 279 | 280 | @Override 281 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 282 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 283 | switch (requestCode) { 284 | case 1: 285 | if (grantResults.length > 0) { 286 | for (int i = 0; i < grantResults.length; i++) { 287 | int grantResult = grantResults[i]; 288 | if (grantResult == PackageManager.PERMISSION_DENIED) { 289 | String s = permissions[i]; 290 | Toast.makeText(this, s + "permission was denied", Toast.LENGTH_SHORT).show(); 291 | } 292 | } 293 | } 294 | break; 295 | } 296 | } 297 | 298 | } 299 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/yolov3tiny/PhotoUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.yolov3tiny; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.database.Cursor; 7 | import android.graphics.Bitmap; 8 | import android.graphics.BitmapFactory; 9 | import android.net.Uri; 10 | import android.provider.MediaStore; 11 | 12 | public class PhotoUtil { 13 | // get picture in photo 14 | public static void use_photo(Activity activity, int requestCode) { 15 | Intent intent = new Intent(Intent.ACTION_PICK); 16 | intent.setType("image/*"); 17 | activity.startActivityForResult(intent, requestCode); 18 | } 19 | 20 | // get photo from Uri 21 | public static String get_path_from_URI(Context context, Uri uri) { 22 | String result; 23 | Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); 24 | if (cursor == null) { 25 | result = uri.getPath(); 26 | } else { 27 | cursor.moveToFirst(); 28 | int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 29 | result = cursor.getString(idx); 30 | cursor.close(); 31 | } 32 | return result; 33 | } 34 | 35 | // compress picture 36 | public static Bitmap getScaleBitmap(String filePath) { 37 | BitmapFactory.Options opt = new BitmapFactory.Options(); 38 | opt.inJustDecodeBounds = true; 39 | BitmapFactory.decodeFile(filePath, opt); 40 | 41 | int bmpWidth = opt.outWidth; 42 | int bmpHeight = opt.outHeight; 43 | 44 | int maxSize = 1280;//500 45 | 46 | // compress picture with inSampleSize 47 | opt.inSampleSize = 1; 48 | while (true) { 49 | if (bmpWidth / opt.inSampleSize < maxSize || bmpHeight / opt.inSampleSize < maxSize) { 50 | break; 51 | } 52 | opt.inSampleSize *= 2; 53 | } 54 | opt.inJustDecodeBounds = false; 55 | return BitmapFactory.decodeFile(filePath, opt); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/yolov3tiny/yolov3Tiny.java: -------------------------------------------------------------------------------- 1 | package com.example.yolov3tiny; 2 | import android.graphics.Bitmap; 3 | 4 | public class yolov3Tiny { 5 | public native boolean Init(String param, String bin); 6 | public native float[] Detect(Bitmap bitmap); 7 | static { 8 | System.loadLibrary("yolov3_tiny_jni"); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libncnn.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paleomoon/darknet-ncnn-android/dea4cc0b128eb5054ff3f69af20d473f874558d2/app/src/main/jniLibs/armeabi-v7a/libncnn.a -------------------------------------------------------------------------------- /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/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/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 14 |