├── .gitignore ├── LICENSE ├── README.md ├── image ├── Mat.png ├── lession-5.png └── tree.png └── lesson ├── lesson_1 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── lession_1.cpp │ ├── tmp.model │ └── tmp.proto └── src │ ├── CMakeLists.txt │ ├── datareader.cpp │ └── datareader.h ├── lesson_10 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── dog.png │ ├── lession_10.cpp │ ├── squeezenet_v1.1.bin │ └── squeezenet_v1.1.param └── src │ ├── CMakeLists.txt │ ├── allocator.h │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── layer │ ├── concat.cpp │ ├── concat.h │ ├── convolution.cpp │ ├── convolution.h │ ├── dropout.cpp │ ├── dropout.h │ ├── input.cpp │ ├── input.h │ ├── pooling.cpp │ ├── pooling.h │ ├── relu.cpp │ ├── relu.h │ ├── softmax.cpp │ ├── softmax.h │ ├── split.cpp │ └── split.h │ ├── layer_declaration.h │ ├── mat.h │ ├── mat_pixel.cpp │ ├── modelbin.cpp │ ├── modelbin.h │ ├── net.cpp │ ├── net.h │ ├── option.cpp │ ├── option.h │ ├── paramdict.cpp │ └── paramdict.h ├── lesson_2 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ └── lession_2.cpp └── src │ ├── CMakeLists.txt │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── net.cpp │ └── net.h ├── lesson_3 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── lession_3.cpp │ └── squeezenet_v1.1.param └── src │ ├── CMakeLists.txt │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── net.cpp │ ├── net.h │ ├── paramdict.cpp │ └── paramdict.h ├── lesson_4 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── lession_4.cpp │ └── squeezenet_v1.1.param └── src │ ├── CMakeLists.txt │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── layer │ ├── concat.cpp │ ├── concat.h │ ├── convolution.cpp │ ├── convolution.h │ ├── dropout.cpp │ ├── dropout.h │ ├── input.cpp │ ├── input.h │ ├── pooling.cpp │ ├── pooling.h │ ├── relu.cpp │ ├── relu.h │ ├── softmax.cpp │ ├── softmax.h │ ├── split.cpp │ └── split.h │ ├── net.cpp │ ├── net.h │ ├── paramdict.cpp │ └── paramdict.h ├── lesson_5 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── lession_5.cpp │ └── squeezenet_v1.1.param └── src │ ├── CMakeLists.txt │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── layer │ ├── concat.cpp │ ├── concat.h │ ├── convolution.cpp │ ├── convolution.h │ ├── dropout.cpp │ ├── dropout.h │ ├── input.cpp │ ├── input.h │ ├── pooling.cpp │ ├── pooling.h │ ├── relu.cpp │ ├── relu.h │ ├── softmax.cpp │ ├── softmax.h │ ├── split.cpp │ └── split.h │ ├── layer_declaration.h │ ├── net.cpp │ ├── net.h │ ├── paramdict.cpp │ └── paramdict.h ├── lesson_6 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── lession_6.cpp │ └── squeezenet_v1.1.param └── src │ ├── CMakeLists.txt │ ├── allocator.h │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── layer │ ├── concat.cpp │ ├── concat.h │ ├── convolution.cpp │ ├── convolution.h │ ├── dropout.cpp │ ├── dropout.h │ ├── input.cpp │ ├── input.h │ ├── pooling.cpp │ ├── pooling.h │ ├── relu.cpp │ ├── relu.h │ ├── softmax.cpp │ ├── softmax.h │ ├── split.cpp │ └── split.h │ ├── layer_declaration.h │ ├── net.cpp │ ├── net.h │ ├── paramdict.cpp │ └── paramdict.h ├── lesson_7 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── lession_7.cpp │ └── squeezenet_v1.1.param └── src │ ├── CMakeLists.txt │ ├── allocator.h │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── layer │ ├── concat.cpp │ ├── concat.h │ ├── convolution.cpp │ ├── convolution.h │ ├── dropout.cpp │ ├── dropout.h │ ├── input.cpp │ ├── input.h │ ├── pooling.cpp │ ├── pooling.h │ ├── relu.cpp │ ├── relu.h │ ├── softmax.cpp │ ├── softmax.h │ ├── split.cpp │ └── split.h │ ├── layer_declaration.h │ ├── mat.h │ ├── net.cpp │ ├── net.h │ ├── paramdict.cpp │ └── paramdict.h ├── lesson_8 ├── CMakeLists.txt ├── examples │ ├── CMakeLists.txt │ ├── lession_8.cpp │ ├── squeezenet_v1.1.bin │ └── squeezenet_v1.1.param └── src │ ├── CMakeLists.txt │ ├── allocator.h │ ├── blob.cpp │ ├── blob.h │ ├── datareader.cpp │ ├── datareader.h │ ├── layer.cpp │ ├── layer.h │ ├── layer │ ├── concat.cpp │ ├── concat.h │ ├── convolution.cpp │ ├── convolution.h │ ├── dropout.cpp │ ├── dropout.h │ ├── input.cpp │ ├── input.h │ ├── pooling.cpp │ ├── pooling.h │ ├── relu.cpp │ ├── relu.h │ ├── softmax.cpp │ ├── softmax.h │ ├── split.cpp │ └── split.h │ ├── layer_declaration.h │ ├── mat.h │ ├── modelbin.cpp │ ├── modelbin.h │ ├── net.cpp │ ├── net.h │ ├── paramdict.cpp │ └── paramdict.h └── lesson_9 ├── CMakeLists.txt ├── examples ├── CMakeLists.txt ├── dog.png ├── lession_9.cpp ├── squeezenet_v1.1.bin └── squeezenet_v1.1.param └── src ├── CMakeLists.txt ├── allocator.h ├── blob.cpp ├── blob.h ├── datareader.cpp ├── datareader.h ├── layer.cpp ├── layer.h ├── layer ├── concat.cpp ├── concat.h ├── convolution.cpp ├── convolution.h ├── dropout.cpp ├── dropout.h ├── input.cpp ├── input.h ├── pooling.cpp ├── pooling.h ├── relu.cpp ├── relu.h ├── softmax.cpp ├── softmax.h ├── split.cpp └── split.h ├── layer_declaration.h ├── mat.h ├── mat_pixel.cpp ├── modelbin.cpp ├── modelbin.h ├── net.cpp ├── net.h ├── paramdict.cpp └── paramdict.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | 35 | # ignore build folder 36 | [bB]uild 37 | saferm 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Zhengtq 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NCNN BREAKDOWN 2 | a breakdown of NCNN 3 | 4 | ## 一 5 | 6 | 这个tutorial是笔者在自己学习ncnn的过程的一个记录.等于把自己的理解写了出来,如果有差错,还请大家指正. 7 | 8 | 这个tutorial还没有写完,后面会随着学习的深入,会不定期的更新. 9 | 10 | ## 二 11 | 12 | 这个tutorial的每一节,会分为4个section来讲述,分别是: 13 | 14 | > - **开始**  15 | > - **作用** 16 | > - **实现** 17 | > - **代码示例** 18 | 19 | **开始**:每一节的开始,说一下当前学习计划. 20 | 21 | **作用**:说一下本节要讲的内容的作用. 22 | 23 | **实现**:说一下这一节的内容ncnn是如何实现的. 24 | 25 | **代码示例**:把这一节的内容中ncnn相关的代码拿出来,写了个例子. 26 | 27 | ## 三 28 | 29 | 每一节,为了方便展示,我都会用一些图表来展示,如: 30 | 31 | 32 | 33 | ![lession-5](https://github.com/Zhengtq/ncnn_breakdown/blob/main/image/lession-5.png) 34 | 35 | ![Mat](https://github.com/Zhengtq/ncnn_breakdown/blob/main/image/Mat.png) 36 | 37 | ![](https://github.com/Zhengtq/ncnn_breakdown/blob/main/image/tree.png) 38 | 39 | | head | pad_x | (head_use)elemsize | elemsize | elemsize | elemsize | pad_y | pad_y... | (x) | 40 | | :--- | ----- | ------------------ | :------: | -------- | -------- | ----- | -------- | -------- | 41 | | (x) | (x) | (channel2)elemsize | elemsize | elemsize | elemsize | pad_y | pad_y... | (x) | 42 | | (x) | (x) | (channel3)elemsize | elemsize | elemsize | elemsize | pad_y | pad_y... | (x) | 43 | | (x) | (x) | (channel4)elemsize | elemsize | elemsize | elemsize | pad_y | pad_y... | pad_z... | 44 | 45 | ## 四 46 | 47 | 在每一节的最后,我都会附上对应的示例代码.在使用每一节的示例代码时候,需要自己clone下来,然后自己编译.一个常用的过程如下: 48 | 49 | ```bash 50 | git clone git@github.com:Zhengtq/ncnn_breakdown.git 51 | cd ncnn_breakdown && cd lesson && cd lesson_1 52 | mkdir build &&cd build 53 | cmake .. 54 | make -j8 55 | ./examples/lession_1 56 | ``` 57 | 58 | ## 五 59 | 60 | Have Fun ! 61 | 62 | -------------------------------------------------------------------------------- /image/Mat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/image/Mat.png -------------------------------------------------------------------------------- /image/lession-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/image/lession-5.png -------------------------------------------------------------------------------- /image/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/image/tree.png -------------------------------------------------------------------------------- /lesson/lesson_1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession1) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_1/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_1) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_1/examples/lession_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "datareader.h" 5 | #include 6 | using namespace std; 7 | 8 | int test_dr_scan() { 9 | const char* file_path = "../examples/tmp.proto"; 10 | FILE* fp = fopen(file_path, "rb"); 11 | ncnn::DataReaderFromStdio dr(fp); 12 | 13 | int ret = 0; 14 | while(1) 15 | { 16 | char layer_type[256]; 17 | ret = dr.scan("%s", &layer_type); 18 | if (ret == -1) break; 19 | int layer_id; 20 | ret = dr.scan("%d", &layer_id); 21 | if (ret == -1) break; 22 | cout << layer_type << " " << layer_id << endl; 23 | } 24 | return 0; 25 | } 26 | int test_dr_read() { 27 | const char* file_path = "../examples/tmp.model"; 28 | FILE* fp = fopen(file_path, "rb"); 29 | ncnn::DataReaderFromStdio dr(fp); 30 | 31 | int ret = 0; 32 | while (1) { 33 | char* a = new char(4); 34 | ret = dr.read(a, sizeof(char) * 4); 35 | cout << a << endl; 36 | if (ret == 0) break; 37 | } 38 | return 0; 39 | } 40 | int main(int argc, char** argv) { 41 | // test_dr_scan(); 42 | test_dr_read(); 43 | 44 | printf("yes\n"); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /lesson/lesson_1/examples/tmp.model: -------------------------------------------------------------------------------- 1 | 123 2 | 234 3 | 456 4 | 345 5 | 657 6 | 234 7 | -------------------------------------------------------------------------------- /lesson/lesson_1/examples/tmp.proto: -------------------------------------------------------------------------------- 1 | Input 0 2 | Convolution 1 3 | ReLU 2 4 | SPlit 3 5 | Softmax 4 6 | 7 | 8 | -------------------------------------------------------------------------------- /lesson/lesson_1/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | ) 6 | 7 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 8 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 9 | 10 | 11 | -------------------------------------------------------------------------------- /lesson/lesson_1/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_1/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_10/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession10) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_10/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | find_package(OpenCV QUIET COMPONENTS opencv_world) 8 | if("${OpenCV_LIBS}" STREQUAL "") 9 | set(OpenCV_FOUND FALSE) 10 | endif() 11 | 12 | if(NOT OpenCV_FOUND) 13 | find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs videoio) 14 | endif() 15 | 16 | 17 | if(NOT OpenCV_FOUND) 18 | find_package(OpenCV QUIET COMPONENTS core highgui imgproc) 19 | endif() 20 | 21 | 22 | 23 | 24 | 25 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 26 | ncnn_add_example(lession_10) 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /lesson/lesson_10/examples/dog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/lesson/lesson_10/examples/dog.png -------------------------------------------------------------------------------- /lesson/lesson_10/examples/lession_10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "allocator.h" 8 | #include "blob.h" 9 | #include "datareader.h" 10 | #include "iostream" 11 | #include "layer.h" 12 | #include "mat.h" 13 | #include "net.h" 14 | using namespace std; 15 | 16 | int main(int argc, char** argv) { 17 | ncnn::Net squeezenet; 18 | squeezenet.load_param("../examples/squeezenet_v1.1.param"); 19 | squeezenet.load_model("../examples/squeezenet_v1.1.bin"); 20 | 21 | const char* imagepath = "../examples/dog.png"; 22 | cv::Mat bgr = cv::imread(imagepath, 1); 23 | ncnn::Mat in = ncnn::Mat::from_pixels(bgr.data, ncnn::Mat::PIXEL_BGR, bgr.cols, bgr.rows); 24 | 25 | ncnn::Extractor ex = squeezenet.create_extractor(); 26 | ex.input("data", in); 27 | ncnn::Mat out; 28 | ex.extract("prob", out); 29 | 30 | printf("yes\n"); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /lesson/lesson_10/examples/squeezenet_v1.1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/lesson/lesson_10/examples/squeezenet_v1.1.bin -------------------------------------------------------------------------------- /lesson/lesson_10/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | modelbin.cpp 10 | mat_pixel.cpp 11 | option.cpp 12 | ) 13 | 14 | 15 | file(GLOB SRC_LAYER ${CMAKE_CURRENT_SOURCE_DIR}/layer/*.c*) 16 | list(APPEND ncnn_SRCS ${SRC_LAYER}) 17 | 18 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 19 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 20 | 21 | 22 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_ALLOCATOR_H 2 | #define NCNN_ALLOCATOR_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | #define MALLOC_ALIGN 16 9 | 10 | //相当于ptr首先向后移动n-1的位置,然后用-n进行最高位直接截断对其 11 | template 12 | static inline _Tp* alignPtr(_Tp* ptr, int n = (int)sizeof(_Tp)) { 13 | return (_Tp*)(((size_t)ptr + n - 1) & -n); 14 | } 15 | 16 | static inline size_t alignSize(size_t sz, int n) { return (sz + n - 1) & -n; } 17 | 18 | 19 | static inline void* fastMalloc(size_t size) { 20 | //符合POSIX标准的c源码 21 | #if (defined(__unix__)) && _POSIX_C_SOURCE >= 200112L 22 | void* ptr = 0; 23 | if (posix_memalign(&ptr, MALLOC_ALIGN, size)) ptr = 0; 24 | return ptr; 25 | #else 26 | //预留需要的空间,sizeof(void*)的目的是给udata的地址留下空间,MALLOC_ALIGN的目的是使得对齐后有size的空间 27 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 28 | if (!udata) return 0; 29 | //从udata+8开始,其中8是udata地址的位置, 30 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 31 | adata[-1] = udata; 32 | return adata; 33 | #endif 34 | } 35 | 36 | static inline int NCNN_XADD(int* addr, int delta) { 37 | int tmp = *addr; 38 | *addr += delta; 39 | return tmp; 40 | } 41 | 42 | static inline void fastFree(void* ptr) { 43 | if (ptr) { 44 | #if _MSC_VER 45 | _aligned_free(ptr); 46 | #elif (defined(__unix__) || defined(__APPLE__)) && _POSIX_C_SOURCE >= 200112L || \ 47 | (__ANDROID__ && __ANDROID_API__ >= 17) 48 | free(ptr); 49 | #elif __ANDROID__ && __ANDROID_API__ < 17 50 | free(ptr); 51 | #else 52 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 53 | free(udata); 54 | #endif 55 | } 56 | } 57 | 58 | class Allocator { 59 | public: 60 | virtual void* fastMalloc(size_t size) = 0; 61 | virtual void* fastFree(void* ptr) = 0; 62 | }; 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | #include "layer_declaration.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Layer::Layer() { 10 | one_blob_only = false; 11 | support_inplace = false; 12 | } 13 | Layer::~Layer() {} 14 | 15 | int Layer::load_param(const ParamDict&) { return 0; } 16 | int Layer::load_model(const ModelBin&) { return 0; } 17 | 18 | int Layer::forward(const std::vector& bottom_blobs, std::vector& top_blobs, 19 | const Option& opt) const { 20 | if (!support_inplace) return -1; 21 | top_blobs = bottom_blobs; 22 | 23 | for (int i = 0; i < (int)top_blobs.size(); i++) { 24 | top_blobs[i] = bottom_blobs[i].clone(opt.blob_allocator); 25 | if (top_blobs[i].empty()) return -100; 26 | } 27 | 28 | return forward_inplace(top_blobs, opt); 29 | } 30 | 31 | int Layer::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const { 32 | if (!support_inplace) return -1; 33 | 34 | top_blob = bottom_blob.clone(opt.blob_allocator); 35 | if (top_blob.empty()) return -100; 36 | 37 | return forward_inplace(top_blob, opt); 38 | } 39 | 40 | int Layer::forward_inplace(std::vector&, const Option&) const { return -1; } 41 | 42 | int Layer::forward_inplace(Mat&, const Option&) const { return -1; } 43 | 44 | static const layer_registry_entry layer_registry[] = { 45 | {"ReLU", ReLU_final_layer_creator}, 46 | {"Input", Input_final_layer_creator}, 47 | {"Pooling", Pooling_final_layer_creator}, 48 | {"Convolution", Convolution_final_layer_creator}, 49 | {"Split", Split_final_layer_creator}, 50 | {"Concat", Concat_final_layer_creator}, 51 | {"Dropout", Dropout_final_layer_creator}, 52 | {"Softmax", Softmax_final_layer_creator}, 53 | 54 | }; 55 | 56 | //确定一共有多少个layer 57 | static const int layer_registry_entry_count = 58 | sizeof(layer_registry) / sizeof(layer_registry_entry); 59 | 60 | int layer_to_index(const char* type) { 61 | for (int i = 0; i < layer_registry_entry_count; i++) { 62 | if (strcmp(type, layer_registry[i].name) == 0) return i; 63 | } 64 | return -1; 65 | } 66 | 67 | Layer* create_layer(const char* type) { 68 | int index = layer_to_index(type); 69 | if (index == -1) return 0; 70 | return create_layer(index); 71 | } 72 | 73 | //基于id在数组里面找constructor 74 | Layer* create_layer(int index) { 75 | if (index < 0 || index >= layer_registry_entry_count) return 0; 76 | 77 | layer_creator_func layer_creator = 0; 78 | { layer_creator = layer_registry[index].creator; } 79 | 80 | if (!layer_creator) return 0; 81 | 82 | Layer* layer = layer_creator(); 83 | layer->typeindex = index; 84 | return layer; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "modelbin.h" 7 | #include "paramdict.h" 8 | #include "mat.h" 9 | #include "option.h" 10 | 11 | namespace ncnn { 12 | 13 | class Layer { 14 | public: 15 | Layer(); 16 | virtual ~Layer(); 17 | virtual int load_param(const ParamDict& pd); 18 | virtual int load_model(const ModelBin& mb); 19 | 20 | public: 21 | bool one_blob_only; 22 | bool support_inplace; 23 | 24 | int typeindex; 25 | std::string type; 26 | std::string name; 27 | std::vector bottoms; 28 | std::vector tops; 29 | 30 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs, 31 | const Option& opt) const; 32 | virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const; 33 | 34 | virtual int forward_inplace(std::vector& bottom_top_blobs, const Option& opt) const; 35 | virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; 36 | }; 37 | 38 | typedef Layer* (*layer_creator_func)(); 39 | 40 | struct layer_registry_entry { 41 | const char* name; 42 | layer_creator_func creator; 43 | }; 44 | 45 | int layer_to_index(const char* type); 46 | Layer* create_layer(const char* type); 47 | Layer* create_layer(int index); 48 | 49 | #define DEFINE_LAYER_CREATOR(name) \ 50 | ncnn::Layer* name##_final_layer_creator() { return new name; } 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/concat.cpp: -------------------------------------------------------------------------------- 1 | #include "concat.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Concat::Concat() { 8 | one_blob_only = false; 9 | support_inplace = false; 10 | } 11 | 12 | int Concat::load_param(const ParamDict& pd) { 13 | axis = pd.get(0, 0); 14 | return 0; 15 | } 16 | 17 | int Concat::forward(const std::vector& bottom_blobs, std::vector& top_blobs, 18 | const Option&) const { 19 | cout << "CONCAT_FOREARD" << endl; 20 | const Mat& bottom_blob = bottom_blobs[0]; 21 | 22 | for (size_t i = 0; i < top_blobs.size(); i++) { 23 | top_blobs[i] = bottom_blob; 24 | } 25 | return 0; 26 | } 27 | 28 | 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/concat.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONCAT_H 2 | #define LAYER_CONCAT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Concat : public Layer { 9 | public: 10 | Concat(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs, 13 | const Option& opt) const; 14 | 15 | public: 16 | int axis; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/convolution.cpp: -------------------------------------------------------------------------------- 1 | #include "convolution.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Convolution::Convolution() { 8 | one_blob_only = true; 9 | support_inplace = false; 10 | } 11 | 12 | int Convolution::load_param(const ParamDict& pd) { 13 | num_output = pd.get(0, 0); 14 | kernel_w = pd.get(1, 0); 15 | kernel_h = pd.get(11, kernel_w); 16 | dilation_w = pd.get(2, 1); 17 | dilation_h = pd.get(12, dilation_w); 18 | stride_w = pd.get(3, 1); 19 | stride_h = pd.get(13, stride_w); 20 | pad_left = pd.get(4, 0); 21 | pad_right = pd.get(15, pad_left); 22 | pad_top = pd.get(14, pad_left); 23 | pad_bottom = pd.get(16, pad_top); 24 | pad_value = pd.get(18, 0.f); 25 | bias_term = pd.get(5, 0); 26 | weight_data_size = pd.get(6, 0); 27 | int8_scale_term = pd.get(8, 0); 28 | activation_params = pd.get(10, Mat()); 29 | impl_type = pd.get(17, 0); 30 | 31 | 32 | return 0; 33 | } 34 | 35 | int Convolution::load_model(const ModelBin& mb) { 36 | weight_data = mb.load(weight_data_size, 0); 37 | if (weight_data.empty()) return -100; 38 | 39 | if (bias_term) { 40 | bias_data = mb.load(num_output, 1); 41 | if (bias_data.empty()) return -100; 42 | } 43 | return 0; 44 | } 45 | 46 | int Convolution::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const { 47 | cout << "CONV FORWARD" << endl; 48 | top_blob = bottom_blob.clone(opt.blob_allocator); 49 | return 0; 50 | } 51 | 52 | 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/convolution.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONVOLUTION_H 2 | #define LAYER_CONVOLUTION_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Convolution : public Layer { 9 | public: 10 | Convolution(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int load_model(const ModelBin& mb); 13 | virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const; 14 | 15 | public: 16 | int num_output; 17 | int kernel_w; 18 | int kernel_h; 19 | int dilation_w; 20 | int dilation_h; 21 | int stride_w; 22 | int stride_h; 23 | int pad_left; 24 | int pad_right; 25 | int pad_top; 26 | int pad_bottom; 27 | float pad_value; 28 | int bias_term; 29 | int weight_data_size; 30 | int int8_scale_term; 31 | int activation_type; 32 | Mat activation_params; 33 | Mat weight_data; 34 | Mat bias_data; 35 | Mat weight_data_int8_scale; 36 | float bottom_blob_int8_scale; 37 | float top_blob_int8_scale; 38 | bool use_int8_requantize; 39 | int impl_type; 40 | 41 | }; 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/dropout.cpp: -------------------------------------------------------------------------------- 1 | #include "dropout.h" 2 | 3 | namespace ncnn { 4 | 5 | Dropout::Dropout() { 6 | one_blob_only = true; 7 | support_inplace = true; 8 | } 9 | 10 | int Dropout::load_param(const ParamDict& pd) { 11 | scale = pd.get(0, 1.f); 12 | return 0; 13 | } 14 | 15 | int Dropout::forward_inplace(Mat& bottom_top_blob, const Option& opt) const { 16 | cout << "DROPOUT_FORWARD" << endl; 17 | return 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/dropout.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_DROPOUT_h 2 | #define LAYER_DROPOUT_h 3 | #include "layer.h" 4 | 5 | namespace ncnn { 6 | 7 | class Dropout : public Layer { 8 | public: 9 | Dropout(); 10 | virtual int load_param(const ParamDict& pd); 11 | virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; 12 | 13 | public: 14 | float scale; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Input::Input() { 8 | one_blob_only = true; 9 | support_inplace = true; 10 | } 11 | 12 | int Input::load_param(const ParamDict& pd) { 13 | w = pd.get(0, 0); 14 | h = pd.get(1, 0); 15 | c = pd.get(2, 0); 16 | return 0; 17 | } 18 | 19 | int Input::forward_inplace(Mat&, const Option&) const { 20 | cout << "input_forward" << endl; 21 | return 0; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/input.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_INPUT_H 2 | #define LAYER_INPUT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Input : public Layer { 9 | public: 10 | Input(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; 13 | 14 | public: 15 | int w; 16 | int h; 17 | int c; 18 | }; 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/pooling.cpp: -------------------------------------------------------------------------------- 1 | #include "pooling.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Pooling::Pooling() { 8 | one_blob_only = true; 9 | support_inplace = false; 10 | } 11 | 12 | int Pooling::load_param(const ParamDict& pd) { 13 | pooling_type = pd.get(0, 0); 14 | kernel_w = pd.get(1, 0); 15 | kernel_h = pd.get(11, kernel_w); 16 | stride_w = pd.get(2, 1); 17 | stride_h = pd.get(12, stride_w); 18 | pad_left = pd.get(3, 0); 19 | pad_right = pd.get(14, pad_left); 20 | pad_top = pd.get(13, pad_left); 21 | pad_bottom = pd.get(15, pad_top); 22 | global_pooling = pd.get(5, 0); 23 | avgpool_count_include_pad = pd.get(6, 0); 24 | return 0; 25 | } 26 | 27 | int Pooling::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const { 28 | cout << "POOLING_FORWARD" << endl; 29 | top_blob = bottom_blob.clone(opt.blob_allocator); 30 | 31 | return 0; 32 | } 33 | 34 | 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/pooling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_POOLING_H 2 | #define LAYER_POOLING_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Pooling : public Layer { 9 | public: 10 | Pooling(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const; 13 | 14 | enum PoolMethod { PoolMethod_MAX = 0, PoolMethod_AVE = 1 }; 15 | 16 | public: 17 | int pooling_type; 18 | int kernel_w; 19 | int kernel_h; 20 | int stride_w; 21 | int stride_h; 22 | int pad_left; 23 | int pad_right; 24 | int pad_top; 25 | int pad_bottom; 26 | int global_pooling; 27 | int pad_mode; 28 | int avgpool_count_include_pad; 29 | }; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/relu.cpp: -------------------------------------------------------------------------------- 1 | #include "relu.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | ReLU::ReLU() { 8 | one_blob_only = true; 9 | support_inplace = true; 10 | } 11 | 12 | int ReLU::load_param(const ParamDict& pd) { 13 | slope = pd.get(0, 0.f); 14 | return 0; 15 | } 16 | 17 | int ReLU::forward_inplace(Mat& bottom_top_blob, const Option& opt) const { 18 | cout << "RELU_FORWARD" << endl; 19 | 20 | return 0; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/relu.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_RELU_H 2 | #define LAYER_RELU_H 3 | #include 4 | #include "layer.h" 5 | using namespace std; 6 | namespace ncnn { 7 | 8 | class ReLU : public Layer { 9 | public: 10 | ReLU(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; 13 | 14 | public: 15 | float slope; 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/softmax.cpp: -------------------------------------------------------------------------------- 1 | #include "softmax.h" 2 | 3 | namespace ncnn { 4 | 5 | Softmax::Softmax() { 6 | one_blob_only = true; 7 | support_inplace = true; 8 | } 9 | 10 | int Softmax::load_param(const ParamDict& pd) { 11 | axis = pd.get(0, 9); 12 | return 0; 13 | } 14 | 15 | int Softmax::forward_inplace(Mat& bottom_top_blob, const Option& opt) const { 16 | 17 | cout << "SOFTMAX_FORWARD" << endl; 18 | return 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SOFTMAX_H 2 | #define LAYER_SOFTMAX_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Softmax : public Layer { 9 | public: 10 | Softmax(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; 13 | 14 | public: 15 | int axis; 16 | }; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/split.cpp: -------------------------------------------------------------------------------- 1 | #include "split.h" 2 | 3 | namespace ncnn { 4 | 5 | Split::Split() { 6 | one_blob_only = false; 7 | support_inplace = false; 8 | } 9 | 10 | int Split::forward(const std::vector& bottom_blobs, std::vector& top_blobs, 11 | const Option&) const { 12 | cout << "SPLIT_FORWARD" << endl; 13 | const Mat& bottom_blob = bottom_blobs[0]; 14 | for (size_t i = 0; i < top_blobs.size(); i++) { 15 | top_blobs[i] = bottom_blob; 16 | } 17 | return 0; 18 | } 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer/split.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SPLIT_H 2 | #define LAYER_SPLIT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Split : public Layer { 9 | public: 10 | Split(); 11 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs, 12 | const Option& opt) const; 13 | }; 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/layer_declaration.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_DECLARATION 2 | #define NCNN_LAYER_DECLARATION 3 | #include "layer/relu.h" 4 | namespace ncnn { 5 | DEFINE_LAYER_CREATOR(ReLU) 6 | } 7 | #include "layer/input.h" 8 | namespace ncnn { 9 | DEFINE_LAYER_CREATOR(Input) 10 | } 11 | 12 | #include "layer/pooling.h" 13 | namespace ncnn { 14 | DEFINE_LAYER_CREATOR(Pooling) 15 | } 16 | 17 | #include "layer/convolution.h" 18 | namespace ncnn { 19 | DEFINE_LAYER_CREATOR(Convolution) 20 | } 21 | 22 | #include "layer/split.h" 23 | namespace ncnn { 24 | DEFINE_LAYER_CREATOR(Split) 25 | } 26 | 27 | #include "layer/concat.h" 28 | namespace ncnn { 29 | DEFINE_LAYER_CREATOR(Concat) 30 | } 31 | 32 | #include "layer/dropout.h" 33 | namespace ncnn { 34 | DEFINE_LAYER_CREATOR(Dropout) 35 | } 36 | 37 | #include "layer/softmax.h" 38 | namespace ncnn { 39 | DEFINE_LAYER_CREATOR(Softmax) 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/mat_pixel.cpp: -------------------------------------------------------------------------------- 1 | #include "mat.h" 2 | 3 | namespace ncnn { 4 | static int from_rgb(const unsigned char* rgb, int w, int h, int stride, Mat& m, 5 | Allocator* allocator) { 6 | m.create(w, h, 3, 4u, allocator); 7 | if (m.empty()) return -100; 8 | 9 | const int wgap = stride - w * 3; 10 | if (wgap == 0) { 11 | w = w * h; 12 | h = 1; 13 | } 14 | 15 | float* ptr0 = m.channel(0); 16 | float* ptr1 = m.channel(1); 17 | float* ptr2 = m.channel(2); 18 | 19 | for (int y = 0; y < h; y++) { 20 | int remain = w; 21 | for (; remain > 0; remain--) { 22 | *ptr0 = rgb[0]; 23 | *ptr1 = rgb[1]; 24 | *ptr2 = rgb[2]; 25 | rgb += 3; 26 | ptr0++; 27 | ptr1++; 28 | ptr2++; 29 | } 30 | rgb += wgap; 31 | } 32 | 33 | cout << "success" << endl; 34 | return 0; 35 | } 36 | 37 | Mat Mat::from_pixels(const unsigned char* pixels, int type, int w, int h, Allocator* allocator) { 38 | if (type == PIXEL_RGB || type == PIXEL_BGR) { 39 | return Mat::from_pixels(pixels, type, w, h, w * 3, allocator); 40 | } 41 | return Mat(); 42 | } 43 | 44 | Mat Mat::from_pixels(const unsigned char* pixels, int type, int w, int h, int stride, 45 | Allocator* allocator) { 46 | Mat m; 47 | if (type == PIXEL_RGB || PIXEL_RGB) from_rgb(pixels, w, h, stride, m, allocator); 48 | return m; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/modelbin.cpp: -------------------------------------------------------------------------------- 1 | #include "modelbin.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ModelBin::~ModelBin() {} 10 | 11 | 12 | ModelBinFromDataReader::ModelBinFromDataReader(const DataReader& _dr) : dr(_dr) {} 13 | 14 | Mat ModelBinFromDataReader::load(int w, int type) const { 15 | if (type == 0) { 16 | size_t nread; 17 | 18 | union { 19 | struct { 20 | unsigned char f0; 21 | unsigned char f1; 22 | unsigned char f2; 23 | unsigned char f3; 24 | }; 25 | unsigned int tag; 26 | 27 | } flag_struct; 28 | 29 | nread = dr.read(&flag_struct, sizeof(flag_struct)); 30 | 31 | 32 | unsigned int flag = flag_struct.f0 + flag_struct.f1 + flag_struct.f2 + flag_struct.f3; 33 | Mat m(w); 34 | if (m.empty()) return m; 35 | if (flag != 0) { 36 | return m; 37 | } else if (flag_struct.f0 == 0) { 38 | nread = dr.read(m, w * sizeof(float)); 39 | } 40 | return m; 41 | } else if (type == 1) { 42 | Mat m(w); 43 | if (m.empty()) return m; 44 | size_t nread = dr.read(m, w * sizeof(float)); 45 | return m; 46 | } 47 | return Mat(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/modelbin.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_MODELBIN_H 2 | #define NCNN_MODELBIN_H 3 | 4 | #include "mat.h" 5 | 6 | namespace ncnn { 7 | 8 | class DataReader; 9 | class ModelBin { 10 | public: 11 | virtual ~ModelBin(); 12 | virtual Mat load(int w, int type) const = 0; 13 | }; 14 | 15 | class ModelBinFromDataReader : public ModelBin { 16 | public: 17 | ModelBinFromDataReader(const DataReader& dr); 18 | virtual Mat load(int w, int type) const; 19 | 20 | protected: 21 | const DataReader& dr; 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Extractor; 13 | class Net { 14 | public: 15 | Net(); 16 | ~Net(); 17 | 18 | Option opt; 19 | int load_param(const DataReader& dr); 20 | int load_param(const char* protopath); 21 | 22 | int load_model(const DataReader& dr); 23 | int load_model(const char* modelpath); 24 | 25 | Extractor create_extractor() const; 26 | 27 | public: 28 | std::vector layers; 29 | std::vector blobs; //存放blob的信息,如layer或者shape等等 30 | 31 | protected: 32 | int find_blob_index_by_name(const char* name) const; 33 | friend class Extractor; 34 | int forward_layer(int layer_index, std::vector& blob_mats, const Option& opt) const; 35 | }; 36 | 37 | class Extractor { 38 | public: 39 | ~Extractor(); 40 | 41 | int input(const char* blob_name, const Mat& in); 42 | int input(int blob_index, const Mat& in); 43 | 44 | int extract(const char* blob_name, Mat& feat); 45 | int extract(int blob_index, Mat& feat); 46 | 47 | protected: 48 | friend Extractor Net::create_extractor() const; 49 | Extractor(const Net* net, size_t blob_count); 50 | 51 | private: 52 | const Net* net; 53 | std::vector blob_mats; //存放blob的数值 54 | Option opt; 55 | }; 56 | } 57 | #endif 58 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/option.cpp: -------------------------------------------------------------------------------- 1 | #include "option.h" 2 | 3 | namespace ncnn { 4 | 5 | Option::Option() { 6 | lightmode = true; 7 | blob_allocator = 0; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/option.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_OPTION_H 2 | #define NCNN_OPTION_H 3 | #include "allocator.h" 4 | 5 | namespace ncnn { 6 | 7 | class Option { 8 | public: 9 | Option(); 10 | 11 | public: 12 | bool lightmode; 13 | Allocator* blob_allocator; 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | int ParamDict::get(int id, int def) const { return params[id].type ? params[id].i : def; } 11 | float ParamDict::get(int id, float def) const { return params[id].type ? params[id].f : def; } 12 | Mat ParamDict::get(int id, const Mat& def) const { return params[id].type ? params[id].v : def; } 13 | 14 | static bool vstr_is_float(const char vstr[16]) { 15 | // look ahead for determine isfloat 16 | for (int j = 0; j < 16; j++) { 17 | if (vstr[j] == '\0') break; 18 | 19 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | void ParamDict::clear() { 26 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 27 | params[i].type = 0; 28 | } 29 | } 30 | 31 | static float vstr_to_float(const char vstr[16]) { 32 | double v = 0.0; 33 | 34 | const char* p = vstr; 35 | 36 | // sign 37 | bool sign = *p != '-'; 38 | if (*p == '+' || *p == '-') { 39 | p++; 40 | } 41 | 42 | // digits before decimal point or exponent 43 | unsigned int v1 = 0; 44 | while (isdigit(*p)) { 45 | v1 = v1 * 10 + (*p - '0'); 46 | p++; 47 | } 48 | 49 | v = (double)v1; 50 | 51 | // digits after decimal point 52 | if (*p == '.') { 53 | p++; 54 | 55 | unsigned int pow10 = 1; 56 | unsigned int v2 = 0; 57 | 58 | while (isdigit(*p)) { 59 | v2 = v2 * 10 + (*p - '0'); 60 | pow10 *= 10; 61 | p++; 62 | } 63 | 64 | v += v2 / (double)pow10; 65 | } 66 | 67 | // exponent 68 | if (*p == 'e' || *p == 'E') { 69 | p++; 70 | 71 | // sign of exponent 72 | bool fact = *p != '-'; 73 | if (*p == '+' || *p == '-') { 74 | p++; 75 | } 76 | 77 | // digits of exponent 78 | unsigned int expon = 0; 79 | while (isdigit(*p)) { 80 | expon = expon * 10 + (*p - '0'); 81 | p++; 82 | } 83 | 84 | double scale = 1.0; 85 | while (expon >= 8) { 86 | scale *= 1e8; 87 | expon -= 8; 88 | } 89 | while (expon > 0) { 90 | scale *= 10.0; 91 | expon -= 1; 92 | } 93 | 94 | v = fact ? v * scale : v / scale; 95 | } 96 | 97 | // fprintf(stderr, "v = %f\n", v); 98 | return sign ? (float)v : (float)-v; 99 | } 100 | 101 | int ParamDict::load_param(const DataReader& dr) { 102 | clear(); 103 | int id = 0; 104 | while (dr.scan("%d=", &id) == 1) { 105 | bool is_array = id <= -23300; 106 | if (is_array) { 107 | id = -id - 23300; 108 | } 109 | if (is_array) { 110 | int a = 0; 111 | } else { 112 | char vstr[16]; 113 | int nscan = dr.scan("%15s", vstr); 114 | 115 | bool is_float = vstr_is_float(vstr); 116 | if (is_float) 117 | params[id].f = vstr_to_float(vstr); 118 | else 119 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 120 | 121 | params[id].type = is_float ? 3 : 2; 122 | } 123 | } 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lesson/lesson_10/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | #include "mat.h" 5 | 6 | namespace ncnn { 7 | 8 | class DataReader; 9 | class Net; 10 | 11 | class ParamDict { 12 | public: 13 | ParamDict(); 14 | int get(int id, int def) const; 15 | float get(int id, float def) const; 16 | Mat get(int id, const Mat& def) const; 17 | 18 | protected: 19 | friend class Net; 20 | int load_param(const DataReader& dr); 21 | void clear(); 22 | 23 | protected: 24 | struct { 25 | int type; 26 | union { 27 | int i; 28 | float f; 29 | }; 30 | Mat v; 31 | } params[NCNN_MAX_PARAM_COUNT]; 32 | }; 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /lesson/lesson_2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession2) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_2/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_2) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_2/examples/lession_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "blob.h" 6 | #include "datareader.h" 7 | #include "layer.h" 8 | #include "net.h" 9 | using namespace std; 10 | 11 | int main(int argc, char** argv) { 12 | ncnn::Net net; 13 | ncnn::Layer layer; 14 | ncnn::Blob blob; 15 | printf("yes\n"); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | ) 9 | 10 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 11 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 12 | 13 | 14 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | cout << "Blob has been constructed" << endl; 8 | producer = -1; } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | namespace ncnn { 7 | 8 | Layer::Layer() { cout << "Layer has been constructed" << endl; } 9 | 10 | Layer::~Layer() {} 11 | } 12 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class Layer { 9 | public: 10 | Layer(); 11 | virtual ~Layer(); 12 | 13 | public: 14 | std::string type; 15 | std::string name; 16 | std::vector bottoms; 17 | std::vector tops; 18 | 19 | }; 20 | 21 | 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/net.cpp: -------------------------------------------------------------------------------- 1 | #include "net.h" 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | namespace ncnn { 7 | 8 | Net::Net() { cout << "Net has been constructed" << endl; } 9 | 10 | Net::~Net() {} 11 | } 12 | -------------------------------------------------------------------------------- /lesson/lesson_2/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "layer.h" 8 | 9 | namespace ncnn{ 10 | 11 | class Net { 12 | public: 13 | Net(); 14 | ~Net(); 15 | 16 | public: 17 | std::vector layers; 18 | std::vector blobs; //存放blob的信息,如layer或者shape等等 19 | 20 | 21 | }; 22 | 23 | 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /lesson/lesson_3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession3) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_3/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_3) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_3/examples/lession_3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "blob.h" 6 | #include "datareader.h" 7 | #include "layer.h" 8 | #include "net.h" 9 | using namespace std; 10 | 11 | int main(int argc, char** argv) { 12 | ncnn::Net squeezenet; 13 | 14 | squeezenet.load_param("../examples/squeezenet_v1.1.param"); 15 | 16 | printf("yes\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | ) 10 | 11 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 12 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 13 | 14 | 15 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | namespace ncnn { 7 | 8 | Layer::Layer() { } 9 | 10 | Layer::~Layer() {} 11 | } 12 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class Layer { 9 | public: 10 | Layer(); 11 | virtual ~Layer(); 12 | 13 | public: 14 | std::string type; 15 | std::string name; 16 | std::vector bottoms; 17 | std::vector tops; 18 | 19 | }; 20 | 21 | 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/net.cpp: -------------------------------------------------------------------------------- 1 | #include "net.h" 2 | #include 3 | #include 4 | #include "paramdict.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Net::Net() { } 10 | 11 | Net::~Net() {} 12 | 13 | int Net::load_param(const DataReader& dr) { 14 | #define SCAN_VALUE(fmt, v) dr.scan(fmt, &v); 15 | 16 | int magic = 0; 17 | SCAN_VALUE("%d", magic) 18 | 19 | int layer_count = 0; 20 | int blob_count = 0; 21 | 22 | SCAN_VALUE("%d", layer_count) 23 | SCAN_VALUE("%d", blob_count) 24 | 25 | layers.resize((size_t)layer_count); 26 | blobs.resize((size_t)blob_count); 27 | 28 | ParamDict pd; 29 | int blob_index = 0; 30 | for (int i = 0; i < layer_count; i++) { 31 | char layer_type[256]; 32 | char layer_name[256]; 33 | int bottom_count = 0; 34 | int top_count = 0; 35 | 36 | SCAN_VALUE("%255s", layer_type) 37 | SCAN_VALUE("%255s", layer_name) 38 | SCAN_VALUE("%d", bottom_count) 39 | SCAN_VALUE("%d", top_count) 40 | 41 | Layer* layer = new Layer(); 42 | 43 | layer->type = string(layer_type); 44 | layer->name = string(layer_name); 45 | layer->bottoms.resize(bottom_count); 46 | layer->tops.resize(top_count); 47 | 48 | cout << layer->type << " bottoms:"; 49 | for (int j = 0; j < bottom_count; j++) { 50 | char bottom_name[256]; 51 | SCAN_VALUE("%255s", bottom_name) 52 | int bottom_blob_index = 53 | find_blob_index_by_name(bottom_name); //找到blob的唯一id(在top中被指定的) 54 | Blob& blob = blobs[bottom_blob_index]; 55 | blob.consumers.push_back(i); //使用(消费)blob的时候的层的id 56 | layer->bottoms[j] = bottom_blob_index; // layer获取bottom_blob的blob_id 57 | cout << layer->bottoms[j] << " "; 58 | } 59 | 60 | cout << "tops:"; 61 | for (int j = 0; j < top_count; j++) { 62 | Blob& blob = 63 | blobs[blob_index]; // blob在top时候时候才是被产生的时候,获取这时候的blob_id 64 | char blob_name[256]; 65 | SCAN_VALUE("%255s", blob_name) 66 | blob.name = string(blob_name); 67 | blob.producer = i; //产生blob时候的层的id 68 | layer->tops[j] = blob_index; // Layer 获取top_blob的blob_id 69 | blob_index++; 70 | cout << layer->tops[j] << " "; 71 | } 72 | 73 | cout << endl; 74 | 75 | //利用pd,load每一层的配置参数(非weight) 76 | int pdlr = pd.load_param(dr); 77 | 78 | layers[i] = layer; 79 | } 80 | 81 | #undef SCAN_VALUE 82 | 83 | return 0; 84 | } 85 | 86 | int Net::load_param(const char* protopath) { 87 | FILE* fp = fopen(protopath, "rb"); 88 | DataReaderFromStdio dr(fp); 89 | int ret = load_param(dr); 90 | fclose(fp); 91 | return ret; 92 | } 93 | 94 | int Net::find_blob_index_by_name(const char* name) const { 95 | for (size_t i = 0; i < blobs.size(); i++) { 96 | const Blob& blob = blobs[i]; 97 | if (blob.name == name) { 98 | return static_cast(i); 99 | } 100 | } 101 | 102 | return -1; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Net { 13 | public: 14 | Net(); 15 | ~Net(); 16 | 17 | int load_param(const DataReader& dr); 18 | int load_param(const char* protopath); 19 | int find_blob_index_by_name(const char* name) const; 20 | 21 | public: 22 | std::vector layers; 23 | std::vector blobs; //存放blob的信息,如layer或者shape等等 24 | 25 | 26 | }; 27 | 28 | 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | 11 | 12 | static bool vstr_is_float(const char vstr[16]) { 13 | // look ahead for determine isfloat 14 | for (int j = 0; j < 16; j++) { 15 | if (vstr[j] == '\0') break; 16 | 17 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 18 | } 19 | 20 | return false; 21 | } 22 | 23 | void ParamDict::clear() { 24 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 25 | params[i].type = 0; 26 | } 27 | } 28 | 29 | static float vstr_to_float(const char vstr[16]) { 30 | double v = 0.0; 31 | 32 | const char* p = vstr; 33 | 34 | // sign 35 | bool sign = *p != '-'; 36 | if (*p == '+' || *p == '-') { 37 | p++; 38 | } 39 | 40 | // digits before decimal point or exponent 41 | unsigned int v1 = 0; 42 | while (isdigit(*p)) { 43 | v1 = v1 * 10 + (*p - '0'); 44 | p++; 45 | } 46 | 47 | v = (double)v1; 48 | 49 | // digits after decimal point 50 | if (*p == '.') { 51 | p++; 52 | 53 | unsigned int pow10 = 1; 54 | unsigned int v2 = 0; 55 | 56 | while (isdigit(*p)) { 57 | v2 = v2 * 10 + (*p - '0'); 58 | pow10 *= 10; 59 | p++; 60 | } 61 | 62 | v += v2 / (double)pow10; 63 | } 64 | 65 | // exponent 66 | if (*p == 'e' || *p == 'E') { 67 | p++; 68 | 69 | // sign of exponent 70 | bool fact = *p != '-'; 71 | if (*p == '+' || *p == '-') { 72 | p++; 73 | } 74 | 75 | // digits of exponent 76 | unsigned int expon = 0; 77 | while (isdigit(*p)) { 78 | expon = expon * 10 + (*p - '0'); 79 | p++; 80 | } 81 | 82 | double scale = 1.0; 83 | while (expon >= 8) { 84 | scale *= 1e8; 85 | expon -= 8; 86 | } 87 | while (expon > 0) { 88 | scale *= 10.0; 89 | expon -= 1; 90 | } 91 | 92 | v = fact ? v * scale : v / scale; 93 | } 94 | 95 | // fprintf(stderr, "v = %f\n", v); 96 | return sign ? (float)v : (float)-v; 97 | } 98 | 99 | int ParamDict::load_param(const DataReader& dr) { 100 | clear(); 101 | int id = 0; 102 | while (dr.scan("%d=", &id) == 1) { 103 | bool is_array = id <= -23300; 104 | if (is_array) { 105 | id = -id - 23300; 106 | } 107 | if (is_array) { 108 | int a = 0; 109 | } else { 110 | char vstr[16]; 111 | int nscan = dr.scan("%15s", vstr); 112 | 113 | bool is_float = vstr_is_float(vstr); 114 | if (is_float) 115 | params[id].f = vstr_to_float(vstr); 116 | else 117 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 118 | 119 | params[id].type = is_float ? 3 : 2; 120 | } 121 | } 122 | return 0; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /lesson/lesson_3/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | 5 | namespace ncnn { 6 | 7 | class DataReader; 8 | 9 | class ParamDict { 10 | public: 11 | ParamDict(); 12 | 13 | protected: 14 | friend class Net; 15 | int load_param(const DataReader& dr); 16 | void clear(); 17 | 18 | protected: 19 | struct { 20 | int type; 21 | union { 22 | int i; 23 | float f; 24 | }; 25 | } params[NCNN_MAX_PARAM_COUNT]; 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /lesson/lesson_4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession4) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_4/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_4) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_4/examples/lession_4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "blob.h" 6 | #include "datareader.h" 7 | #include "layer.h" 8 | #include "net.h" 9 | using namespace std; 10 | 11 | int main(int argc, char** argv) { 12 | ncnn::Net squeezenet; 13 | 14 | squeezenet.load_param("../examples/squeezenet_v1.1.param"); 15 | 16 | printf("yes\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | ) 10 | 11 | 12 | file(GLOB SRC_LAYER ${CMAKE_CURRENT_SOURCE_DIR}/layer/*.c*) 13 | list(APPEND ncnn_SRCS ${SRC_LAYER}) 14 | 15 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 16 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 17 | 18 | 19 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | namespace ncnn { 7 | 8 | Layer::Layer() { } 9 | Layer::~Layer() {} 10 | 11 | int Layer::load_param(const ParamDict&) { return 0; } 12 | } 13 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | #include "paramdict.h" 6 | 7 | namespace ncnn { 8 | 9 | class Layer { 10 | public: 11 | Layer(); 12 | virtual ~Layer(); 13 | virtual int load_param(const ParamDict& pd); 14 | 15 | public: 16 | std::string type; 17 | std::string name; 18 | std::vector bottoms; 19 | std::vector tops; 20 | 21 | }; 22 | 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/concat.cpp: -------------------------------------------------------------------------------- 1 | #include "concat.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Concat::Concat() { 8 | } 9 | 10 | int Concat::load_param(const ParamDict& pd) { 11 | axis = pd.get(0, 0); 12 | return 0; 13 | } 14 | 15 | 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/concat.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONCAT_H 2 | #define LAYER_CONCAT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Concat : public Layer { 9 | public: 10 | Concat(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/convolution.cpp: -------------------------------------------------------------------------------- 1 | #include "convolution.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Convolution::Convolution() { 8 | } 9 | 10 | int Convolution::load_param(const ParamDict& pd) { 11 | num_output = pd.get(0, 0); 12 | kernel_w = pd.get(1, 0); 13 | kernel_h = pd.get(11, kernel_w); 14 | dilation_w = pd.get(2, 1); 15 | dilation_h = pd.get(12, dilation_w); 16 | stride_w = pd.get(3, 1); 17 | stride_h = pd.get(13, stride_w); 18 | pad_left = pd.get(4, 0); 19 | pad_right = pd.get(15, pad_left); 20 | pad_top = pd.get(14, pad_left); 21 | pad_bottom = pd.get(16, pad_top); 22 | pad_value = pd.get(18, 0.f); 23 | bias_term = pd.get(5, 0); 24 | weight_data_size = pd.get(6, 0); 25 | int8_scale_term = pd.get(8, 0); 26 | impl_type = pd.get(17, 0); 27 | 28 | return 0; 29 | } 30 | 31 | 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/convolution.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONVOLUTION_H 2 | #define LAYER_CONVOLUTION_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Convolution : public Layer { 9 | public: 10 | Convolution(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int num_output; 15 | int kernel_w; 16 | int kernel_h; 17 | int dilation_w; 18 | int dilation_h; 19 | int stride_w; 20 | int stride_h; 21 | int pad_left; 22 | int pad_right; 23 | int pad_top; 24 | int pad_bottom; 25 | float pad_value; 26 | int bias_term; 27 | int weight_data_size; 28 | int int8_scale_term; 29 | int activation_type; 30 | float bottom_blob_int8_scale; 31 | float top_blob_int8_scale; 32 | bool use_int8_requantize; 33 | int impl_type; 34 | 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/dropout.cpp: -------------------------------------------------------------------------------- 1 | #include "dropout.h" 2 | 3 | namespace ncnn { 4 | 5 | Dropout::Dropout() { 6 | } 7 | 8 | int Dropout::load_param(const ParamDict& pd) { 9 | scale = pd.get(0, 1.f); 10 | return 0; 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/dropout.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_DROPOUT_h 2 | #define LAYER_DROPOUT_h 3 | #include "layer.h" 4 | 5 | namespace ncnn { 6 | 7 | class Dropout : public Layer { 8 | public: 9 | Dropout(); 10 | virtual int load_param(const ParamDict& pd); 11 | 12 | public: 13 | float scale; 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Input::Input() { 8 | } 9 | 10 | int Input::load_param(const ParamDict& pd) { 11 | w = pd.get(0, 0); 12 | h = pd.get(1, 0); 13 | c = pd.get(2, 0); 14 | return 0; 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/input.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_INPUT_H 2 | #define LAYER_INPUT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Input : public Layer { 9 | public: 10 | Input(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int w; 15 | int h; 16 | int c; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/pooling.cpp: -------------------------------------------------------------------------------- 1 | #include "pooling.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Pooling::Pooling() { 8 | } 9 | 10 | int Pooling::load_param(const ParamDict& pd) { 11 | pooling_type = pd.get(0, 0); 12 | kernel_w = pd.get(1, 0); 13 | kernel_h = pd.get(11, kernel_w); 14 | stride_w = pd.get(2, 1); 15 | stride_h = pd.get(12, stride_w); 16 | pad_left = pd.get(3, 0); 17 | pad_right = pd.get(14, pad_left); 18 | pad_top = pd.get(13, pad_left); 19 | pad_bottom = pd.get(15, pad_top); 20 | global_pooling = pd.get(5, 0); 21 | avgpool_count_include_pad = pd.get(6, 0); 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/pooling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_POOLING_H 2 | #define LAYER_POOLING_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Pooling : public Layer { 9 | public: 10 | Pooling(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int pooling_type; 15 | int kernel_w; 16 | int kernel_h; 17 | int stride_w; 18 | int stride_h; 19 | int pad_left; 20 | int pad_right; 21 | int pad_top; 22 | int pad_bottom; 23 | int global_pooling; 24 | int pad_mode; 25 | int avgpool_count_include_pad; 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/relu.cpp: -------------------------------------------------------------------------------- 1 | #include "relu.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | ReLU::ReLU() { 8 | } 9 | 10 | int ReLU::load_param(const ParamDict& pd) { 11 | slope = pd.get(0, 0.f); 12 | return 0; 13 | } 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/relu.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_RELU_H 2 | #define LAYER_RELU_H 3 | #include 4 | #include "layer.h" 5 | using namespace std; 6 | namespace ncnn { 7 | 8 | class ReLU : public Layer { 9 | public: 10 | ReLU(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | float slope; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/softmax.cpp: -------------------------------------------------------------------------------- 1 | #include "softmax.h" 2 | 3 | namespace ncnn { 4 | 5 | Softmax::Softmax() { 6 | } 7 | 8 | 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SOFTMAX_H 2 | #define LAYER_SOFTMAX_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Softmax : public Layer { 9 | public: 10 | Softmax(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/split.cpp: -------------------------------------------------------------------------------- 1 | #include "split.h" 2 | 3 | namespace ncnn { 4 | 5 | Split::Split() { 6 | } 7 | 8 | 9 | } 10 | 11 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/layer/split.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SPLIT_H 2 | #define LAYER_SPLIT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Split : public Layer { 9 | public: 10 | Split(); 11 | }; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/net.cpp: -------------------------------------------------------------------------------- 1 | #include "net.h" 2 | #include 3 | #include 4 | #include "paramdict.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Net::Net() { } 10 | 11 | Net::~Net() {} 12 | 13 | int Net::load_param(const DataReader& dr) { 14 | #define SCAN_VALUE(fmt, v) dr.scan(fmt, &v); 15 | 16 | int magic = 0; 17 | SCAN_VALUE("%d", magic) 18 | 19 | int layer_count = 0; 20 | int blob_count = 0; 21 | 22 | SCAN_VALUE("%d", layer_count) 23 | SCAN_VALUE("%d", blob_count) 24 | 25 | layers.resize((size_t)layer_count); 26 | blobs.resize((size_t)blob_count); 27 | 28 | ParamDict pd; 29 | int blob_index = 0; 30 | for (int i = 0; i < layer_count; i++) { 31 | char layer_type[256]; 32 | char layer_name[256]; 33 | int bottom_count = 0; 34 | int top_count = 0; 35 | 36 | SCAN_VALUE("%255s", layer_type) 37 | SCAN_VALUE("%255s", layer_name) 38 | SCAN_VALUE("%d", bottom_count) 39 | SCAN_VALUE("%d", top_count) 40 | 41 | Layer* layer = new Layer(); 42 | 43 | layer->type = string(layer_type); 44 | layer->name = string(layer_name); 45 | layer->bottoms.resize(bottom_count); 46 | layer->tops.resize(top_count); 47 | 48 | cout << layer->type << " bottoms:"; 49 | for (int j = 0; j < bottom_count; j++) { 50 | char bottom_name[256]; 51 | SCAN_VALUE("%255s", bottom_name) 52 | int bottom_blob_index = 53 | find_blob_index_by_name(bottom_name); //找到blob的唯一id(在top中被指定的) 54 | Blob& blob = blobs[bottom_blob_index]; 55 | blob.consumers.push_back(i); //使用(消费)blob的时候的层的id 56 | layer->bottoms[j] = bottom_blob_index; // layer获取bottom_blob的blob_id 57 | cout << layer->bottoms[j] << " "; 58 | } 59 | 60 | cout << "tops:"; 61 | for (int j = 0; j < top_count; j++) { 62 | Blob& blob = 63 | blobs[blob_index]; // blob在top时候时候才是被产生的时候,获取这时候的blob_id 64 | char blob_name[256]; 65 | SCAN_VALUE("%255s", blob_name) 66 | blob.name = string(blob_name); 67 | blob.producer = i; //产生blob时候的层的id 68 | layer->tops[j] = blob_index; // Layer 获取top_blob的blob_id 69 | blob_index++; 70 | cout << layer->tops[j] << " "; 71 | } 72 | 73 | cout << endl; 74 | 75 | //利用pd,load每一层的配置参数(非weight) 76 | int pdlr = pd.load_param(dr); 77 | 78 | layers[i] = layer; 79 | } 80 | 81 | #undef SCAN_VALUE 82 | 83 | return 0; 84 | } 85 | 86 | int Net::load_param(const char* protopath) { 87 | FILE* fp = fopen(protopath, "rb"); 88 | DataReaderFromStdio dr(fp); 89 | int ret = load_param(dr); 90 | fclose(fp); 91 | return ret; 92 | } 93 | 94 | int Net::find_blob_index_by_name(const char* name) const { 95 | for (size_t i = 0; i < blobs.size(); i++) { 96 | const Blob& blob = blobs[i]; 97 | if (blob.name == name) { 98 | return static_cast(i); 99 | } 100 | } 101 | 102 | return -1; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Net { 13 | public: 14 | Net(); 15 | ~Net(); 16 | 17 | int load_param(const DataReader& dr); 18 | int load_param(const char* protopath); 19 | int find_blob_index_by_name(const char* name) const; 20 | 21 | public: 22 | std::vector layers; 23 | std::vector blobs; //存放blob的信息,如layer或者shape等等 24 | 25 | 26 | }; 27 | 28 | 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | int ParamDict::get(int id, int def) const { return params[id].type ? params[id].i : def; } 11 | float ParamDict::get(int id, float def) const { return params[id].type ? params[id].f : def; } 12 | 13 | 14 | static bool vstr_is_float(const char vstr[16]) { 15 | // look ahead for determine isfloat 16 | for (int j = 0; j < 16; j++) { 17 | if (vstr[j] == '\0') break; 18 | 19 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | void ParamDict::clear() { 26 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 27 | params[i].type = 0; 28 | } 29 | } 30 | 31 | static float vstr_to_float(const char vstr[16]) { 32 | double v = 0.0; 33 | 34 | const char* p = vstr; 35 | 36 | // sign 37 | bool sign = *p != '-'; 38 | if (*p == '+' || *p == '-') { 39 | p++; 40 | } 41 | 42 | // digits before decimal point or exponent 43 | unsigned int v1 = 0; 44 | while (isdigit(*p)) { 45 | v1 = v1 * 10 + (*p - '0'); 46 | p++; 47 | } 48 | 49 | v = (double)v1; 50 | 51 | // digits after decimal point 52 | if (*p == '.') { 53 | p++; 54 | 55 | unsigned int pow10 = 1; 56 | unsigned int v2 = 0; 57 | 58 | while (isdigit(*p)) { 59 | v2 = v2 * 10 + (*p - '0'); 60 | pow10 *= 10; 61 | p++; 62 | } 63 | 64 | v += v2 / (double)pow10; 65 | } 66 | 67 | // exponent 68 | if (*p == 'e' || *p == 'E') { 69 | p++; 70 | 71 | // sign of exponent 72 | bool fact = *p != '-'; 73 | if (*p == '+' || *p == '-') { 74 | p++; 75 | } 76 | 77 | // digits of exponent 78 | unsigned int expon = 0; 79 | while (isdigit(*p)) { 80 | expon = expon * 10 + (*p - '0'); 81 | p++; 82 | } 83 | 84 | double scale = 1.0; 85 | while (expon >= 8) { 86 | scale *= 1e8; 87 | expon -= 8; 88 | } 89 | while (expon > 0) { 90 | scale *= 10.0; 91 | expon -= 1; 92 | } 93 | 94 | v = fact ? v * scale : v / scale; 95 | } 96 | 97 | // fprintf(stderr, "v = %f\n", v); 98 | return sign ? (float)v : (float)-v; 99 | } 100 | 101 | int ParamDict::load_param(const DataReader& dr) { 102 | clear(); 103 | int id = 0; 104 | while (dr.scan("%d=", &id) == 1) { 105 | bool is_array = id <= -23300; 106 | if (is_array) { 107 | id = -id - 23300; 108 | } 109 | if (is_array) { 110 | int a = 0; 111 | } else { 112 | char vstr[16]; 113 | int nscan = dr.scan("%15s", vstr); 114 | 115 | bool is_float = vstr_is_float(vstr); 116 | if (is_float) 117 | params[id].f = vstr_to_float(vstr); 118 | else 119 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 120 | 121 | params[id].type = is_float ? 3 : 2; 122 | } 123 | } 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lesson/lesson_4/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | 5 | namespace ncnn { 6 | 7 | class DataReader; 8 | class Net; 9 | 10 | class ParamDict { 11 | public: 12 | ParamDict(); 13 | int get(int id, int def) const; 14 | float get(int id, float def) const; 15 | 16 | protected: 17 | friend class Net; 18 | int load_param(const DataReader& dr); 19 | void clear(); 20 | 21 | protected: 22 | struct { 23 | int type; 24 | union { 25 | int i; 26 | float f; 27 | }; 28 | } params[NCNN_MAX_PARAM_COUNT]; 29 | }; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lesson/lesson_5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession5) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_5/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_5) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_5/examples/lession_5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "blob.h" 6 | #include "datareader.h" 7 | #include "layer.h" 8 | #include "net.h" 9 | using namespace std; 10 | 11 | int main(int argc, char** argv) { 12 | ncnn::Net squeezenet; 13 | 14 | squeezenet.load_param("../examples/squeezenet_v1.1.param"); 15 | 16 | printf("yes\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | ) 10 | 11 | 12 | file(GLOB SRC_LAYER ${CMAKE_CURRENT_SOURCE_DIR}/layer/*.c*) 13 | list(APPEND ncnn_SRCS ${SRC_LAYER}) 14 | 15 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 16 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 17 | 18 | 19 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | #include "layer_declaration.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Layer::Layer() { } 10 | Layer::~Layer() {} 11 | 12 | int Layer::load_param(const ParamDict&) { return 0; } 13 | 14 | static const layer_registry_entry layer_registry[] = { 15 | {"ReLU", ReLU_final_layer_creator}, 16 | {"Input", Input_final_layer_creator}, 17 | {"Pooling", Pooling_final_layer_creator}, 18 | {"Convolution", Convolution_final_layer_creator}, 19 | {"Split", Split_final_layer_creator}, 20 | {"Concat", Concat_final_layer_creator}, 21 | {"Dropout", Dropout_final_layer_creator}, 22 | {"Softmax", Softmax_final_layer_creator}, 23 | 24 | }; 25 | 26 | //确定一共有多少个layer 27 | static const int layer_registry_entry_count = 28 | sizeof(layer_registry) / sizeof(layer_registry_entry); 29 | 30 | int layer_to_index(const char* type) { 31 | for (int i = 0; i < layer_registry_entry_count; i++) { 32 | if (strcmp(type, layer_registry[i].name) == 0) return i; 33 | } 34 | return -1; 35 | } 36 | 37 | Layer* create_layer(const char* type) { 38 | int index = layer_to_index(type); 39 | if (index == -1) return 0; 40 | return create_layer(index); 41 | } 42 | 43 | //基于id在数组里面找constructor 44 | Layer* create_layer(int index) { 45 | if (index < 0 || index >= layer_registry_entry_count) return 0; 46 | 47 | layer_creator_func layer_creator = 0; 48 | { layer_creator = layer_registry[index].creator; } 49 | 50 | if (!layer_creator) return 0; 51 | 52 | Layer* layer = layer_creator(); 53 | layer->typeindex = index; 54 | return layer; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | #include "paramdict.h" 6 | 7 | namespace ncnn { 8 | 9 | class Layer { 10 | public: 11 | Layer(); 12 | virtual ~Layer(); 13 | virtual int load_param(const ParamDict& pd); 14 | 15 | public: 16 | int typeindex; 17 | std::string type; 18 | std::string name; 19 | std::vector bottoms; 20 | std::vector tops; 21 | 22 | }; 23 | 24 | typedef Layer* (*layer_creator_func)(); 25 | 26 | struct layer_registry_entry { 27 | const char* name; 28 | layer_creator_func creator; 29 | }; 30 | 31 | int layer_to_index(const char* type); 32 | Layer* create_layer(const char* type); 33 | Layer* create_layer(int index); 34 | 35 | #define DEFINE_LAYER_CREATOR(name) \ 36 | ncnn::Layer* name##_final_layer_creator() { return new name; } 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/concat.cpp: -------------------------------------------------------------------------------- 1 | #include "concat.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Concat::Concat() { cout << "concat constructed" << endl; } 8 | 9 | int Concat::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 0); 11 | return 0; 12 | } 13 | 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/concat.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONCAT_H 2 | #define LAYER_CONCAT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Concat : public Layer { 9 | public: 10 | Concat(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/convolution.cpp: -------------------------------------------------------------------------------- 1 | #include "convolution.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Convolution::Convolution() { cout << "convolution constructed" << endl; } 8 | 9 | int Convolution::load_param(const ParamDict& pd) { 10 | num_output = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | dilation_w = pd.get(2, 1); 14 | dilation_h = pd.get(12, dilation_w); 15 | stride_w = pd.get(3, 1); 16 | stride_h = pd.get(13, stride_w); 17 | pad_left = pd.get(4, 0); 18 | pad_right = pd.get(15, pad_left); 19 | pad_top = pd.get(14, pad_left); 20 | pad_bottom = pd.get(16, pad_top); 21 | pad_value = pd.get(18, 0.f); 22 | bias_term = pd.get(5, 0); 23 | weight_data_size = pd.get(6, 0); 24 | int8_scale_term = pd.get(8, 0); 25 | impl_type = pd.get(17, 0); 26 | 27 | return 0; 28 | } 29 | 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/convolution.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONVOLUTION_H 2 | #define LAYER_CONVOLUTION_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Convolution : public Layer { 9 | public: 10 | Convolution(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int num_output; 15 | int kernel_w; 16 | int kernel_h; 17 | int dilation_w; 18 | int dilation_h; 19 | int stride_w; 20 | int stride_h; 21 | int pad_left; 22 | int pad_right; 23 | int pad_top; 24 | int pad_bottom; 25 | float pad_value; 26 | int bias_term; 27 | int weight_data_size; 28 | int int8_scale_term; 29 | int activation_type; 30 | float bottom_blob_int8_scale; 31 | float top_blob_int8_scale; 32 | bool use_int8_requantize; 33 | int impl_type; 34 | 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/dropout.cpp: -------------------------------------------------------------------------------- 1 | #include "dropout.h" 2 | #include "iostream" 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Dropout::Dropout() { cout << "dropout constructed" << endl; } 7 | 8 | int Dropout::load_param(const ParamDict& pd) { 9 | scale = pd.get(0, 1.f); 10 | return 0; 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/dropout.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_DROPOUT_h 2 | #define LAYER_DROPOUT_h 3 | #include "layer.h" 4 | 5 | namespace ncnn { 6 | 7 | class Dropout : public Layer { 8 | public: 9 | Dropout(); 10 | virtual int load_param(const ParamDict& pd); 11 | 12 | public: 13 | float scale; 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Input::Input() { cout << "input constructed" << endl; } 8 | 9 | int Input::load_param(const ParamDict& pd) { 10 | w = pd.get(0, 0); 11 | h = pd.get(1, 0); 12 | c = pd.get(2, 0); 13 | return 0; 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/input.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_INPUT_H 2 | #define LAYER_INPUT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Input : public Layer { 9 | public: 10 | Input(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int w; 15 | int h; 16 | int c; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/pooling.cpp: -------------------------------------------------------------------------------- 1 | #include "pooling.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Pooling::Pooling() { cout << "pooling constructed" << endl; } 8 | 9 | int Pooling::load_param(const ParamDict& pd) { 10 | pooling_type = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | stride_w = pd.get(2, 1); 14 | stride_h = pd.get(12, stride_w); 15 | pad_left = pd.get(3, 0); 16 | pad_right = pd.get(14, pad_left); 17 | pad_top = pd.get(13, pad_left); 18 | pad_bottom = pd.get(15, pad_top); 19 | global_pooling = pd.get(5, 0); 20 | avgpool_count_include_pad = pd.get(6, 0); 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/pooling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_POOLING_H 2 | #define LAYER_POOLING_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Pooling : public Layer { 9 | public: 10 | Pooling(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int pooling_type; 15 | int kernel_w; 16 | int kernel_h; 17 | int stride_w; 18 | int stride_h; 19 | int pad_left; 20 | int pad_right; 21 | int pad_top; 22 | int pad_bottom; 23 | int global_pooling; 24 | int pad_mode; 25 | int avgpool_count_include_pad; 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/relu.cpp: -------------------------------------------------------------------------------- 1 | #include "relu.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | ReLU::ReLU() { cout << "relu constructed" << endl; } 8 | 9 | int ReLU::load_param(const ParamDict& pd) { 10 | slope = pd.get(0, 0.f); 11 | return 0; 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/relu.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_RELU_H 2 | #define LAYER_RELU_H 3 | #include 4 | #include "layer.h" 5 | using namespace std; 6 | namespace ncnn { 7 | 8 | class ReLU : public Layer { 9 | public: 10 | ReLU(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | float slope; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/softmax.cpp: -------------------------------------------------------------------------------- 1 | #include "softmax.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Softmax::Softmax() { cout << "softmax constructed" << endl; } 8 | 9 | int Softmax::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 9); 11 | return 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SOFTMAX_H 2 | #define LAYER_SOFTMAX_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Softmax : public Layer { 9 | public: 10 | Softmax(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/split.cpp: -------------------------------------------------------------------------------- 1 | #include "split.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | Split::Split() { cout << "split constructed" << endl; } 7 | } 8 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer/split.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SPLIT_H 2 | #define LAYER_SPLIT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Split : public Layer { 9 | public: 10 | Split(); 11 | }; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/layer_declaration.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_DECLARATION 2 | #define NCNN_LAYER_DECLARATION 3 | #include "layer/relu.h" 4 | namespace ncnn { 5 | DEFINE_LAYER_CREATOR(ReLU) 6 | } 7 | #include "layer/input.h" 8 | namespace ncnn { 9 | DEFINE_LAYER_CREATOR(Input) 10 | } 11 | 12 | #include "layer/pooling.h" 13 | namespace ncnn { 14 | DEFINE_LAYER_CREATOR(Pooling) 15 | } 16 | 17 | #include "layer/convolution.h" 18 | namespace ncnn { 19 | DEFINE_LAYER_CREATOR(Convolution) 20 | } 21 | 22 | #include "layer/split.h" 23 | namespace ncnn { 24 | DEFINE_LAYER_CREATOR(Split) 25 | } 26 | 27 | #include "layer/concat.h" 28 | namespace ncnn { 29 | DEFINE_LAYER_CREATOR(Concat) 30 | } 31 | 32 | #include "layer/dropout.h" 33 | namespace ncnn { 34 | DEFINE_LAYER_CREATOR(Dropout) 35 | } 36 | 37 | #include "layer/softmax.h" 38 | namespace ncnn { 39 | DEFINE_LAYER_CREATOR(Softmax) 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/net.cpp: -------------------------------------------------------------------------------- 1 | #include "net.h" 2 | #include 3 | #include 4 | #include "paramdict.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Net::Net() { } 10 | 11 | Net::~Net() {} 12 | 13 | int Net::load_param(const DataReader& dr) { 14 | #define SCAN_VALUE(fmt, v) dr.scan(fmt, &v); 15 | 16 | int magic = 0; 17 | SCAN_VALUE("%d", magic) 18 | 19 | int layer_count = 0; 20 | int blob_count = 0; 21 | 22 | SCAN_VALUE("%d", layer_count) 23 | SCAN_VALUE("%d", blob_count) 24 | 25 | layers.resize((size_t)layer_count); 26 | blobs.resize((size_t)blob_count); 27 | 28 | ParamDict pd; 29 | int blob_index = 0; 30 | for (int i = 0; i < layer_count; i++) { 31 | char layer_type[256]; 32 | char layer_name[256]; 33 | int bottom_count = 0; 34 | int top_count = 0; 35 | 36 | SCAN_VALUE("%255s", layer_type) 37 | SCAN_VALUE("%255s", layer_name) 38 | SCAN_VALUE("%d", bottom_count) 39 | SCAN_VALUE("%d", top_count) 40 | 41 | Layer* layer = create_layer(layer_type); 42 | // Layer* layer = new Layer(); 43 | 44 | layer->type = string(layer_type); 45 | layer->name = string(layer_name); 46 | layer->bottoms.resize(bottom_count); 47 | layer->tops.resize(top_count); 48 | 49 | for (int j = 0; j < bottom_count; j++) { 50 | char bottom_name[256]; 51 | SCAN_VALUE("%255s", bottom_name) 52 | int bottom_blob_index = 53 | find_blob_index_by_name(bottom_name); //找到blob的唯一id(在top中被指定的) 54 | Blob& blob = blobs[bottom_blob_index]; 55 | blob.consumers.push_back(i); //使用(消费)blob的时候的层的id 56 | layer->bottoms[j] = bottom_blob_index; // layer获取bottom_blob的blob_id 57 | } 58 | 59 | for (int j = 0; j < top_count; j++) { 60 | Blob& blob = 61 | blobs[blob_index]; // blob在top时候时候才是被产生的时候,获取这时候的blob_id 62 | char blob_name[256]; 63 | SCAN_VALUE("%255s", blob_name) 64 | blob.name = string(blob_name); 65 | blob.producer = i; //产生blob时候的层的id 66 | layer->tops[j] = blob_index; // Layer 获取top_blob的blob_id 67 | blob_index++; 68 | } 69 | 70 | 71 | //利用pd,load每一层的配置参数(非weight) 72 | int pdlr = pd.load_param(dr); 73 | 74 | layers[i] = layer; 75 | } 76 | 77 | #undef SCAN_VALUE 78 | 79 | return 0; 80 | } 81 | 82 | int Net::load_param(const char* protopath) { 83 | FILE* fp = fopen(protopath, "rb"); 84 | DataReaderFromStdio dr(fp); 85 | int ret = load_param(dr); 86 | fclose(fp); 87 | return ret; 88 | } 89 | 90 | int Net::find_blob_index_by_name(const char* name) const { 91 | for (size_t i = 0; i < blobs.size(); i++) { 92 | const Blob& blob = blobs[i]; 93 | if (blob.name == name) { 94 | return static_cast(i); 95 | } 96 | } 97 | 98 | return -1; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Net { 13 | public: 14 | Net(); 15 | ~Net(); 16 | 17 | int load_param(const DataReader& dr); 18 | int load_param(const char* protopath); 19 | int find_blob_index_by_name(const char* name) const; 20 | 21 | public: 22 | std::vector layers; 23 | std::vector blobs; //存放blob的信息,如layer或者shape等等 24 | 25 | 26 | }; 27 | 28 | 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | int ParamDict::get(int id, int def) const { return params[id].type ? params[id].i : def; } 11 | float ParamDict::get(int id, float def) const { return params[id].type ? params[id].f : def; } 12 | 13 | 14 | static bool vstr_is_float(const char vstr[16]) { 15 | // look ahead for determine isfloat 16 | for (int j = 0; j < 16; j++) { 17 | if (vstr[j] == '\0') break; 18 | 19 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | void ParamDict::clear() { 26 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 27 | params[i].type = 0; 28 | } 29 | } 30 | 31 | static float vstr_to_float(const char vstr[16]) { 32 | double v = 0.0; 33 | 34 | const char* p = vstr; 35 | 36 | // sign 37 | bool sign = *p != '-'; 38 | if (*p == '+' || *p == '-') { 39 | p++; 40 | } 41 | 42 | // digits before decimal point or exponent 43 | unsigned int v1 = 0; 44 | while (isdigit(*p)) { 45 | v1 = v1 * 10 + (*p - '0'); 46 | p++; 47 | } 48 | 49 | v = (double)v1; 50 | 51 | // digits after decimal point 52 | if (*p == '.') { 53 | p++; 54 | 55 | unsigned int pow10 = 1; 56 | unsigned int v2 = 0; 57 | 58 | while (isdigit(*p)) { 59 | v2 = v2 * 10 + (*p - '0'); 60 | pow10 *= 10; 61 | p++; 62 | } 63 | 64 | v += v2 / (double)pow10; 65 | } 66 | 67 | // exponent 68 | if (*p == 'e' || *p == 'E') { 69 | p++; 70 | 71 | // sign of exponent 72 | bool fact = *p != '-'; 73 | if (*p == '+' || *p == '-') { 74 | p++; 75 | } 76 | 77 | // digits of exponent 78 | unsigned int expon = 0; 79 | while (isdigit(*p)) { 80 | expon = expon * 10 + (*p - '0'); 81 | p++; 82 | } 83 | 84 | double scale = 1.0; 85 | while (expon >= 8) { 86 | scale *= 1e8; 87 | expon -= 8; 88 | } 89 | while (expon > 0) { 90 | scale *= 10.0; 91 | expon -= 1; 92 | } 93 | 94 | v = fact ? v * scale : v / scale; 95 | } 96 | 97 | // fprintf(stderr, "v = %f\n", v); 98 | return sign ? (float)v : (float)-v; 99 | } 100 | 101 | int ParamDict::load_param(const DataReader& dr) { 102 | clear(); 103 | int id = 0; 104 | while (dr.scan("%d=", &id) == 1) { 105 | bool is_array = id <= -23300; 106 | if (is_array) { 107 | id = -id - 23300; 108 | } 109 | if (is_array) { 110 | int a = 0; 111 | } else { 112 | char vstr[16]; 113 | int nscan = dr.scan("%15s", vstr); 114 | 115 | bool is_float = vstr_is_float(vstr); 116 | if (is_float) 117 | params[id].f = vstr_to_float(vstr); 118 | else 119 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 120 | 121 | params[id].type = is_float ? 3 : 2; 122 | } 123 | } 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lesson/lesson_5/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | 5 | namespace ncnn { 6 | 7 | class DataReader; 8 | class Net; 9 | 10 | class ParamDict { 11 | public: 12 | ParamDict(); 13 | int get(int id, int def) const; 14 | float get(int id, float def) const; 15 | 16 | protected: 17 | friend class Net; 18 | int load_param(const DataReader& dr); 19 | void clear(); 20 | 21 | protected: 22 | struct { 23 | int type; 24 | union { 25 | int i; 26 | float f; 27 | }; 28 | } params[NCNN_MAX_PARAM_COUNT]; 29 | }; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lesson/lesson_6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession6) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_6/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_6) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_6/examples/lession_6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "iostream" 9 | #include "layer.h" 10 | #include "net.h" 11 | using namespace std; 12 | 13 | int main(int argc, char** argv) { 14 | cout << "buffer created" << endl; 15 | char* new_buff = (char*)fastMalloc(1000); 16 | 17 | cout << "buffer freed" << endl; 18 | fastFree(new_buff); 19 | 20 | printf("yes\n"); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | ) 10 | 11 | 12 | file(GLOB SRC_LAYER ${CMAKE_CURRENT_SOURCE_DIR}/layer/*.c*) 13 | list(APPEND ncnn_SRCS ${SRC_LAYER}) 14 | 15 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 16 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 17 | 18 | 19 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_ALLOCATOR_H 2 | #define NCNN_ALLOCATOR_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | #define MALLOC_ALIGN 16 9 | 10 | //相当于ptr首先向后移动n-1的位置,然后用-n进行最高位直接截断对其 11 | template 12 | static inline _Tp* alignPtr(_Tp* ptr, int n = (int)sizeof(_Tp)) { 13 | return (_Tp*)(((size_t)ptr + n - 1) & -n); 14 | } 15 | static inline size_t alignSize(size_t sz, int n) { return (sz + n - 1) & -n; } 16 | } 17 | 18 | static inline void* fastMalloc(size_t size) { 19 | //符合POSIX标准的c源码 20 | #if (defined(__unix__)) && _POSIX_C_SOURCE >= 200112L 21 | void* ptr = 0; 22 | if (posix_memalign(&ptr, MALLOC_ALIGN, size)) ptr = 0; 23 | return ptr; 24 | #else 25 | //预留需要的空间,sizeof(void*)的目的是给udata的地址留下空间,MALLOC_ALIGN的目的是使得对齐后有size的空间 26 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 27 | if (!udata) return 0; 28 | //从udata+8开始,其中8是udata地址的位置, 29 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 30 | adata[-1] = udata; 31 | return adata; 32 | #endif 33 | } 34 | 35 | static inline void fastFree(void* ptr) { 36 | if (ptr) { 37 | #if _MSC_VER 38 | _aligned_free(ptr); 39 | #elif (defined(__unix__) || defined(__APPLE__)) && _POSIX_C_SOURCE >= 200112L || \ 40 | (__ANDROID__ && __ANDROID_API__ >= 17) 41 | free(ptr); 42 | #elif __ANDROID__ && __ANDROID_API__ < 17 43 | free(ptr); 44 | #else 45 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 46 | free(udata); 47 | #endif 48 | } 49 | } 50 | 51 | class Allocator { 52 | public: 53 | virtual void* fastMalloc(size_t size) = 0; 54 | virtual void* fastFree(void* ptr) = 0; 55 | }; 56 | 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | #include "layer_declaration.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Layer::Layer() { } 10 | Layer::~Layer() {} 11 | 12 | int Layer::load_param(const ParamDict&) { return 0; } 13 | 14 | static const layer_registry_entry layer_registry[] = { 15 | {"ReLU", ReLU_final_layer_creator}, 16 | {"Input", Input_final_layer_creator}, 17 | {"Pooling", Pooling_final_layer_creator}, 18 | {"Convolution", Convolution_final_layer_creator}, 19 | {"Split", Split_final_layer_creator}, 20 | {"Concat", Concat_final_layer_creator}, 21 | {"Dropout", Dropout_final_layer_creator}, 22 | {"Softmax", Softmax_final_layer_creator}, 23 | 24 | }; 25 | 26 | //确定一共有多少个layer 27 | static const int layer_registry_entry_count = 28 | sizeof(layer_registry) / sizeof(layer_registry_entry); 29 | 30 | int layer_to_index(const char* type) { 31 | for (int i = 0; i < layer_registry_entry_count; i++) { 32 | if (strcmp(type, layer_registry[i].name) == 0) return i; 33 | } 34 | return -1; 35 | } 36 | 37 | Layer* create_layer(const char* type) { 38 | int index = layer_to_index(type); 39 | if (index == -1) return 0; 40 | return create_layer(index); 41 | } 42 | 43 | //基于id在数组里面找constructor 44 | Layer* create_layer(int index) { 45 | if (index < 0 || index >= layer_registry_entry_count) return 0; 46 | 47 | layer_creator_func layer_creator = 0; 48 | { layer_creator = layer_registry[index].creator; } 49 | 50 | if (!layer_creator) return 0; 51 | 52 | Layer* layer = layer_creator(); 53 | layer->typeindex = index; 54 | return layer; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "paramdict.h" 7 | 8 | namespace ncnn { 9 | 10 | class Layer { 11 | public: 12 | Layer(); 13 | virtual ~Layer(); 14 | virtual int load_param(const ParamDict& pd); 15 | 16 | public: 17 | int typeindex; 18 | std::string type; 19 | std::string name; 20 | std::vector bottoms; 21 | std::vector tops; 22 | 23 | }; 24 | 25 | typedef Layer* (*layer_creator_func)(); 26 | 27 | struct layer_registry_entry { 28 | const char* name; 29 | layer_creator_func creator; 30 | }; 31 | 32 | int layer_to_index(const char* type); 33 | Layer* create_layer(const char* type); 34 | Layer* create_layer(int index); 35 | 36 | #define DEFINE_LAYER_CREATOR(name) \ 37 | ncnn::Layer* name##_final_layer_creator() { return new name; } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/concat.cpp: -------------------------------------------------------------------------------- 1 | #include "concat.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Concat::Concat() { cout << "concat constructed" << endl; } 8 | 9 | int Concat::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 0); 11 | return 0; 12 | } 13 | 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/concat.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONCAT_H 2 | #define LAYER_CONCAT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Concat : public Layer { 9 | public: 10 | Concat(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/convolution.cpp: -------------------------------------------------------------------------------- 1 | #include "convolution.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Convolution::Convolution() { cout << "convolution constructed" << endl; } 8 | 9 | int Convolution::load_param(const ParamDict& pd) { 10 | num_output = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | dilation_w = pd.get(2, 1); 14 | dilation_h = pd.get(12, dilation_w); 15 | stride_w = pd.get(3, 1); 16 | stride_h = pd.get(13, stride_w); 17 | pad_left = pd.get(4, 0); 18 | pad_right = pd.get(15, pad_left); 19 | pad_top = pd.get(14, pad_left); 20 | pad_bottom = pd.get(16, pad_top); 21 | pad_value = pd.get(18, 0.f); 22 | bias_term = pd.get(5, 0); 23 | weight_data_size = pd.get(6, 0); 24 | int8_scale_term = pd.get(8, 0); 25 | impl_type = pd.get(17, 0); 26 | 27 | return 0; 28 | } 29 | 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/convolution.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONVOLUTION_H 2 | #define LAYER_CONVOLUTION_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Convolution : public Layer { 9 | public: 10 | Convolution(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int num_output; 15 | int kernel_w; 16 | int kernel_h; 17 | int dilation_w; 18 | int dilation_h; 19 | int stride_w; 20 | int stride_h; 21 | int pad_left; 22 | int pad_right; 23 | int pad_top; 24 | int pad_bottom; 25 | float pad_value; 26 | int bias_term; 27 | int weight_data_size; 28 | int int8_scale_term; 29 | int activation_type; 30 | float bottom_blob_int8_scale; 31 | float top_blob_int8_scale; 32 | bool use_int8_requantize; 33 | int impl_type; 34 | 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/dropout.cpp: -------------------------------------------------------------------------------- 1 | #include "dropout.h" 2 | #include "iostream" 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Dropout::Dropout() { cout << "dropout constructed" << endl; } 7 | 8 | int Dropout::load_param(const ParamDict& pd) { 9 | scale = pd.get(0, 1.f); 10 | return 0; 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/dropout.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_DROPOUT_h 2 | #define LAYER_DROPOUT_h 3 | #include "layer.h" 4 | 5 | namespace ncnn { 6 | 7 | class Dropout : public Layer { 8 | public: 9 | Dropout(); 10 | virtual int load_param(const ParamDict& pd); 11 | 12 | public: 13 | float scale; 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Input::Input() { cout << "input constructed" << endl; } 8 | 9 | int Input::load_param(const ParamDict& pd) { 10 | w = pd.get(0, 0); 11 | h = pd.get(1, 0); 12 | c = pd.get(2, 0); 13 | return 0; 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/input.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_INPUT_H 2 | #define LAYER_INPUT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Input : public Layer { 9 | public: 10 | Input(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int w; 15 | int h; 16 | int c; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/pooling.cpp: -------------------------------------------------------------------------------- 1 | #include "pooling.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Pooling::Pooling() { cout << "pooling constructed" << endl; } 8 | 9 | int Pooling::load_param(const ParamDict& pd) { 10 | pooling_type = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | stride_w = pd.get(2, 1); 14 | stride_h = pd.get(12, stride_w); 15 | pad_left = pd.get(3, 0); 16 | pad_right = pd.get(14, pad_left); 17 | pad_top = pd.get(13, pad_left); 18 | pad_bottom = pd.get(15, pad_top); 19 | global_pooling = pd.get(5, 0); 20 | avgpool_count_include_pad = pd.get(6, 0); 21 | } 22 | 23 | 24 | 25 | 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/pooling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_POOLING_H 2 | #define LAYER_POOLING_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Pooling : public Layer { 9 | public: 10 | Pooling(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int pooling_type; 15 | int kernel_w; 16 | int kernel_h; 17 | int stride_w; 18 | int stride_h; 19 | int pad_left; 20 | int pad_right; 21 | int pad_top; 22 | int pad_bottom; 23 | int global_pooling; 24 | int pad_mode; 25 | int avgpool_count_include_pad; 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/relu.cpp: -------------------------------------------------------------------------------- 1 | #include "relu.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | ReLU::ReLU() { cout << "relu constructed" << endl; } 8 | 9 | int ReLU::load_param(const ParamDict& pd) { 10 | slope = pd.get(0, 0.f); 11 | return 0; 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/relu.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_RELU_H 2 | #define LAYER_RELU_H 3 | #include 4 | #include "layer.h" 5 | using namespace std; 6 | namespace ncnn { 7 | 8 | class ReLU : public Layer { 9 | public: 10 | ReLU(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | float slope; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/softmax.cpp: -------------------------------------------------------------------------------- 1 | #include "softmax.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Softmax::Softmax() { cout << "softmax constructed" << endl; } 8 | 9 | int Softmax::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 9); 11 | return 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SOFTMAX_H 2 | #define LAYER_SOFTMAX_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Softmax : public Layer { 9 | public: 10 | Softmax(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/split.cpp: -------------------------------------------------------------------------------- 1 | #include "split.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | Split::Split() { cout << "split constructed" << endl; } 7 | } 8 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer/split.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SPLIT_H 2 | #define LAYER_SPLIT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Split : public Layer { 9 | public: 10 | Split(); 11 | }; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/layer_declaration.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_DECLARATION 2 | #define NCNN_LAYER_DECLARATION 3 | #include "layer/relu.h" 4 | namespace ncnn { 5 | DEFINE_LAYER_CREATOR(ReLU) 6 | } 7 | #include "layer/input.h" 8 | namespace ncnn { 9 | DEFINE_LAYER_CREATOR(Input) 10 | } 11 | 12 | #include "layer/pooling.h" 13 | namespace ncnn { 14 | DEFINE_LAYER_CREATOR(Pooling) 15 | } 16 | 17 | #include "layer/convolution.h" 18 | namespace ncnn { 19 | DEFINE_LAYER_CREATOR(Convolution) 20 | } 21 | 22 | #include "layer/split.h" 23 | namespace ncnn { 24 | DEFINE_LAYER_CREATOR(Split) 25 | } 26 | 27 | #include "layer/concat.h" 28 | namespace ncnn { 29 | DEFINE_LAYER_CREATOR(Concat) 30 | } 31 | 32 | #include "layer/dropout.h" 33 | namespace ncnn { 34 | DEFINE_LAYER_CREATOR(Dropout) 35 | } 36 | 37 | #include "layer/softmax.h" 38 | namespace ncnn { 39 | DEFINE_LAYER_CREATOR(Softmax) 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/net.cpp: -------------------------------------------------------------------------------- 1 | #include "net.h" 2 | #include 3 | #include 4 | #include "paramdict.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Net::Net() { } 10 | 11 | Net::~Net() {} 12 | 13 | int Net::load_param(const DataReader& dr) { 14 | #define SCAN_VALUE(fmt, v) dr.scan(fmt, &v); 15 | 16 | int magic = 0; 17 | SCAN_VALUE("%d", magic) 18 | 19 | int layer_count = 0; 20 | int blob_count = 0; 21 | 22 | SCAN_VALUE("%d", layer_count) 23 | SCAN_VALUE("%d", blob_count) 24 | 25 | layers.resize((size_t)layer_count); 26 | blobs.resize((size_t)blob_count); 27 | 28 | ParamDict pd; 29 | int blob_index = 0; 30 | for (int i = 0; i < layer_count; i++) { 31 | char layer_type[256]; 32 | char layer_name[256]; 33 | int bottom_count = 0; 34 | int top_count = 0; 35 | 36 | SCAN_VALUE("%255s", layer_type) 37 | SCAN_VALUE("%255s", layer_name) 38 | SCAN_VALUE("%d", bottom_count) 39 | SCAN_VALUE("%d", top_count) 40 | 41 | Layer* layer = create_layer(layer_type); 42 | // Layer* layer = new Layer(); 43 | 44 | layer->type = string(layer_type); 45 | layer->name = string(layer_name); 46 | layer->bottoms.resize(bottom_count); 47 | layer->tops.resize(top_count); 48 | 49 | for (int j = 0; j < bottom_count; j++) { 50 | char bottom_name[256]; 51 | SCAN_VALUE("%255s", bottom_name) 52 | int bottom_blob_index = 53 | find_blob_index_by_name(bottom_name); //找到blob的唯一id(在top中被指定的) 54 | Blob& blob = blobs[bottom_blob_index]; 55 | blob.consumers.push_back(i); //使用(消费)blob的时候的层的id 56 | layer->bottoms[j] = bottom_blob_index; // layer获取bottom_blob的blob_id 57 | } 58 | 59 | for (int j = 0; j < top_count; j++) { 60 | Blob& blob = 61 | blobs[blob_index]; // blob在top时候时候才是被产生的时候,获取这时候的blob_id 62 | char blob_name[256]; 63 | SCAN_VALUE("%255s", blob_name) 64 | blob.name = string(blob_name); 65 | blob.producer = i; //产生blob时候的层的id 66 | layer->tops[j] = blob_index; // Layer 获取top_blob的blob_id 67 | blob_index++; 68 | } 69 | 70 | 71 | //利用pd,load每一层的配置参数(非weight) 72 | int pdlr = pd.load_param(dr); 73 | 74 | layers[i] = layer; 75 | } 76 | 77 | #undef SCAN_VALUE 78 | 79 | return 0; 80 | } 81 | 82 | int Net::load_param(const char* protopath) { 83 | FILE* fp = fopen(protopath, "rb"); 84 | DataReaderFromStdio dr(fp); 85 | int ret = load_param(dr); 86 | fclose(fp); 87 | return ret; 88 | } 89 | 90 | int Net::find_blob_index_by_name(const char* name) const { 91 | for (size_t i = 0; i < blobs.size(); i++) { 92 | const Blob& blob = blobs[i]; 93 | if (blob.name == name) { 94 | return static_cast(i); 95 | } 96 | } 97 | 98 | return -1; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Net { 13 | public: 14 | Net(); 15 | ~Net(); 16 | 17 | int load_param(const DataReader& dr); 18 | int load_param(const char* protopath); 19 | int find_blob_index_by_name(const char* name) const; 20 | 21 | public: 22 | std::vector layers; 23 | std::vector blobs; //存放blob的信息,如layer或者shape等等 24 | 25 | 26 | }; 27 | 28 | 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | int ParamDict::get(int id, int def) const { return params[id].type ? params[id].i : def; } 11 | float ParamDict::get(int id, float def) const { return params[id].type ? params[id].f : def; } 12 | 13 | 14 | static bool vstr_is_float(const char vstr[16]) { 15 | // look ahead for determine isfloat 16 | for (int j = 0; j < 16; j++) { 17 | if (vstr[j] == '\0') break; 18 | 19 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | void ParamDict::clear() { 26 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 27 | params[i].type = 0; 28 | } 29 | } 30 | 31 | static float vstr_to_float(const char vstr[16]) { 32 | double v = 0.0; 33 | 34 | const char* p = vstr; 35 | 36 | // sign 37 | bool sign = *p != '-'; 38 | if (*p == '+' || *p == '-') { 39 | p++; 40 | } 41 | 42 | // digits before decimal point or exponent 43 | unsigned int v1 = 0; 44 | while (isdigit(*p)) { 45 | v1 = v1 * 10 + (*p - '0'); 46 | p++; 47 | } 48 | 49 | v = (double)v1; 50 | 51 | // digits after decimal point 52 | if (*p == '.') { 53 | p++; 54 | 55 | unsigned int pow10 = 1; 56 | unsigned int v2 = 0; 57 | 58 | while (isdigit(*p)) { 59 | v2 = v2 * 10 + (*p - '0'); 60 | pow10 *= 10; 61 | p++; 62 | } 63 | 64 | v += v2 / (double)pow10; 65 | } 66 | 67 | // exponent 68 | if (*p == 'e' || *p == 'E') { 69 | p++; 70 | 71 | // sign of exponent 72 | bool fact = *p != '-'; 73 | if (*p == '+' || *p == '-') { 74 | p++; 75 | } 76 | 77 | // digits of exponent 78 | unsigned int expon = 0; 79 | while (isdigit(*p)) { 80 | expon = expon * 10 + (*p - '0'); 81 | p++; 82 | } 83 | 84 | double scale = 1.0; 85 | while (expon >= 8) { 86 | scale *= 1e8; 87 | expon -= 8; 88 | } 89 | while (expon > 0) { 90 | scale *= 10.0; 91 | expon -= 1; 92 | } 93 | 94 | v = fact ? v * scale : v / scale; 95 | } 96 | 97 | // fprintf(stderr, "v = %f\n", v); 98 | return sign ? (float)v : (float)-v; 99 | } 100 | 101 | int ParamDict::load_param(const DataReader& dr) { 102 | clear(); 103 | int id = 0; 104 | while (dr.scan("%d=", &id) == 1) { 105 | bool is_array = id <= -23300; 106 | if (is_array) { 107 | id = -id - 23300; 108 | } 109 | if (is_array) { 110 | int a = 0; 111 | } else { 112 | char vstr[16]; 113 | int nscan = dr.scan("%15s", vstr); 114 | 115 | bool is_float = vstr_is_float(vstr); 116 | if (is_float) 117 | params[id].f = vstr_to_float(vstr); 118 | else 119 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 120 | 121 | params[id].type = is_float ? 3 : 2; 122 | } 123 | } 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lesson/lesson_6/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | 5 | namespace ncnn { 6 | 7 | class DataReader; 8 | class Net; 9 | 10 | class ParamDict { 11 | public: 12 | ParamDict(); 13 | int get(int id, int def) const; 14 | float get(int id, float def) const; 15 | 16 | protected: 17 | friend class Net; 18 | int load_param(const DataReader& dr); 19 | void clear(); 20 | 21 | protected: 22 | struct { 23 | int type; 24 | union { 25 | int i; 26 | float f; 27 | }; 28 | } params[NCNN_MAX_PARAM_COUNT]; 29 | }; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lesson/lesson_7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession7) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_7/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_7) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_7/examples/lession_7.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "iostream" 9 | #include "layer.h" 10 | #include "mat.h" 11 | #include "net.h" 12 | using namespace std; 13 | 14 | int main(int argc, char** argv) { 15 | ncnn::Mat tmpmat(100); 16 | printf("yes\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | ) 10 | 11 | 12 | file(GLOB SRC_LAYER ${CMAKE_CURRENT_SOURCE_DIR}/layer/*.c*) 13 | list(APPEND ncnn_SRCS ${SRC_LAYER}) 14 | 15 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 16 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 17 | 18 | 19 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_ALLOCATOR_H 2 | #define NCNN_ALLOCATOR_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | #define MALLOC_ALIGN 16 9 | 10 | //相当于ptr首先向后移动n-1的位置,然后用-n进行最高位直接截断对其 11 | template 12 | static inline _Tp* alignPtr(_Tp* ptr, int n = (int)sizeof(_Tp)) { 13 | return (_Tp*)(((size_t)ptr + n - 1) & -n); 14 | } 15 | 16 | static inline size_t alignSize(size_t sz, int n) { return (sz + n - 1) & -n; } 17 | 18 | 19 | static inline void* fastMalloc(size_t size) { 20 | //符合POSIX标准的c源码 21 | #if (defined(__unix__)) && _POSIX_C_SOURCE >= 200112L 22 | void* ptr = 0; 23 | if (posix_memalign(&ptr, MALLOC_ALIGN, size)) ptr = 0; 24 | return ptr; 25 | #else 26 | //预留需要的空间,sizeof(void*)的目的是给udata的地址留下空间,MALLOC_ALIGN的目的是使得对齐后有size的空间 27 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 28 | if (!udata) return 0; 29 | //从udata+8开始,其中8是udata地址的位置, 30 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 31 | adata[-1] = udata; 32 | return adata; 33 | #endif 34 | } 35 | 36 | static inline int NCNN_XADD(int* addr, int delta) { 37 | int tmp = *addr; 38 | *addr += delta; 39 | return tmp; 40 | } 41 | 42 | static inline void fastFree(void* ptr) { 43 | if (ptr) { 44 | #if _MSC_VER 45 | _aligned_free(ptr); 46 | #elif (defined(__unix__) || defined(__APPLE__)) && _POSIX_C_SOURCE >= 200112L || \ 47 | (__ANDROID__ && __ANDROID_API__ >= 17) 48 | free(ptr); 49 | #elif __ANDROID__ && __ANDROID_API__ < 17 50 | free(ptr); 51 | #else 52 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 53 | free(udata); 54 | #endif 55 | } 56 | } 57 | 58 | class Allocator { 59 | public: 60 | virtual void* fastMalloc(size_t size) = 0; 61 | virtual void* fastFree(void* ptr) = 0; 62 | }; 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | #include "layer_declaration.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Layer::Layer() { } 10 | Layer::~Layer() {} 11 | 12 | int Layer::load_param(const ParamDict&) { return 0; } 13 | 14 | static const layer_registry_entry layer_registry[] = { 15 | {"ReLU", ReLU_final_layer_creator}, 16 | {"Input", Input_final_layer_creator}, 17 | {"Pooling", Pooling_final_layer_creator}, 18 | {"Convolution", Convolution_final_layer_creator}, 19 | {"Split", Split_final_layer_creator}, 20 | {"Concat", Concat_final_layer_creator}, 21 | {"Dropout", Dropout_final_layer_creator}, 22 | {"Softmax", Softmax_final_layer_creator}, 23 | 24 | }; 25 | 26 | //确定一共有多少个layer 27 | static const int layer_registry_entry_count = 28 | sizeof(layer_registry) / sizeof(layer_registry_entry); 29 | 30 | int layer_to_index(const char* type) { 31 | for (int i = 0; i < layer_registry_entry_count; i++) { 32 | if (strcmp(type, layer_registry[i].name) == 0) return i; 33 | } 34 | return -1; 35 | } 36 | 37 | Layer* create_layer(const char* type) { 38 | int index = layer_to_index(type); 39 | if (index == -1) return 0; 40 | return create_layer(index); 41 | } 42 | 43 | //基于id在数组里面找constructor 44 | Layer* create_layer(int index) { 45 | if (index < 0 || index >= layer_registry_entry_count) return 0; 46 | 47 | layer_creator_func layer_creator = 0; 48 | { layer_creator = layer_registry[index].creator; } 49 | 50 | if (!layer_creator) return 0; 51 | 52 | Layer* layer = layer_creator(); 53 | layer->typeindex = index; 54 | return layer; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "paramdict.h" 7 | 8 | namespace ncnn { 9 | 10 | class Layer { 11 | public: 12 | Layer(); 13 | virtual ~Layer(); 14 | virtual int load_param(const ParamDict& pd); 15 | 16 | public: 17 | int typeindex; 18 | std::string type; 19 | std::string name; 20 | std::vector bottoms; 21 | std::vector tops; 22 | 23 | }; 24 | 25 | typedef Layer* (*layer_creator_func)(); 26 | 27 | struct layer_registry_entry { 28 | const char* name; 29 | layer_creator_func creator; 30 | }; 31 | 32 | int layer_to_index(const char* type); 33 | Layer* create_layer(const char* type); 34 | Layer* create_layer(int index); 35 | 36 | #define DEFINE_LAYER_CREATOR(name) \ 37 | ncnn::Layer* name##_final_layer_creator() { return new name; } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/concat.cpp: -------------------------------------------------------------------------------- 1 | #include "concat.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Concat::Concat() { cout << "concat constructed" << endl; } 8 | 9 | int Concat::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 0); 11 | return 0; 12 | } 13 | 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/concat.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONCAT_H 2 | #define LAYER_CONCAT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Concat : public Layer { 9 | public: 10 | Concat(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/convolution.cpp: -------------------------------------------------------------------------------- 1 | #include "convolution.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Convolution::Convolution() { cout << "convolution constructed" << endl; } 8 | 9 | int Convolution::load_param(const ParamDict& pd) { 10 | num_output = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | dilation_w = pd.get(2, 1); 14 | dilation_h = pd.get(12, dilation_w); 15 | stride_w = pd.get(3, 1); 16 | stride_h = pd.get(13, stride_w); 17 | pad_left = pd.get(4, 0); 18 | pad_right = pd.get(15, pad_left); 19 | pad_top = pd.get(14, pad_left); 20 | pad_bottom = pd.get(16, pad_top); 21 | pad_value = pd.get(18, 0.f); 22 | bias_term = pd.get(5, 0); 23 | weight_data_size = pd.get(6, 0); 24 | int8_scale_term = pd.get(8, 0); 25 | impl_type = pd.get(17, 0); 26 | 27 | return 0; 28 | } 29 | 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/convolution.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONVOLUTION_H 2 | #define LAYER_CONVOLUTION_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Convolution : public Layer { 9 | public: 10 | Convolution(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int num_output; 15 | int kernel_w; 16 | int kernel_h; 17 | int dilation_w; 18 | int dilation_h; 19 | int stride_w; 20 | int stride_h; 21 | int pad_left; 22 | int pad_right; 23 | int pad_top; 24 | int pad_bottom; 25 | float pad_value; 26 | int bias_term; 27 | int weight_data_size; 28 | int int8_scale_term; 29 | int activation_type; 30 | float bottom_blob_int8_scale; 31 | float top_blob_int8_scale; 32 | bool use_int8_requantize; 33 | int impl_type; 34 | 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/dropout.cpp: -------------------------------------------------------------------------------- 1 | #include "dropout.h" 2 | #include "iostream" 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Dropout::Dropout() { cout << "dropout constructed" << endl; } 7 | 8 | int Dropout::load_param(const ParamDict& pd) { 9 | scale = pd.get(0, 1.f); 10 | return 0; 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/dropout.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_DROPOUT_h 2 | #define LAYER_DROPOUT_h 3 | #include "layer.h" 4 | 5 | namespace ncnn { 6 | 7 | class Dropout : public Layer { 8 | public: 9 | Dropout(); 10 | virtual int load_param(const ParamDict& pd); 11 | 12 | public: 13 | float scale; 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Input::Input() { cout << "input constructed" << endl; } 8 | 9 | int Input::load_param(const ParamDict& pd) { 10 | w = pd.get(0, 0); 11 | h = pd.get(1, 0); 12 | c = pd.get(2, 0); 13 | return 0; 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/input.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_INPUT_H 2 | #define LAYER_INPUT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Input : public Layer { 9 | public: 10 | Input(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int w; 15 | int h; 16 | int c; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/pooling.cpp: -------------------------------------------------------------------------------- 1 | #include "pooling.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Pooling::Pooling() { cout << "pooling constructed" << endl; } 8 | 9 | int Pooling::load_param(const ParamDict& pd) { 10 | pooling_type = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | stride_w = pd.get(2, 1); 14 | stride_h = pd.get(12, stride_w); 15 | pad_left = pd.get(3, 0); 16 | pad_right = pd.get(14, pad_left); 17 | pad_top = pd.get(13, pad_left); 18 | pad_bottom = pd.get(15, pad_top); 19 | global_pooling = pd.get(5, 0); 20 | avgpool_count_include_pad = pd.get(6, 0); 21 | return 0; 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/pooling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_POOLING_H 2 | #define LAYER_POOLING_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Pooling : public Layer { 9 | public: 10 | Pooling(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int pooling_type; 15 | int kernel_w; 16 | int kernel_h; 17 | int stride_w; 18 | int stride_h; 19 | int pad_left; 20 | int pad_right; 21 | int pad_top; 22 | int pad_bottom; 23 | int global_pooling; 24 | int pad_mode; 25 | int avgpool_count_include_pad; 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/relu.cpp: -------------------------------------------------------------------------------- 1 | #include "relu.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | ReLU::ReLU() { cout << "relu constructed" << endl; } 8 | 9 | int ReLU::load_param(const ParamDict& pd) { 10 | slope = pd.get(0, 0.f); 11 | return 0; 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/relu.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_RELU_H 2 | #define LAYER_RELU_H 3 | #include 4 | #include "layer.h" 5 | using namespace std; 6 | namespace ncnn { 7 | 8 | class ReLU : public Layer { 9 | public: 10 | ReLU(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | float slope; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/softmax.cpp: -------------------------------------------------------------------------------- 1 | #include "softmax.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Softmax::Softmax() { cout << "softmax constructed" << endl; } 8 | 9 | int Softmax::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 9); 11 | return 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SOFTMAX_H 2 | #define LAYER_SOFTMAX_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Softmax : public Layer { 9 | public: 10 | Softmax(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/split.cpp: -------------------------------------------------------------------------------- 1 | #include "split.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | Split::Split() { cout << "split constructed" << endl; } 7 | } 8 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer/split.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SPLIT_H 2 | #define LAYER_SPLIT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Split : public Layer { 9 | public: 10 | Split(); 11 | }; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/layer_declaration.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_DECLARATION 2 | #define NCNN_LAYER_DECLARATION 3 | #include "layer/relu.h" 4 | namespace ncnn { 5 | DEFINE_LAYER_CREATOR(ReLU) 6 | } 7 | #include "layer/input.h" 8 | namespace ncnn { 9 | DEFINE_LAYER_CREATOR(Input) 10 | } 11 | 12 | #include "layer/pooling.h" 13 | namespace ncnn { 14 | DEFINE_LAYER_CREATOR(Pooling) 15 | } 16 | 17 | #include "layer/convolution.h" 18 | namespace ncnn { 19 | DEFINE_LAYER_CREATOR(Convolution) 20 | } 21 | 22 | #include "layer/split.h" 23 | namespace ncnn { 24 | DEFINE_LAYER_CREATOR(Split) 25 | } 26 | 27 | #include "layer/concat.h" 28 | namespace ncnn { 29 | DEFINE_LAYER_CREATOR(Concat) 30 | } 31 | 32 | #include "layer/dropout.h" 33 | namespace ncnn { 34 | DEFINE_LAYER_CREATOR(Dropout) 35 | } 36 | 37 | #include "layer/softmax.h" 38 | namespace ncnn { 39 | DEFINE_LAYER_CREATOR(Softmax) 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/net.cpp: -------------------------------------------------------------------------------- 1 | #include "net.h" 2 | #include 3 | #include 4 | #include "paramdict.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Net::Net() { } 10 | 11 | Net::~Net() {} 12 | 13 | int Net::load_param(const DataReader& dr) { 14 | #define SCAN_VALUE(fmt, v) dr.scan(fmt, &v); 15 | 16 | int magic = 0; 17 | SCAN_VALUE("%d", magic) 18 | 19 | int layer_count = 0; 20 | int blob_count = 0; 21 | 22 | SCAN_VALUE("%d", layer_count) 23 | SCAN_VALUE("%d", blob_count) 24 | 25 | layers.resize((size_t)layer_count); 26 | blobs.resize((size_t)blob_count); 27 | 28 | ParamDict pd; 29 | int blob_index = 0; 30 | for (int i = 0; i < layer_count; i++) { 31 | char layer_type[256]; 32 | char layer_name[256]; 33 | int bottom_count = 0; 34 | int top_count = 0; 35 | 36 | SCAN_VALUE("%255s", layer_type) 37 | SCAN_VALUE("%255s", layer_name) 38 | SCAN_VALUE("%d", bottom_count) 39 | SCAN_VALUE("%d", top_count) 40 | 41 | Layer* layer = create_layer(layer_type); 42 | // Layer* layer = new Layer(); 43 | 44 | layer->type = string(layer_type); 45 | layer->name = string(layer_name); 46 | layer->bottoms.resize(bottom_count); 47 | layer->tops.resize(top_count); 48 | 49 | for (int j = 0; j < bottom_count; j++) { 50 | char bottom_name[256]; 51 | SCAN_VALUE("%255s", bottom_name) 52 | int bottom_blob_index = 53 | find_blob_index_by_name(bottom_name); //找到blob的唯一id(在top中被指定的) 54 | Blob& blob = blobs[bottom_blob_index]; 55 | blob.consumers.push_back(i); //使用(消费)blob的时候的层的id 56 | layer->bottoms[j] = bottom_blob_index; // layer获取bottom_blob的blob_id 57 | } 58 | 59 | for (int j = 0; j < top_count; j++) { 60 | Blob& blob = 61 | blobs[blob_index]; // blob在top时候时候才是被产生的时候,获取这时候的blob_id 62 | char blob_name[256]; 63 | SCAN_VALUE("%255s", blob_name) 64 | blob.name = string(blob_name); 65 | blob.producer = i; //产生blob时候的层的id 66 | layer->tops[j] = blob_index; // Layer 获取top_blob的blob_id 67 | blob_index++; 68 | } 69 | 70 | 71 | //利用pd,load每一层的配置参数(非weight) 72 | int pdlr = pd.load_param(dr); 73 | 74 | layers[i] = layer; 75 | } 76 | 77 | #undef SCAN_VALUE 78 | 79 | return 0; 80 | } 81 | 82 | int Net::load_param(const char* protopath) { 83 | FILE* fp = fopen(protopath, "rb"); 84 | DataReaderFromStdio dr(fp); 85 | int ret = load_param(dr); 86 | fclose(fp); 87 | return ret; 88 | } 89 | 90 | int Net::find_blob_index_by_name(const char* name) const { 91 | for (size_t i = 0; i < blobs.size(); i++) { 92 | const Blob& blob = blobs[i]; 93 | if (blob.name == name) { 94 | return static_cast(i); 95 | } 96 | } 97 | 98 | return -1; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Net { 13 | public: 14 | Net(); 15 | ~Net(); 16 | 17 | int load_param(const DataReader& dr); 18 | int load_param(const char* protopath); 19 | int find_blob_index_by_name(const char* name) const; 20 | 21 | public: 22 | std::vector layers; 23 | std::vector blobs; //存放blob的信息,如layer或者shape等等 24 | 25 | 26 | }; 27 | 28 | 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | int ParamDict::get(int id, int def) const { return params[id].type ? params[id].i : def; } 11 | float ParamDict::get(int id, float def) const { return params[id].type ? params[id].f : def; } 12 | 13 | 14 | static bool vstr_is_float(const char vstr[16]) { 15 | // look ahead for determine isfloat 16 | for (int j = 0; j < 16; j++) { 17 | if (vstr[j] == '\0') break; 18 | 19 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | void ParamDict::clear() { 26 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 27 | params[i].type = 0; 28 | } 29 | } 30 | 31 | static float vstr_to_float(const char vstr[16]) { 32 | double v = 0.0; 33 | 34 | const char* p = vstr; 35 | 36 | // sign 37 | bool sign = *p != '-'; 38 | if (*p == '+' || *p == '-') { 39 | p++; 40 | } 41 | 42 | // digits before decimal point or exponent 43 | unsigned int v1 = 0; 44 | while (isdigit(*p)) { 45 | v1 = v1 * 10 + (*p - '0'); 46 | p++; 47 | } 48 | 49 | v = (double)v1; 50 | 51 | // digits after decimal point 52 | if (*p == '.') { 53 | p++; 54 | 55 | unsigned int pow10 = 1; 56 | unsigned int v2 = 0; 57 | 58 | while (isdigit(*p)) { 59 | v2 = v2 * 10 + (*p - '0'); 60 | pow10 *= 10; 61 | p++; 62 | } 63 | 64 | v += v2 / (double)pow10; 65 | } 66 | 67 | // exponent 68 | if (*p == 'e' || *p == 'E') { 69 | p++; 70 | 71 | // sign of exponent 72 | bool fact = *p != '-'; 73 | if (*p == '+' || *p == '-') { 74 | p++; 75 | } 76 | 77 | // digits of exponent 78 | unsigned int expon = 0; 79 | while (isdigit(*p)) { 80 | expon = expon * 10 + (*p - '0'); 81 | p++; 82 | } 83 | 84 | double scale = 1.0; 85 | while (expon >= 8) { 86 | scale *= 1e8; 87 | expon -= 8; 88 | } 89 | while (expon > 0) { 90 | scale *= 10.0; 91 | expon -= 1; 92 | } 93 | 94 | v = fact ? v * scale : v / scale; 95 | } 96 | 97 | // fprintf(stderr, "v = %f\n", v); 98 | return sign ? (float)v : (float)-v; 99 | } 100 | 101 | int ParamDict::load_param(const DataReader& dr) { 102 | clear(); 103 | int id = 0; 104 | while (dr.scan("%d=", &id) == 1) { 105 | bool is_array = id <= -23300; 106 | if (is_array) { 107 | id = -id - 23300; 108 | } 109 | if (is_array) { 110 | int a = 0; 111 | } else { 112 | char vstr[16]; 113 | int nscan = dr.scan("%15s", vstr); 114 | 115 | bool is_float = vstr_is_float(vstr); 116 | if (is_float) 117 | params[id].f = vstr_to_float(vstr); 118 | else 119 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 120 | 121 | params[id].type = is_float ? 3 : 2; 122 | } 123 | } 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lesson/lesson_7/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | 5 | namespace ncnn { 6 | 7 | class DataReader; 8 | class Net; 9 | 10 | class ParamDict { 11 | public: 12 | ParamDict(); 13 | int get(int id, int def) const; 14 | float get(int id, float def) const; 15 | 16 | protected: 17 | friend class Net; 18 | int load_param(const DataReader& dr); 19 | void clear(); 20 | 21 | protected: 22 | struct { 23 | int type; 24 | union { 25 | int i; 26 | float f; 27 | }; 28 | } params[NCNN_MAX_PARAM_COUNT]; 29 | }; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lesson/lesson_8/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession8) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_8/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | 8 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 9 | ncnn_add_example(lession_8) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/lesson_8/examples/lession_8.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "iostream" 9 | #include "layer.h" 10 | #include "mat.h" 11 | #include "net.h" 12 | using namespace std; 13 | 14 | int main(int argc, char** argv) { 15 | ncnn::Net squeezenet; 16 | squeezenet.load_param("../examples/squeezenet_v1.1.param"); 17 | squeezenet.load_model("../examples/squeezenet_v1.1.bin"); 18 | 19 | printf("yes\n"); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /lesson/lesson_8/examples/squeezenet_v1.1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/lesson/lesson_8/examples/squeezenet_v1.1.bin -------------------------------------------------------------------------------- /lesson/lesson_8/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | modelbin.cpp 10 | ) 11 | 12 | 13 | file(GLOB SRC_LAYER ${CMAKE_CURRENT_SOURCE_DIR}/layer/*.c*) 14 | list(APPEND ncnn_SRCS ${SRC_LAYER}) 15 | 16 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 17 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 18 | 19 | 20 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_ALLOCATOR_H 2 | #define NCNN_ALLOCATOR_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | #define MALLOC_ALIGN 16 9 | 10 | //相当于ptr首先向后移动n-1的位置,然后用-n进行最高位直接截断对其 11 | template 12 | static inline _Tp* alignPtr(_Tp* ptr, int n = (int)sizeof(_Tp)) { 13 | return (_Tp*)(((size_t)ptr + n - 1) & -n); 14 | } 15 | 16 | static inline size_t alignSize(size_t sz, int n) { return (sz + n - 1) & -n; } 17 | 18 | 19 | static inline void* fastMalloc(size_t size) { 20 | //符合POSIX标准的c源码 21 | #if (defined(__unix__)) && _POSIX_C_SOURCE >= 200112L 22 | void* ptr = 0; 23 | if (posix_memalign(&ptr, MALLOC_ALIGN, size)) ptr = 0; 24 | return ptr; 25 | #else 26 | //预留需要的空间,sizeof(void*)的目的是给udata的地址留下空间,MALLOC_ALIGN的目的是使得对齐后有size的空间 27 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 28 | if (!udata) return 0; 29 | //从udata+8开始,其中8是udata地址的位置, 30 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 31 | adata[-1] = udata; 32 | return adata; 33 | #endif 34 | } 35 | 36 | static inline int NCNN_XADD(int* addr, int delta) { 37 | int tmp = *addr; 38 | *addr += delta; 39 | return tmp; 40 | } 41 | 42 | static inline void fastFree(void* ptr) { 43 | if (ptr) { 44 | #if _MSC_VER 45 | _aligned_free(ptr); 46 | #elif (defined(__unix__) || defined(__APPLE__)) && _POSIX_C_SOURCE >= 200112L || \ 47 | (__ANDROID__ && __ANDROID_API__ >= 17) 48 | free(ptr); 49 | #elif __ANDROID__ && __ANDROID_API__ < 17 50 | free(ptr); 51 | #else 52 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 53 | free(udata); 54 | #endif 55 | } 56 | } 57 | 58 | class Allocator { 59 | public: 60 | virtual void* fastMalloc(size_t size) = 0; 61 | virtual void* fastFree(void* ptr) = 0; 62 | }; 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | #include "layer_declaration.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Layer::Layer() { } 10 | Layer::~Layer() {} 11 | 12 | int Layer::load_param(const ParamDict&) { return 0; } 13 | int Layer::load_model(const ModelBin&) { return 0; } 14 | 15 | static const layer_registry_entry layer_registry[] = { 16 | {"ReLU", ReLU_final_layer_creator}, 17 | {"Input", Input_final_layer_creator}, 18 | {"Pooling", Pooling_final_layer_creator}, 19 | {"Convolution", Convolution_final_layer_creator}, 20 | {"Split", Split_final_layer_creator}, 21 | {"Concat", Concat_final_layer_creator}, 22 | {"Dropout", Dropout_final_layer_creator}, 23 | {"Softmax", Softmax_final_layer_creator}, 24 | 25 | }; 26 | 27 | //确定一共有多少个layer 28 | static const int layer_registry_entry_count = 29 | sizeof(layer_registry) / sizeof(layer_registry_entry); 30 | 31 | int layer_to_index(const char* type) { 32 | for (int i = 0; i < layer_registry_entry_count; i++) { 33 | if (strcmp(type, layer_registry[i].name) == 0) return i; 34 | } 35 | return -1; 36 | } 37 | 38 | Layer* create_layer(const char* type) { 39 | int index = layer_to_index(type); 40 | if (index == -1) return 0; 41 | return create_layer(index); 42 | } 43 | 44 | //基于id在数组里面找constructor 45 | Layer* create_layer(int index) { 46 | if (index < 0 || index >= layer_registry_entry_count) return 0; 47 | 48 | layer_creator_func layer_creator = 0; 49 | { layer_creator = layer_registry[index].creator; } 50 | 51 | if (!layer_creator) return 0; 52 | 53 | Layer* layer = layer_creator(); 54 | layer->typeindex = index; 55 | return layer; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "modelbin.h" 7 | #include "paramdict.h" 8 | #include "mat.h" 9 | 10 | namespace ncnn { 11 | 12 | class Layer { 13 | public: 14 | Layer(); 15 | virtual ~Layer(); 16 | virtual int load_param(const ParamDict& pd); 17 | virtual int load_model(const ModelBin& mb); 18 | 19 | public: 20 | int typeindex; 21 | std::string type; 22 | std::string name; 23 | std::vector bottoms; 24 | std::vector tops; 25 | 26 | }; 27 | 28 | typedef Layer* (*layer_creator_func)(); 29 | 30 | struct layer_registry_entry { 31 | const char* name; 32 | layer_creator_func creator; 33 | }; 34 | 35 | int layer_to_index(const char* type); 36 | Layer* create_layer(const char* type); 37 | Layer* create_layer(int index); 38 | 39 | #define DEFINE_LAYER_CREATOR(name) \ 40 | ncnn::Layer* name##_final_layer_creator() { return new name; } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/concat.cpp: -------------------------------------------------------------------------------- 1 | #include "concat.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Concat::Concat() { cout << "concat constructed" << endl; } 8 | 9 | int Concat::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 0); 11 | return 0; 12 | } 13 | 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/concat.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONCAT_H 2 | #define LAYER_CONCAT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Concat : public Layer { 9 | public: 10 | Concat(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/convolution.cpp: -------------------------------------------------------------------------------- 1 | #include "convolution.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Convolution::Convolution() { cout << "convolution constructed" << endl; } 8 | 9 | int Convolution::load_param(const ParamDict& pd) { 10 | num_output = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | dilation_w = pd.get(2, 1); 14 | dilation_h = pd.get(12, dilation_w); 15 | stride_w = pd.get(3, 1); 16 | stride_h = pd.get(13, stride_w); 17 | pad_left = pd.get(4, 0); 18 | pad_right = pd.get(15, pad_left); 19 | pad_top = pd.get(14, pad_left); 20 | pad_bottom = pd.get(16, pad_top); 21 | pad_value = pd.get(18, 0.f); 22 | bias_term = pd.get(5, 0); 23 | weight_data_size = pd.get(6, 0); 24 | int8_scale_term = pd.get(8, 0); 25 | impl_type = pd.get(17, 0); 26 | 27 | return 0; 28 | } 29 | 30 | int Convolution::load_model(const ModelBin& mb) { 31 | weight_data = mb.load(weight_data_size, 0); 32 | if (weight_data.empty()) return -100; 33 | 34 | if (bias_term) { 35 | bias_data = mb.load(num_output, 1); 36 | if (bias_data.empty()) return -100; 37 | } 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/convolution.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONVOLUTION_H 2 | #define LAYER_CONVOLUTION_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Convolution : public Layer { 9 | public: 10 | Convolution(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int load_model(const ModelBin& mb); 13 | 14 | public: 15 | int num_output; 16 | int kernel_w; 17 | int kernel_h; 18 | int dilation_w; 19 | int dilation_h; 20 | int stride_w; 21 | int stride_h; 22 | int pad_left; 23 | int pad_right; 24 | int pad_top; 25 | int pad_bottom; 26 | float pad_value; 27 | int bias_term; 28 | int weight_data_size; 29 | int int8_scale_term; 30 | int activation_type; 31 | float bottom_blob_int8_scale; 32 | float top_blob_int8_scale; 33 | bool use_int8_requantize; 34 | int impl_type; 35 | Mat weight_data; 36 | Mat bias_data; 37 | }; 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/dropout.cpp: -------------------------------------------------------------------------------- 1 | #include "dropout.h" 2 | #include "iostream" 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Dropout::Dropout() { cout << "dropout constructed" << endl; } 7 | 8 | int Dropout::load_param(const ParamDict& pd) { 9 | scale = pd.get(0, 1.f); 10 | return 0; 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/dropout.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_DROPOUT_h 2 | #define LAYER_DROPOUT_h 3 | #include "layer.h" 4 | 5 | namespace ncnn { 6 | 7 | class Dropout : public Layer { 8 | public: 9 | Dropout(); 10 | virtual int load_param(const ParamDict& pd); 11 | 12 | public: 13 | float scale; 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Input::Input() { cout << "input constructed" << endl; } 8 | 9 | int Input::load_param(const ParamDict& pd) { 10 | w = pd.get(0, 0); 11 | h = pd.get(1, 0); 12 | c = pd.get(2, 0); 13 | return 0; 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/input.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_INPUT_H 2 | #define LAYER_INPUT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Input : public Layer { 9 | public: 10 | Input(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int w; 15 | int h; 16 | int c; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/pooling.cpp: -------------------------------------------------------------------------------- 1 | #include "pooling.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Pooling::Pooling() { cout << "pooling constructed" << endl; } 8 | 9 | int Pooling::load_param(const ParamDict& pd) { 10 | pooling_type = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | stride_w = pd.get(2, 1); 14 | stride_h = pd.get(12, stride_w); 15 | pad_left = pd.get(3, 0); 16 | pad_right = pd.get(14, pad_left); 17 | pad_top = pd.get(13, pad_left); 18 | pad_bottom = pd.get(15, pad_top); 19 | global_pooling = pd.get(5, 0); 20 | avgpool_count_include_pad = pd.get(6, 0); 21 | return 0; 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/pooling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_POOLING_H 2 | #define LAYER_POOLING_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Pooling : public Layer { 9 | public: 10 | Pooling(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int pooling_type; 15 | int kernel_w; 16 | int kernel_h; 17 | int stride_w; 18 | int stride_h; 19 | int pad_left; 20 | int pad_right; 21 | int pad_top; 22 | int pad_bottom; 23 | int global_pooling; 24 | int pad_mode; 25 | int avgpool_count_include_pad; 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/relu.cpp: -------------------------------------------------------------------------------- 1 | #include "relu.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | ReLU::ReLU() { cout << "relu constructed" << endl; } 8 | 9 | int ReLU::load_param(const ParamDict& pd) { 10 | slope = pd.get(0, 0.f); 11 | return 0; 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/relu.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_RELU_H 2 | #define LAYER_RELU_H 3 | #include 4 | #include "layer.h" 5 | using namespace std; 6 | namespace ncnn { 7 | 8 | class ReLU : public Layer { 9 | public: 10 | ReLU(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | float slope; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/softmax.cpp: -------------------------------------------------------------------------------- 1 | #include "softmax.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Softmax::Softmax() { cout << "softmax constructed" << endl; } 8 | 9 | int Softmax::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 9); 11 | return 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SOFTMAX_H 2 | #define LAYER_SOFTMAX_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Softmax : public Layer { 9 | public: 10 | Softmax(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/split.cpp: -------------------------------------------------------------------------------- 1 | #include "split.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | Split::Split() { cout << "split constructed" << endl; } 7 | } 8 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer/split.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SPLIT_H 2 | #define LAYER_SPLIT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Split : public Layer { 9 | public: 10 | Split(); 11 | }; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/layer_declaration.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_DECLARATION 2 | #define NCNN_LAYER_DECLARATION 3 | #include "layer/relu.h" 4 | namespace ncnn { 5 | DEFINE_LAYER_CREATOR(ReLU) 6 | } 7 | #include "layer/input.h" 8 | namespace ncnn { 9 | DEFINE_LAYER_CREATOR(Input) 10 | } 11 | 12 | #include "layer/pooling.h" 13 | namespace ncnn { 14 | DEFINE_LAYER_CREATOR(Pooling) 15 | } 16 | 17 | #include "layer/convolution.h" 18 | namespace ncnn { 19 | DEFINE_LAYER_CREATOR(Convolution) 20 | } 21 | 22 | #include "layer/split.h" 23 | namespace ncnn { 24 | DEFINE_LAYER_CREATOR(Split) 25 | } 26 | 27 | #include "layer/concat.h" 28 | namespace ncnn { 29 | DEFINE_LAYER_CREATOR(Concat) 30 | } 31 | 32 | #include "layer/dropout.h" 33 | namespace ncnn { 34 | DEFINE_LAYER_CREATOR(Dropout) 35 | } 36 | 37 | #include "layer/softmax.h" 38 | namespace ncnn { 39 | DEFINE_LAYER_CREATOR(Softmax) 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/modelbin.cpp: -------------------------------------------------------------------------------- 1 | #include "modelbin.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ModelBin::~ModelBin() {} 10 | 11 | 12 | ModelBinFromDataReader::ModelBinFromDataReader(const DataReader& _dr) : dr(_dr) {} 13 | 14 | Mat ModelBinFromDataReader::load(int w, int type) const { 15 | cout << "weight size : " << w << endl; 16 | if (type == 0) { 17 | size_t nread; 18 | 19 | union { 20 | struct { 21 | unsigned char f0; 22 | unsigned char f1; 23 | unsigned char f2; 24 | unsigned char f3; 25 | }; 26 | unsigned int tag; 27 | 28 | } flag_struct; 29 | 30 | nread = dr.read(&flag_struct, sizeof(flag_struct)); 31 | 32 | 33 | unsigned int flag = flag_struct.f0 + flag_struct.f1 + flag_struct.f2 + flag_struct.f3; 34 | Mat m(w); 35 | if (m.empty()) return m; 36 | if (flag != 0) { 37 | return m; 38 | } else if (flag_struct.f0 == 0) { 39 | nread = dr.read(m, w * sizeof(float)); 40 | } 41 | return m; 42 | } else if (type == 1) { 43 | Mat m(w); 44 | if (m.empty()) return m; 45 | size_t nread = dr.read(m, w * sizeof(float)); 46 | return m; 47 | } 48 | return Mat(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/modelbin.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_MODELBIN_H 2 | #define NCNN_MODELBIN_H 3 | 4 | #include "mat.h" 5 | 6 | namespace ncnn { 7 | 8 | class DataReader; 9 | class ModelBin { 10 | public: 11 | virtual ~ModelBin(); 12 | virtual Mat load(int w, int type) const = 0; 13 | }; 14 | 15 | class ModelBinFromDataReader : public ModelBin { 16 | public: 17 | ModelBinFromDataReader(const DataReader& dr); 18 | virtual Mat load(int w, int type) const; 19 | 20 | protected: 21 | const DataReader& dr; 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Net { 13 | public: 14 | Net(); 15 | ~Net(); 16 | 17 | int load_param(const DataReader& dr); 18 | int load_param(const char* protopath); 19 | int find_blob_index_by_name(const char* name) const; 20 | 21 | int load_model(const DataReader& dr); 22 | int load_model(const char* modelpath); 23 | 24 | public: 25 | std::vector layers; 26 | std::vector blobs; //存放blob的信息,如layer或者shape等等 27 | 28 | 29 | }; 30 | 31 | 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | int ParamDict::get(int id, int def) const { return params[id].type ? params[id].i : def; } 11 | float ParamDict::get(int id, float def) const { return params[id].type ? params[id].f : def; } 12 | 13 | 14 | static bool vstr_is_float(const char vstr[16]) { 15 | // look ahead for determine isfloat 16 | for (int j = 0; j < 16; j++) { 17 | if (vstr[j] == '\0') break; 18 | 19 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | void ParamDict::clear() { 26 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 27 | params[i].type = 0; 28 | } 29 | } 30 | 31 | static float vstr_to_float(const char vstr[16]) { 32 | double v = 0.0; 33 | 34 | const char* p = vstr; 35 | 36 | // sign 37 | bool sign = *p != '-'; 38 | if (*p == '+' || *p == '-') { 39 | p++; 40 | } 41 | 42 | // digits before decimal point or exponent 43 | unsigned int v1 = 0; 44 | while (isdigit(*p)) { 45 | v1 = v1 * 10 + (*p - '0'); 46 | p++; 47 | } 48 | 49 | v = (double)v1; 50 | 51 | // digits after decimal point 52 | if (*p == '.') { 53 | p++; 54 | 55 | unsigned int pow10 = 1; 56 | unsigned int v2 = 0; 57 | 58 | while (isdigit(*p)) { 59 | v2 = v2 * 10 + (*p - '0'); 60 | pow10 *= 10; 61 | p++; 62 | } 63 | 64 | v += v2 / (double)pow10; 65 | } 66 | 67 | // exponent 68 | if (*p == 'e' || *p == 'E') { 69 | p++; 70 | 71 | // sign of exponent 72 | bool fact = *p != '-'; 73 | if (*p == '+' || *p == '-') { 74 | p++; 75 | } 76 | 77 | // digits of exponent 78 | unsigned int expon = 0; 79 | while (isdigit(*p)) { 80 | expon = expon * 10 + (*p - '0'); 81 | p++; 82 | } 83 | 84 | double scale = 1.0; 85 | while (expon >= 8) { 86 | scale *= 1e8; 87 | expon -= 8; 88 | } 89 | while (expon > 0) { 90 | scale *= 10.0; 91 | expon -= 1; 92 | } 93 | 94 | v = fact ? v * scale : v / scale; 95 | } 96 | 97 | // fprintf(stderr, "v = %f\n", v); 98 | return sign ? (float)v : (float)-v; 99 | } 100 | 101 | int ParamDict::load_param(const DataReader& dr) { 102 | clear(); 103 | int id = 0; 104 | while (dr.scan("%d=", &id) == 1) { 105 | bool is_array = id <= -23300; 106 | if (is_array) { 107 | id = -id - 23300; 108 | } 109 | if (is_array) { 110 | int a = 0; 111 | } else { 112 | char vstr[16]; 113 | int nscan = dr.scan("%15s", vstr); 114 | 115 | bool is_float = vstr_is_float(vstr); 116 | if (is_float) 117 | params[id].f = vstr_to_float(vstr); 118 | else 119 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 120 | 121 | params[id].type = is_float ? 3 : 2; 122 | } 123 | } 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lesson/lesson_8/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | 5 | namespace ncnn { 6 | 7 | class DataReader; 8 | class Net; 9 | 10 | class ParamDict { 11 | public: 12 | ParamDict(); 13 | int get(int id, int def) const; 14 | float get(int id, float def) const; 15 | 16 | protected: 17 | friend class Net; 18 | int load_param(const DataReader& dr); 19 | void clear(); 20 | 21 | protected: 22 | struct { 23 | int type; 24 | union { 25 | int i; 26 | float f; 27 | }; 28 | } params[NCNN_MAX_PARAM_COUNT]; 29 | }; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lesson/lesson_9/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.12) 2 | set(CMAKE_BUILD_TYPE debug) 3 | project(ncnn_lession9) 4 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 6 | 7 | add_subdirectory(src) 8 | add_subdirectory(examples) 9 | -------------------------------------------------------------------------------- /lesson/lesson_9/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | macro(ncnn_add_example name) 2 | add_executable(${name} ${name}.cpp) 3 | target_link_libraries(${name} PRIVATE ncnn_lession1 ${OpenCV_LIBS}) 4 | set_property(TARGET ${name} PROPERTY FOLDER "examples") 5 | endmacro() 6 | 7 | find_package(OpenCV QUIET COMPONENTS opencv_world) 8 | if("${OpenCV_LIBS}" STREQUAL "") 9 | set(OpenCV_FOUND FALSE) 10 | endif() 11 | 12 | if(NOT OpenCV_FOUND) 13 | find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs videoio) 14 | endif() 15 | 16 | 17 | if(NOT OpenCV_FOUND) 18 | find_package(OpenCV QUIET COMPONENTS core highgui imgproc) 19 | endif() 20 | 21 | 22 | 23 | 24 | 25 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) 26 | ncnn_add_example(lession_9) 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /lesson/lesson_9/examples/dog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/lesson/lesson_9/examples/dog.png -------------------------------------------------------------------------------- /lesson/lesson_9/examples/lession_9.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "allocator.h" 8 | #include "blob.h" 9 | #include "datareader.h" 10 | #include "iostream" 11 | #include "layer.h" 12 | #include "mat.h" 13 | #include "net.h" 14 | using namespace std; 15 | 16 | int main(int argc, char** argv) { 17 | ncnn::Net squeezenet; 18 | squeezenet.load_param("../examples/squeezenet_v1.1.param"); 19 | squeezenet.load_model("../examples/squeezenet_v1.1.bin"); 20 | 21 | const char* imagepath = "../examples/dog.png"; 22 | cv::Mat bgr = cv::imread(imagepath, 1); 23 | ncnn::Mat in = ncnn::Mat::from_pixels(bgr.data, ncnn::Mat::PIXEL_BGR, bgr.cols, bgr.rows); 24 | 25 | printf("yes\n"); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /lesson/lesson_9/examples/squeezenet_v1.1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengtq/ncnn_breakdown/c7b1e6853c432724d2cd54e98cc6e7ce8a8c2612/lesson/lesson_9/examples/squeezenet_v1.1.bin -------------------------------------------------------------------------------- /lesson/lesson_9/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}") 2 | 3 | set(ncnn_SRCS 4 | datareader.cpp 5 | net.cpp 6 | layer.cpp 7 | blob.cpp 8 | paramdict.cpp 9 | modelbin.cpp 10 | mat_pixel.cpp 11 | ) 12 | 13 | 14 | file(GLOB SRC_LAYER ${CMAKE_CURRENT_SOURCE_DIR}/layer/*.c*) 15 | list(APPEND ncnn_SRCS ${SRC_LAYER}) 16 | 17 | set(LIBRARY_OUTPUT_PATH ${ncnn_lession1_BINARY_DIR/src_lib/}) 18 | add_library(ncnn_lession1 STATIC ${ncnn_SRCS}) 19 | 20 | 21 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/allocator.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_ALLOCATOR_H 2 | #define NCNN_ALLOCATOR_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | #define MALLOC_ALIGN 16 9 | 10 | //相当于ptr首先向后移动n-1的位置,然后用-n进行最高位直接截断对其 11 | template 12 | static inline _Tp* alignPtr(_Tp* ptr, int n = (int)sizeof(_Tp)) { 13 | return (_Tp*)(((size_t)ptr + n - 1) & -n); 14 | } 15 | 16 | static inline size_t alignSize(size_t sz, int n) { return (sz + n - 1) & -n; } 17 | 18 | 19 | static inline void* fastMalloc(size_t size) { 20 | //符合POSIX标准的c源码 21 | #if (defined(__unix__)) && _POSIX_C_SOURCE >= 200112L 22 | void* ptr = 0; 23 | if (posix_memalign(&ptr, MALLOC_ALIGN, size)) ptr = 0; 24 | return ptr; 25 | #else 26 | //预留需要的空间,sizeof(void*)的目的是给udata的地址留下空间,MALLOC_ALIGN的目的是使得对齐后有size的空间 27 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 28 | if (!udata) return 0; 29 | //从udata+8开始,其中8是udata地址的位置, 30 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 31 | adata[-1] = udata; 32 | return adata; 33 | #endif 34 | } 35 | 36 | static inline int NCNN_XADD(int* addr, int delta) { 37 | int tmp = *addr; 38 | *addr += delta; 39 | return tmp; 40 | } 41 | 42 | static inline void fastFree(void* ptr) { 43 | if (ptr) { 44 | #if _MSC_VER 45 | _aligned_free(ptr); 46 | #elif (defined(__unix__) || defined(__APPLE__)) && _POSIX_C_SOURCE >= 200112L || \ 47 | (__ANDROID__ && __ANDROID_API__ >= 17) 48 | free(ptr); 49 | #elif __ANDROID__ && __ANDROID_API__ < 17 50 | free(ptr); 51 | #else 52 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 53 | free(udata); 54 | #endif 55 | } 56 | } 57 | 58 | class Allocator { 59 | public: 60 | virtual void* fastMalloc(size_t size) = 0; 61 | virtual void* fastFree(void* ptr) = 0; 62 | }; 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/blob.cpp: -------------------------------------------------------------------------------- 1 | #include "blob.h" 2 | #include 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Blob::Blob() { 7 | producer = -1; } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/blob.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_BLOB_H 2 | #define NCNN_BLOB_H 3 | 4 | #include 5 | #include 6 | 7 | namespace ncnn { 8 | 9 | class Blob { 10 | public: 11 | Blob(); 12 | 13 | public: 14 | std::string name; 15 | int producer; 16 | std::vector consumers; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/datareader.cpp: -------------------------------------------------------------------------------- 1 | #include "datareader.h" 2 | #include 3 | 4 | namespace ncnn { 5 | DataReader::~DataReader() {} 6 | 7 | int DataReader::scan(const char*, void*) const { return 0; } 8 | size_t DataReader::read(void*, size_t) const { return 0; } 9 | 10 | DataReaderFromStdio::DataReaderFromStdio(FILE* _fp) : fp(_fp) {} 11 | 12 | int DataReaderFromStdio::scan(const char* format, void* p) const { return fscanf(fp, format, p); } 13 | 14 | size_t DataReaderFromStdio::read(void* buf, size_t size) const { return fread(buf, 1, size, fp); } 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/datareader.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_DATAREADER_H 2 | #define NCNN_DATAREADER_H 3 | 4 | #include 5 | 6 | namespace ncnn { 7 | 8 | class DataReader { 9 | public: 10 | virtual ~DataReader(); 11 | virtual int scan(const char* format, void* p) const; 12 | virtual size_t read(void* buf, size_t size) const; 13 | }; 14 | 15 | class DataReaderFromStdio : public DataReader { 16 | public: 17 | DataReaderFromStdio(FILE* fp); 18 | virtual int scan(const char* format, void* p) const; 19 | virtual size_t read(void* buf, size_t size) const; 20 | 21 | protected: 22 | FILE* fp; 23 | }; 24 | 25 | 26 | } 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer.cpp: -------------------------------------------------------------------------------- 1 | #include "layer.h" 2 | #include 3 | #include 4 | #include "layer_declaration.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | Layer::Layer() { } 10 | Layer::~Layer() {} 11 | 12 | int Layer::load_param(const ParamDict&) { return 0; } 13 | int Layer::load_model(const ModelBin&) { return 0; } 14 | 15 | static const layer_registry_entry layer_registry[] = { 16 | {"ReLU", ReLU_final_layer_creator}, 17 | {"Input", Input_final_layer_creator}, 18 | {"Pooling", Pooling_final_layer_creator}, 19 | {"Convolution", Convolution_final_layer_creator}, 20 | {"Split", Split_final_layer_creator}, 21 | {"Concat", Concat_final_layer_creator}, 22 | {"Dropout", Dropout_final_layer_creator}, 23 | {"Softmax", Softmax_final_layer_creator}, 24 | 25 | }; 26 | 27 | //确定一共有多少个layer 28 | static const int layer_registry_entry_count = 29 | sizeof(layer_registry) / sizeof(layer_registry_entry); 30 | 31 | int layer_to_index(const char* type) { 32 | for (int i = 0; i < layer_registry_entry_count; i++) { 33 | if (strcmp(type, layer_registry[i].name) == 0) return i; 34 | } 35 | return -1; 36 | } 37 | 38 | Layer* create_layer(const char* type) { 39 | int index = layer_to_index(type); 40 | if (index == -1) return 0; 41 | return create_layer(index); 42 | } 43 | 44 | //基于id在数组里面找constructor 45 | Layer* create_layer(int index) { 46 | if (index < 0 || index >= layer_registry_entry_count) return 0; 47 | 48 | layer_creator_func layer_creator = 0; 49 | { layer_creator = layer_registry[index].creator; } 50 | 51 | if (!layer_creator) return 0; 52 | 53 | Layer* layer = layer_creator(); 54 | layer->typeindex = index; 55 | return layer; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_H 2 | #define NCNN_LAYER_H 3 | #include 4 | #include 5 | #include "allocator.h" 6 | #include "modelbin.h" 7 | #include "paramdict.h" 8 | #include "mat.h" 9 | 10 | namespace ncnn { 11 | 12 | class Layer { 13 | public: 14 | Layer(); 15 | virtual ~Layer(); 16 | virtual int load_param(const ParamDict& pd); 17 | virtual int load_model(const ModelBin& mb); 18 | 19 | public: 20 | int typeindex; 21 | std::string type; 22 | std::string name; 23 | std::vector bottoms; 24 | std::vector tops; 25 | 26 | }; 27 | 28 | typedef Layer* (*layer_creator_func)(); 29 | 30 | struct layer_registry_entry { 31 | const char* name; 32 | layer_creator_func creator; 33 | }; 34 | 35 | int layer_to_index(const char* type); 36 | Layer* create_layer(const char* type); 37 | Layer* create_layer(int index); 38 | 39 | #define DEFINE_LAYER_CREATOR(name) \ 40 | ncnn::Layer* name##_final_layer_creator() { return new name; } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/concat.cpp: -------------------------------------------------------------------------------- 1 | #include "concat.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Concat::Concat() { cout << "concat constructed" << endl; } 8 | 9 | int Concat::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 0); 11 | return 0; 12 | } 13 | 14 | 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/concat.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONCAT_H 2 | #define LAYER_CONCAT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Concat : public Layer { 9 | public: 10 | Concat(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/convolution.cpp: -------------------------------------------------------------------------------- 1 | #include "convolution.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Convolution::Convolution() { cout << "convolution constructed" << endl; } 8 | 9 | int Convolution::load_param(const ParamDict& pd) { 10 | num_output = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | dilation_w = pd.get(2, 1); 14 | dilation_h = pd.get(12, dilation_w); 15 | stride_w = pd.get(3, 1); 16 | stride_h = pd.get(13, stride_w); 17 | pad_left = pd.get(4, 0); 18 | pad_right = pd.get(15, pad_left); 19 | pad_top = pd.get(14, pad_left); 20 | pad_bottom = pd.get(16, pad_top); 21 | pad_value = pd.get(18, 0.f); 22 | bias_term = pd.get(5, 0); 23 | weight_data_size = pd.get(6, 0); 24 | int8_scale_term = pd.get(8, 0); 25 | impl_type = pd.get(17, 0); 26 | 27 | return 0; 28 | } 29 | 30 | int Convolution::load_model(const ModelBin& mb) { 31 | weight_data = mb.load(weight_data_size, 0); 32 | if (weight_data.empty()) return -100; 33 | 34 | if (bias_term) { 35 | bias_data = mb.load(num_output, 1); 36 | if (bias_data.empty()) return -100; 37 | } 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/convolution.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_CONVOLUTION_H 2 | #define LAYER_CONVOLUTION_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Convolution : public Layer { 9 | public: 10 | Convolution(); 11 | virtual int load_param(const ParamDict& pd); 12 | virtual int load_model(const ModelBin& mb); 13 | 14 | public: 15 | int num_output; 16 | int kernel_w; 17 | int kernel_h; 18 | int dilation_w; 19 | int dilation_h; 20 | int stride_w; 21 | int stride_h; 22 | int pad_left; 23 | int pad_right; 24 | int pad_top; 25 | int pad_bottom; 26 | float pad_value; 27 | int bias_term; 28 | int weight_data_size; 29 | int int8_scale_term; 30 | int activation_type; 31 | float bottom_blob_int8_scale; 32 | float top_blob_int8_scale; 33 | bool use_int8_requantize; 34 | int impl_type; 35 | Mat weight_data; 36 | Mat bias_data; 37 | }; 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/dropout.cpp: -------------------------------------------------------------------------------- 1 | #include "dropout.h" 2 | #include "iostream" 3 | using namespace std; 4 | namespace ncnn { 5 | 6 | Dropout::Dropout() { cout << "dropout constructed" << endl; } 7 | 8 | int Dropout::load_param(const ParamDict& pd) { 9 | scale = pd.get(0, 1.f); 10 | return 0; 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/dropout.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_DROPOUT_h 2 | #define LAYER_DROPOUT_h 3 | #include "layer.h" 4 | 5 | namespace ncnn { 6 | 7 | class Dropout : public Layer { 8 | public: 9 | Dropout(); 10 | virtual int load_param(const ParamDict& pd); 11 | 12 | public: 13 | float scale; 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Input::Input() { cout << "input constructed" << endl; } 8 | 9 | int Input::load_param(const ParamDict& pd) { 10 | w = pd.get(0, 0); 11 | h = pd.get(1, 0); 12 | c = pd.get(2, 0); 13 | return 0; 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/input.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_INPUT_H 2 | #define LAYER_INPUT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Input : public Layer { 9 | public: 10 | Input(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int w; 15 | int h; 16 | int c; 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/pooling.cpp: -------------------------------------------------------------------------------- 1 | #include "pooling.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Pooling::Pooling() { cout << "pooling constructed" << endl; } 8 | 9 | int Pooling::load_param(const ParamDict& pd) { 10 | pooling_type = pd.get(0, 0); 11 | kernel_w = pd.get(1, 0); 12 | kernel_h = pd.get(11, kernel_w); 13 | stride_w = pd.get(2, 1); 14 | stride_h = pd.get(12, stride_w); 15 | pad_left = pd.get(3, 0); 16 | pad_right = pd.get(14, pad_left); 17 | pad_top = pd.get(13, pad_left); 18 | pad_bottom = pd.get(15, pad_top); 19 | global_pooling = pd.get(5, 0); 20 | avgpool_count_include_pad = pd.get(6, 0); 21 | return 0; 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/pooling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_POOLING_H 2 | #define LAYER_POOLING_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Pooling : public Layer { 9 | public: 10 | Pooling(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int pooling_type; 15 | int kernel_w; 16 | int kernel_h; 17 | int stride_w; 18 | int stride_h; 19 | int pad_left; 20 | int pad_right; 21 | int pad_top; 22 | int pad_bottom; 23 | int global_pooling; 24 | int pad_mode; 25 | int avgpool_count_include_pad; 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/relu.cpp: -------------------------------------------------------------------------------- 1 | #include "relu.h" 2 | #include 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | ReLU::ReLU() { cout << "relu constructed" << endl; } 8 | 9 | int ReLU::load_param(const ParamDict& pd) { 10 | slope = pd.get(0, 0.f); 11 | return 0; 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/relu.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_RELU_H 2 | #define LAYER_RELU_H 3 | #include 4 | #include "layer.h" 5 | using namespace std; 6 | namespace ncnn { 7 | 8 | class ReLU : public Layer { 9 | public: 10 | ReLU(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | float slope; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/softmax.cpp: -------------------------------------------------------------------------------- 1 | #include "softmax.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | 7 | Softmax::Softmax() { cout << "softmax constructed" << endl; } 8 | 9 | int Softmax::load_param(const ParamDict& pd) { 10 | axis = pd.get(0, 9); 11 | return 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/softmax.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SOFTMAX_H 2 | #define LAYER_SOFTMAX_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Softmax : public Layer { 9 | public: 10 | Softmax(); 11 | virtual int load_param(const ParamDict& pd); 12 | 13 | public: 14 | int axis; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/split.cpp: -------------------------------------------------------------------------------- 1 | #include "split.h" 2 | #include "iostream" 3 | using namespace std; 4 | 5 | namespace ncnn { 6 | Split::Split() { cout << "split constructed" << endl; } 7 | } 8 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer/split.h: -------------------------------------------------------------------------------- 1 | #ifndef LAYER_SPLIT_H 2 | #define LAYER_SPLIT_H 3 | 4 | #include "layer.h" 5 | 6 | namespace ncnn { 7 | 8 | class Split : public Layer { 9 | public: 10 | Split(); 11 | }; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/layer_declaration.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_LAYER_DECLARATION 2 | #define NCNN_LAYER_DECLARATION 3 | #include "layer/relu.h" 4 | namespace ncnn { 5 | DEFINE_LAYER_CREATOR(ReLU) 6 | } 7 | #include "layer/input.h" 8 | namespace ncnn { 9 | DEFINE_LAYER_CREATOR(Input) 10 | } 11 | 12 | #include "layer/pooling.h" 13 | namespace ncnn { 14 | DEFINE_LAYER_CREATOR(Pooling) 15 | } 16 | 17 | #include "layer/convolution.h" 18 | namespace ncnn { 19 | DEFINE_LAYER_CREATOR(Convolution) 20 | } 21 | 22 | #include "layer/split.h" 23 | namespace ncnn { 24 | DEFINE_LAYER_CREATOR(Split) 25 | } 26 | 27 | #include "layer/concat.h" 28 | namespace ncnn { 29 | DEFINE_LAYER_CREATOR(Concat) 30 | } 31 | 32 | #include "layer/dropout.h" 33 | namespace ncnn { 34 | DEFINE_LAYER_CREATOR(Dropout) 35 | } 36 | 37 | #include "layer/softmax.h" 38 | namespace ncnn { 39 | DEFINE_LAYER_CREATOR(Softmax) 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/mat_pixel.cpp: -------------------------------------------------------------------------------- 1 | #include "mat.h" 2 | 3 | namespace ncnn { 4 | static int from_rgb(const unsigned char* rgb, int w, int h, int stride, Mat& m, 5 | Allocator* allocator) { 6 | m.create(w, h, 3, 4u, allocator); 7 | if (m.empty()) return -100; 8 | 9 | const int wgap = stride - w * 3; 10 | if (wgap == 0) { 11 | w = w * h; 12 | h = 1; 13 | } 14 | 15 | float* ptr0 = m.channel(0); 16 | float* ptr1 = m.channel(1); 17 | float* ptr2 = m.channel(2); 18 | 19 | for (int y = 0; y < h; y++) { 20 | int remain = w; 21 | for (; remain > 0; remain--) { 22 | *ptr0 = rgb[0]; 23 | *ptr1 = rgb[1]; 24 | *ptr2 = rgb[2]; 25 | rgb += 3; 26 | ptr0++; 27 | ptr1++; 28 | ptr2++; 29 | } 30 | rgb += wgap; 31 | } 32 | 33 | cout << "success" << endl; 34 | return 0; 35 | } 36 | 37 | Mat Mat::from_pixels(const unsigned char* pixels, int type, int w, int h, Allocator* allocator) { 38 | if (type == PIXEL_RGB || type == PIXEL_BGR) { 39 | return Mat::from_pixels(pixels, type, w, h, w * 3, allocator); 40 | } 41 | return Mat(); 42 | } 43 | 44 | Mat Mat::from_pixels(const unsigned char* pixels, int type, int w, int h, int stride, 45 | Allocator* allocator) { 46 | Mat m; 47 | if (type == PIXEL_RGB || PIXEL_RGB) from_rgb(pixels, w, h, stride, m, allocator); 48 | return m; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/modelbin.cpp: -------------------------------------------------------------------------------- 1 | #include "modelbin.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ModelBin::~ModelBin() {} 10 | 11 | 12 | ModelBinFromDataReader::ModelBinFromDataReader(const DataReader& _dr) : dr(_dr) {} 13 | 14 | Mat ModelBinFromDataReader::load(int w, int type) const { 15 | if (type == 0) { 16 | size_t nread; 17 | 18 | union { 19 | struct { 20 | unsigned char f0; 21 | unsigned char f1; 22 | unsigned char f2; 23 | unsigned char f3; 24 | }; 25 | unsigned int tag; 26 | 27 | } flag_struct; 28 | 29 | nread = dr.read(&flag_struct, sizeof(flag_struct)); 30 | 31 | 32 | unsigned int flag = flag_struct.f0 + flag_struct.f1 + flag_struct.f2 + flag_struct.f3; 33 | Mat m(w); 34 | if (m.empty()) return m; 35 | if (flag != 0) { 36 | return m; 37 | } else if (flag_struct.f0 == 0) { 38 | nread = dr.read(m, w * sizeof(float)); 39 | } 40 | return m; 41 | } else if (type == 1) { 42 | Mat m(w); 43 | if (m.empty()) return m; 44 | size_t nread = dr.read(m, w * sizeof(float)); 45 | return m; 46 | } 47 | return Mat(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/modelbin.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_MODELBIN_H 2 | #define NCNN_MODELBIN_H 3 | 4 | #include "mat.h" 5 | 6 | namespace ncnn { 7 | 8 | class DataReader; 9 | class ModelBin { 10 | public: 11 | virtual ~ModelBin(); 12 | virtual Mat load(int w, int type) const = 0; 13 | }; 14 | 15 | class ModelBinFromDataReader : public ModelBin { 16 | public: 17 | ModelBinFromDataReader(const DataReader& dr); 18 | virtual Mat load(int w, int type) const; 19 | 20 | protected: 21 | const DataReader& dr; 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/net.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_NET_H 2 | #define NCNN_NET_H 3 | #include 4 | #include 5 | #include 6 | #include "blob.h" 7 | #include "datareader.h" 8 | #include "layer.h" 9 | 10 | namespace ncnn{ 11 | 12 | class Net { 13 | public: 14 | Net(); 15 | ~Net(); 16 | 17 | int load_param(const DataReader& dr); 18 | int load_param(const char* protopath); 19 | int find_blob_index_by_name(const char* name) const; 20 | 21 | int load_model(const DataReader& dr); 22 | int load_model(const char* modelpath); 23 | 24 | public: 25 | std::vector layers; 26 | std::vector blobs; //存放blob的信息,如layer或者shape等等 27 | 28 | 29 | }; 30 | 31 | 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/paramdict.cpp: -------------------------------------------------------------------------------- 1 | #include "paramdict.h" 2 | #include 3 | #include 4 | #include "datareader.h" 5 | using namespace std; 6 | 7 | namespace ncnn { 8 | 9 | ParamDict::ParamDict() { clear(); } 10 | int ParamDict::get(int id, int def) const { return params[id].type ? params[id].i : def; } 11 | float ParamDict::get(int id, float def) const { return params[id].type ? params[id].f : def; } 12 | 13 | 14 | static bool vstr_is_float(const char vstr[16]) { 15 | // look ahead for determine isfloat 16 | for (int j = 0; j < 16; j++) { 17 | if (vstr[j] == '\0') break; 18 | 19 | if (vstr[j] == '.' || tolower(vstr[j]) == 'e') return true; 20 | } 21 | 22 | return false; 23 | } 24 | 25 | void ParamDict::clear() { 26 | for (int i = 0; i < NCNN_MAX_PARAM_COUNT; i++) { 27 | params[i].type = 0; 28 | } 29 | } 30 | 31 | static float vstr_to_float(const char vstr[16]) { 32 | double v = 0.0; 33 | 34 | const char* p = vstr; 35 | 36 | // sign 37 | bool sign = *p != '-'; 38 | if (*p == '+' || *p == '-') { 39 | p++; 40 | } 41 | 42 | // digits before decimal point or exponent 43 | unsigned int v1 = 0; 44 | while (isdigit(*p)) { 45 | v1 = v1 * 10 + (*p - '0'); 46 | p++; 47 | } 48 | 49 | v = (double)v1; 50 | 51 | // digits after decimal point 52 | if (*p == '.') { 53 | p++; 54 | 55 | unsigned int pow10 = 1; 56 | unsigned int v2 = 0; 57 | 58 | while (isdigit(*p)) { 59 | v2 = v2 * 10 + (*p - '0'); 60 | pow10 *= 10; 61 | p++; 62 | } 63 | 64 | v += v2 / (double)pow10; 65 | } 66 | 67 | // exponent 68 | if (*p == 'e' || *p == 'E') { 69 | p++; 70 | 71 | // sign of exponent 72 | bool fact = *p != '-'; 73 | if (*p == '+' || *p == '-') { 74 | p++; 75 | } 76 | 77 | // digits of exponent 78 | unsigned int expon = 0; 79 | while (isdigit(*p)) { 80 | expon = expon * 10 + (*p - '0'); 81 | p++; 82 | } 83 | 84 | double scale = 1.0; 85 | while (expon >= 8) { 86 | scale *= 1e8; 87 | expon -= 8; 88 | } 89 | while (expon > 0) { 90 | scale *= 10.0; 91 | expon -= 1; 92 | } 93 | 94 | v = fact ? v * scale : v / scale; 95 | } 96 | 97 | // fprintf(stderr, "v = %f\n", v); 98 | return sign ? (float)v : (float)-v; 99 | } 100 | 101 | int ParamDict::load_param(const DataReader& dr) { 102 | clear(); 103 | int id = 0; 104 | while (dr.scan("%d=", &id) == 1) { 105 | bool is_array = id <= -23300; 106 | if (is_array) { 107 | id = -id - 23300; 108 | } 109 | if (is_array) { 110 | int a = 0; 111 | } else { 112 | char vstr[16]; 113 | int nscan = dr.scan("%15s", vstr); 114 | 115 | bool is_float = vstr_is_float(vstr); 116 | if (is_float) 117 | params[id].f = vstr_to_float(vstr); 118 | else 119 | nscan = sscanf(vstr, "%d", ¶ms[id].i); 120 | 121 | params[id].type = is_float ? 3 : 2; 122 | } 123 | } 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lesson/lesson_9/src/paramdict.h: -------------------------------------------------------------------------------- 1 | #ifndef NCNN_PARAMDICT_H 2 | #define NCNN_PARAMDICT_H 3 | #define NCNN_MAX_PARAM_COUNT 32 4 | 5 | namespace ncnn { 6 | 7 | class DataReader; 8 | class Net; 9 | 10 | class ParamDict { 11 | public: 12 | ParamDict(); 13 | int get(int id, int def) const; 14 | float get(int id, float def) const; 15 | 16 | protected: 17 | friend class Net; 18 | int load_param(const DataReader& dr); 19 | void clear(); 20 | 21 | protected: 22 | struct { 23 | int type; 24 | union { 25 | int i; 26 | float f; 27 | }; 28 | } params[NCNN_MAX_PARAM_COUNT]; 29 | }; 30 | } 31 | 32 | #endif 33 | --------------------------------------------------------------------------------