├── README.md ├── arcface ├── Makefile ├── arcface.cpp ├── arcface.h ├── base.cpp ├── base.h ├── main.cpp ├── mtcnn.cpp └── mtcnn.h ├── image ├── fbb1.jpeg ├── fbb2.jpeg ├── gyy1.jpeg └── gyy2.jpeg ├── models ├── det1.bin ├── det1.param ├── det2.bin ├── det2.param ├── det3.bin ├── det3.param ├── det4.bin ├── det4.param ├── mobilefacenet.bin └── mobilefacenet.param └── ncnn ├── include ├── benchmark.h ├── blob.h ├── cpu.h ├── layer.h ├── layer_type.h ├── layer_type_enum.h ├── mat.h ├── modelbin.h ├── net.h ├── opencv.h ├── paramdict.h └── platform.h └── lib └── libncnn.a /README.md: -------------------------------------------------------------------------------- 1 | # insightface_ncnn 2 | -------------------------------------------------------------------------------- /arcface/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | COMMON = `pkg-config --cflags opencv` 3 | LIB = ../ncnn/lib/libncnn.a 4 | LIB += `pkg-config --libs opencv` 5 | INCLUDE = -I../ncnn/include 6 | COMMON += -fopenmp -pthread -std=c++11 7 | DEPS = $(wildcard *.h) 8 | OBJ = base.o mtcnn.o arcface.o 9 | all : main 10 | main : main.cpp $(OBJ) 11 | $(CXX) $(COMMON) $(INCLUDE) $^ -o $@ $(LIB) 12 | %.o : %.cpp $(DEPS) 13 | $(CXX) $(COMMON) $(INCLUDE) -c $< -o $@ 14 | .PHONY : clean 15 | clean : 16 | rm -rf $(OBJ) main 17 | -------------------------------------------------------------------------------- /arcface/arcface.cpp: -------------------------------------------------------------------------------- 1 | #include "arcface.h" 2 | 3 | Arcface::Arcface(string model_folder) 4 | { 5 | string param_file = model_folder + "/mobilefacenet.param"; 6 | string bin_file = model_folder + "/mobilefacenet.bin"; 7 | 8 | this->net.load_param(param_file.c_str()); 9 | this->net.load_model(bin_file.c_str()); 10 | } 11 | 12 | Arcface::~Arcface() 13 | { 14 | this->net.clear(); 15 | } 16 | 17 | vector Arcface::getFeature(ncnn::Mat img) 18 | { 19 | vector feature; 20 | ncnn::Mat in = resize(img, 112, 112); 21 | in = bgr2rgb(in); 22 | ncnn::Extractor ex = net.create_extractor(); 23 | ex.set_light_mode(true); 24 | ex.input("data", in); 25 | ncnn::Mat out; 26 | ex.extract("fc1", out); 27 | feature.resize(this->feature_dim); 28 | for (int i = 0; i < this->feature_dim; i++) 29 | feature[i] = out[i]; 30 | normalize(feature); 31 | return feature; 32 | } 33 | 34 | void Arcface::normalize(vector &feature) 35 | { 36 | float sum = 0; 37 | for (auto it = feature.begin(); it != feature.end(); it++) 38 | sum += (float)*it * (float)*it; 39 | sum = sqrt(sum); 40 | for (auto it = feature.begin(); it != feature.end(); it++) 41 | *it /= sum; 42 | } 43 | 44 | ncnn::Mat preprocess(ncnn::Mat img, FaceInfo info) 45 | { 46 | int image_w = 112; //96 or 112 47 | int image_h = 112; 48 | 49 | float dst[10] = {30.2946, 65.5318, 48.0252, 33.5493, 62.7299, 50 | 51.6963, 51.5014, 71.7366, 92.3655, 92.2041}; 51 | 52 | if (image_w == 112) 53 | for (int i = 0; i < 5; i++) 54 | dst[i] += 8.0; 55 | 56 | float src[10]; 57 | for (int i = 0; i < 5; i++) 58 | { 59 | src[i] = info.landmark[2 * i]; 60 | src[i + 5] = info.landmark[2 * i + 1]; 61 | } 62 | 63 | float M[6]; 64 | getAffineMatrix(src, dst, M); 65 | ncnn::Mat out; 66 | warpAffineMatrix(img, out, M, image_w, image_h); 67 | return out; 68 | } 69 | 70 | float calcSimilar(std::vector feature1, std::vector feature2) 71 | { 72 | //assert(feature1.size() == feature2.size()); 73 | float sim = 0.0; 74 | for (int i = 0; i < feature1.size(); i++) 75 | sim += feature1[i] * feature2[i]; 76 | return sim; 77 | } 78 | -------------------------------------------------------------------------------- /arcface/arcface.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCFACE_H 2 | #define ARCFACE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "net.h" 8 | #include "base.h" 9 | 10 | using namespace std; 11 | 12 | ncnn::Mat preprocess(ncnn::Mat img, FaceInfo info); 13 | 14 | float calcSimilar(std::vector feature1, std::vector feature2); 15 | 16 | 17 | class Arcface { 18 | 19 | public: 20 | Arcface(string model_folder = "."); 21 | ~Arcface(); 22 | vector getFeature(ncnn::Mat img); 23 | 24 | private: 25 | ncnn::Net net; 26 | 27 | const int feature_dim = 128; 28 | 29 | void normalize(vector &feature); 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /arcface/base.cpp: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | ncnn::Mat resize(ncnn::Mat src, int w, int h) 4 | { 5 | int src_w = src.w; 6 | int src_h = src.h; 7 | unsigned char* u_src = new unsigned char[src_w * src_h * 3]; 8 | src.to_pixels(u_src, ncnn::Mat::PIXEL_RGB); 9 | unsigned char* u_dst = new unsigned char[w * h * 3]; 10 | ncnn::resize_bilinear_c3(u_src, src_w, src_h, u_dst, w, h); 11 | ncnn::Mat dst = ncnn::Mat::from_pixels(u_dst, ncnn::Mat::PIXEL_RGB, w, h); 12 | delete[] u_src; 13 | delete[] u_dst; 14 | return dst; 15 | } 16 | 17 | ncnn::Mat bgr2rgb(ncnn::Mat src) 18 | { 19 | int src_w = src.w; 20 | int src_h = src.h; 21 | unsigned char* u_rgb = new unsigned char[src_w * src_h * 3]; 22 | src.to_pixels(u_rgb, ncnn::Mat::PIXEL_BGR2RGB); 23 | ncnn::Mat dst = ncnn::Mat::from_pixels(u_rgb, ncnn::Mat::PIXEL_RGB, src_w, src_h); 24 | delete[] u_rgb; 25 | return dst; 26 | } 27 | 28 | ncnn::Mat rgb2bgr(ncnn::Mat src) 29 | { 30 | return bgr2rgb(src); 31 | } 32 | 33 | void getAffineMatrix(float* src_5pts, const float* dst_5pts, float* M) 34 | { 35 | float src[10], dst[10]; 36 | memcpy(src, src_5pts, sizeof(float)*10); 37 | memcpy(dst, dst_5pts, sizeof(float)*10); 38 | 39 | float ptmp[2]; 40 | ptmp[0] = ptmp[1] = 0; 41 | for (int i = 0; i < 5; ++i) { 42 | ptmp[0] += src[i]; 43 | ptmp[1] += src[5+i]; 44 | } 45 | ptmp[0] /= 5; 46 | ptmp[1] /= 5; 47 | for (int i = 0; i < 5; ++i) { 48 | src[i] -= ptmp[0]; 49 | src[5+i] -= ptmp[1]; 50 | dst[i] -= ptmp[0]; 51 | dst[5+i] -= ptmp[1]; 52 | } 53 | 54 | float dst_x = (dst[3]+dst[4]-dst[0]-dst[1])/2, dst_y = (dst[8]+dst[9]-dst[5]-dst[6])/2; 55 | float src_x = (src[3]+src[4]-src[0]-src[1])/2, src_y = (src[8]+src[9]-src[5]-src[6])/2; 56 | float theta = atan2(dst_x, dst_y) - atan2(src_x, src_y); 57 | 58 | float scale = sqrt(pow(dst_x, 2) + pow(dst_y, 2)) / sqrt(pow(src_x, 2) + pow(src_y, 2)); 59 | float pts1[10]; 60 | float pts0[2]; 61 | float _a = sin(theta), _b = cos(theta); 62 | pts0[0] = pts0[1] = 0; 63 | for (int i = 0; i < 5; ++i) { 64 | pts1[i] = scale*(src[i]*_b + src[i+5]*_a); 65 | pts1[i+5] = scale*(-src[i]*_a + src[i+5]*_b); 66 | pts0[0] += (dst[i] - pts1[i]); 67 | pts0[1] += (dst[i+5] - pts1[i+5]); 68 | } 69 | pts0[0] /= 5; 70 | pts0[1] /= 5; 71 | 72 | float sqloss = 0; 73 | for (int i = 0; i < 5; ++i) { 74 | sqloss += ((pts0[0]+pts1[i]-dst[i])*(pts0[0]+pts1[i]-dst[i]) 75 | + (pts0[1]+pts1[i+5]-dst[i+5])*(pts0[1]+pts1[i+5]-dst[i+5])); 76 | } 77 | 78 | float square_sum = 0; 79 | for (int i = 0; i < 10; ++i) { 80 | square_sum += src[i]*src[i]; 81 | } 82 | for (int t = 0; t < 200; ++t) { 83 | _a = 0; 84 | _b = 0; 85 | for (int i = 0; i < 5; ++i) { 86 | _a += ((pts0[0]-dst[i])*src[i+5] - (pts0[1]-dst[i+5])*src[i]); 87 | _b += ((pts0[0]-dst[i])*src[i] + (pts0[1]-dst[i+5])*src[i+5]); 88 | } 89 | if (_b < 0) { 90 | _b = -_b; 91 | _a = -_a; 92 | } 93 | float _s = sqrt(_a*_a + _b*_b); 94 | _b /= _s; 95 | _a /= _s; 96 | 97 | for (int i = 0; i < 5; ++i) { 98 | pts1[i] = scale*(src[i]*_b + src[i+5]*_a); 99 | pts1[i+5] = scale*(-src[i]*_a + src[i+5]*_b); 100 | } 101 | 102 | float _scale = 0; 103 | for (int i = 0; i < 5; ++i) { 104 | _scale += ((dst[i]-pts0[0])*pts1[i] + (dst[i+5]-pts0[1])*pts1[i+5]); 105 | } 106 | _scale /= (square_sum*scale); 107 | for (int i = 0; i < 10; ++i) { 108 | pts1[i] *= (_scale / scale); 109 | } 110 | scale = _scale; 111 | 112 | pts0[0] = pts0[1] = 0; 113 | for (int i = 0; i < 5; ++i) { 114 | pts0[0] += (dst[i] - pts1[i]); 115 | pts0[1] += (dst[i+5] - pts1[i+5]); 116 | } 117 | pts0[0] /= 5; 118 | pts0[1] /= 5; 119 | 120 | float _sqloss = 0; 121 | for (int i = 0; i < 5; ++i) { 122 | _sqloss += ((pts0[0]+pts1[i]-dst[i])*(pts0[0]+pts1[i]-dst[i]) 123 | + (pts0[1]+pts1[i+5]-dst[i+5])*(pts0[1]+pts1[i+5]-dst[i+5])); 124 | } 125 | if (abs(_sqloss - sqloss) < 1e-2) { 126 | break; 127 | } 128 | sqloss = _sqloss; 129 | } 130 | 131 | for (int i = 0; i < 5; ++i) { 132 | pts1[i] += (pts0[0] + ptmp[0]); 133 | pts1[i+5] += (pts0[1] + ptmp[1]); 134 | } 135 | 136 | M[0] = _b*scale; 137 | M[1] = _a*scale; 138 | M[3] = -_a*scale; 139 | M[4] = _b*scale; 140 | M[2] = pts0[0] + ptmp[0] - scale*(ptmp[0]*_b + ptmp[1]*_a); 141 | M[5] = pts0[1] + ptmp[1] - scale*(-ptmp[0]*_a + ptmp[1]*_b); 142 | } 143 | 144 | void warpAffineMatrix(ncnn::Mat src, ncnn::Mat &dst, float *M, int dst_w, int dst_h) 145 | { 146 | int src_w = src.w; 147 | int src_h = src.h; 148 | 149 | unsigned char * src_u = new unsigned char[src_w * src_h * 3]{0}; 150 | unsigned char * dst_u = new unsigned char[dst_w * dst_h * 3]{0}; 151 | 152 | src.to_pixels(src_u, ncnn::Mat::PIXEL_RGB); 153 | 154 | float m[6]; 155 | for (int i = 0; i < 6; i++) 156 | m[i] = M[i]; 157 | float D = m[0] * m[4] - m[1] * m[3]; 158 | D = D != 0 ? 1./D : 0; 159 | float A11 = m[4] * D, A22 = m[0] * D; 160 | m[0] = A11; m[1] *= -D; 161 | m[3] *= -D; m[4] = A22; 162 | float b1 = -m[0] * m[2] - m[1] * m[5]; 163 | float b2 = -m[3] * m[2] - m[4] * m[5]; 164 | m[2] = b1; m[5] = b2; 165 | 166 | for (int y= 0; y < dst_h; y++) 167 | { 168 | for (int x = 0; x < dst_w; x++) 169 | { 170 | float fx = m[0] * x + m[1] * y + m[2]; 171 | float fy = m[3] * x + m[4] * y + m[5]; 172 | 173 | int sy = (int)floor(fy); 174 | fy -= sy; 175 | if (sy < 0 || sy >= src_h) continue; 176 | 177 | short cbufy[2]; 178 | cbufy[0] = (short)((1.f - fy) * 2048); 179 | cbufy[1] = 2048 - cbufy[0]; 180 | 181 | int sx = (int)floor(fx); 182 | fx -= sx; 183 | if (sx < 0 || sx >= src_w) continue; 184 | 185 | short cbufx[2]; 186 | cbufx[0] = (short)((1.f - fx) * 2048); 187 | cbufx[1] = 2048 - cbufx[0]; 188 | 189 | if (sy == src_h - 1 || sx == src_w - 1) 190 | continue; 191 | for (int c = 0; c < 3; c++) 192 | { 193 | dst_u[3 * (y * dst_w + x) + c] = 194 | ( 195 | src_u[3 * (sy * src_w + sx) + c] * cbufx[0] * cbufy[0] + 196 | src_u[3 * ((sy + 1) * src_w + sx) + c] * cbufx[0] * cbufy[1] + 197 | src_u[3 * (sy * src_w + sx + 1) + c] * cbufx[1] * cbufy[0] + 198 | src_u[3 * ((sy + 1) * src_w + sx + 1) + c] * cbufx[1] * cbufy[1] 199 | ) >> 22; 200 | } 201 | } 202 | } 203 | 204 | dst = ncnn::Mat::from_pixels(dst_u, ncnn::Mat::PIXEL_BGR, dst_w, dst_h); 205 | delete[] src_u; 206 | delete[] dst_u; 207 | } 208 | -------------------------------------------------------------------------------- /arcface/base.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE_H 2 | #define BASE_H 3 | #include 4 | #include 5 | #include "net.h" 6 | 7 | typedef struct FaceInfo { 8 | float score; 9 | int x[2]; 10 | int y[2]; 11 | float area; 12 | float regreCoord[4]; 13 | int landmark[10]; 14 | } FaceInfo; 15 | 16 | ncnn::Mat resize(ncnn::Mat src, int w, int h); 17 | 18 | ncnn::Mat bgr2rgb(ncnn::Mat src); 19 | 20 | ncnn::Mat rgb2bgr(ncnn::Mat src); 21 | 22 | void getAffineMatrix(float* src_5pts, const float* dst_5pts, float* M); 23 | 24 | void warpAffineMatrix(ncnn::Mat src, ncnn::Mat &dst, float *M, int dst_w, int dst_h); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /arcface/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arcface.h" 5 | #include "mtcnn.h" 6 | using namespace cv; 7 | using namespace std; 8 | 9 | cv::Mat ncnn2cv(ncnn::Mat img) 10 | { 11 | unsigned char pix[img.h * img.w * 3]; 12 | img.to_pixels(pix, ncnn::Mat::PIXEL_BGR); 13 | cv::Mat cv_img(img.h, img.w, CV_8UC3); 14 | for (int i = 0; i < cv_img.rows; i++) 15 | { 16 | for (int j = 0; j < cv_img.cols; j++) 17 | { 18 | cv_img.at(i,j)[0] = pix[3 * (i * cv_img.cols + j)]; 19 | cv_img.at(i,j)[1] = pix[3 * (i * cv_img.cols + j) + 1]; 20 | cv_img.at(i,j)[2] = pix[3 * (i * cv_img.cols + j) + 2]; 21 | } 22 | } 23 | return cv_img; 24 | } 25 | 26 | int main(int argc, char* argv[]) 27 | { 28 | Mat img1; 29 | Mat img2; 30 | if (argc == 3) 31 | { 32 | img1 = imread(argv[1]); 33 | img2 = imread(argv[2]); 34 | } 35 | else{ 36 | img1 = imread("../image/gyy1.jpeg"); 37 | img2 = imread("../image/gyy2.jpeg"); 38 | } 39 | ncnn::Mat ncnn_img1 = ncnn::Mat::from_pixels(img1.data, ncnn::Mat::PIXEL_BGR, img1.cols, img1.rows); 40 | ncnn::Mat ncnn_img2 = ncnn::Mat::from_pixels(img2.data, ncnn::Mat::PIXEL_BGR, img2.cols, img2.rows); 41 | 42 | MtcnnDetector detector("../models"); 43 | 44 | double start = (double)getTickCount(); 45 | vector results1 = detector.Detect(ncnn_img1); 46 | cout << "Detection Time: " << (getTickCount() - start) / getTickFrequency() << "s" << std::endl; 47 | 48 | start = (double)getTickCount(); 49 | vector results2 = detector.Detect(ncnn_img2); 50 | cout << "Detection Time: " << (getTickCount() - start) / getTickFrequency() << "s" << std::endl; 51 | 52 | ncnn::Mat det1 = preprocess(ncnn_img1, results1[0]); 53 | ncnn::Mat det2 = preprocess(ncnn_img2, results2[0]); 54 | 55 | //for (auto it = results1.begin(); it != results1.end(); it++) 56 | //{ 57 | // rectangle(img1, cv::Point(it->x[0], it->y[0]), cv::Point(it->x[1], it->y[1]), cv::Scalar(0, 255, 0), 2); 58 | // circle(img1, cv::Point(it->landmark[0], it->landmark[1]), 2, cv::Scalar(0, 255, 0), 2); 59 | // circle(img1, cv::Point(it->landmark[2], it->landmark[3]), 2, cv::Scalar(0, 255, 0), 2); 60 | // circle(img1, cv::Point(it->landmark[4], it->landmark[5]), 2, cv::Scalar(0, 255, 0), 2); 61 | // circle(img1, cv::Point(it->landmark[6], it->landmark[7]), 2, cv::Scalar(0, 255, 0), 2); 62 | // circle(img1, cv::Point(it->landmark[8], it->landmark[9]), 2, cv::Scalar(0, 255, 0), 2); 63 | //} 64 | 65 | //for (auto it = results2.begin(); it != results2.end(); it++) 66 | //{ 67 | // rectangle(img2, cv::Point(it->x[0], it->y[0]), cv::Point(it->x[1], it->y[1]), cv::Scalar(0, 255, 0), 2); 68 | // circle(img2, cv::Point(it->landmark[0], it->landmark[1]), 2, cv::Scalar(0, 255, 0), 2); 69 | // circle(img2, cv::Point(it->landmark[2], it->landmark[3]), 2, cv::Scalar(0, 255, 0), 2); 70 | // circle(img2, cv::Point(it->landmark[4], it->landmark[5]), 2, cv::Scalar(0, 255, 0), 2); 71 | // circle(img2, cv::Point(it->landmark[6], it->landmark[7]), 2, cv::Scalar(0, 255, 0), 2); 72 | // circle(img2, cv::Point(it->landmark[8], it->landmark[9]), 2, cv::Scalar(0, 255, 0), 2); 73 | //} 74 | 75 | Arcface arc("../models"); 76 | 77 | start = (double)getTickCount(); 78 | vector feature1 = arc.getFeature(det1); 79 | cout << "Extraction Time: " << (getTickCount() - start) / getTickFrequency() << "s" << std::endl; 80 | 81 | start = (double)getTickCount(); 82 | vector feature2 = arc.getFeature(det2); 83 | cout << "Extraction Time: " << (getTickCount() - start) / getTickFrequency() << "s" << std::endl; 84 | 85 | std::cout << "Similarity: " << calcSimilar(feature1, feature2) << std::endl;; 86 | 87 | //imshow("img1", img1); 88 | //imshow("img2", img2); 89 | 90 | imshow("det1", ncnn2cv(det1)); 91 | imshow("det2", ncnn2cv(det2)); 92 | 93 | waitKey(0); 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /arcface/mtcnn.cpp: -------------------------------------------------------------------------------- 1 | #include "mtcnn.h" 2 | 3 | MtcnnDetector::MtcnnDetector(string model_folder) 4 | { 5 | vector param_files = { 6 | model_folder + "/det1.param", 7 | model_folder + "/det2.param", 8 | model_folder + "/det3.param", 9 | model_folder + "/det4.param" 10 | }; 11 | vector bin_files = { 12 | model_folder + "/det1.bin", 13 | model_folder + "/det2.bin", 14 | model_folder + "/det3.bin", 15 | model_folder + "/det4.bin" 16 | }; 17 | this->Pnet.load_param(param_files[0].c_str()); 18 | this->Pnet.load_model(bin_files[0].c_str()); 19 | this->Rnet.load_param(param_files[1].c_str()); 20 | this->Rnet.load_model(bin_files[1].c_str()); 21 | this->Onet.load_param(param_files[2].c_str()); 22 | this->Onet.load_model(bin_files[2].c_str()); 23 | this->Lnet.load_param(param_files[3].c_str()); 24 | this->Lnet.load_model(bin_files[3].c_str()); 25 | } 26 | 27 | MtcnnDetector::~MtcnnDetector() 28 | { 29 | this->Pnet.clear(); 30 | this->Rnet.clear(); 31 | this->Onet.clear(); 32 | this->Lnet.clear(); 33 | } 34 | 35 | vector MtcnnDetector::Detect(ncnn::Mat img) 36 | { 37 | int img_w = img.w; 38 | int img_h = img.h; 39 | 40 | vector pnet_results = Pnet_Detect(img); 41 | doNms(pnet_results, 0.7, "union"); 42 | refine(pnet_results, img_h, img_w, true); 43 | 44 | vector rnet_results = Rnet_Detect(img, pnet_results); 45 | doNms(rnet_results, 0.7, "union"); 46 | refine(rnet_results, img_h, img_w, true); 47 | 48 | vector onet_results = Onet_Detect(img, rnet_results); 49 | refine(onet_results, img_h, img_w, false); 50 | doNms(onet_results, 0.7, "min"); 51 | 52 | Lnet_Detect(img, onet_results); 53 | 54 | return onet_results; 55 | } 56 | 57 | vector MtcnnDetector::Pnet_Detect(ncnn::Mat img) 58 | { 59 | vector results; 60 | int img_w = img.w; 61 | int img_h = img.h; 62 | float minl = img_w < img_h ? img_w : img_h; 63 | double scale = 12.0 / this->minsize; 64 | minl *= scale; 65 | vector scales; 66 | while (minl > 12) 67 | { 68 | scales.push_back(scale); 69 | minl *= this->factor; 70 | scale *= this->factor; 71 | } 72 | for (auto it = scales.begin(); it != scales.end(); it++) 73 | { 74 | scale = (double)(*it); 75 | int hs = (int) ceil(img_h * scale); 76 | int ws = (int) ceil(img_w * scale); 77 | ncnn::Mat in = resize(img, ws, hs); 78 | in.substract_mean_normalize(this->mean_vals, this->norm_vals); 79 | ncnn::Extractor ex = Pnet.create_extractor(); 80 | ex.set_light_mode(true); 81 | ex.input("data", in); 82 | ncnn::Mat score; 83 | ncnn::Mat location; 84 | ex.extract("prob1", score); 85 | ex.extract("conv4_2", location); 86 | vector bboxs = generateBbox(score, location, *it, this->threshold[0]); 87 | doNms(bboxs, 0.5, "union"); 88 | results.insert(results.end(), bboxs.begin(), bboxs.end()); 89 | } 90 | return results; 91 | } 92 | 93 | vector MtcnnDetector::Rnet_Detect(ncnn::Mat img, vector bboxs) 94 | { 95 | vector results; 96 | 97 | int img_w = img.w; 98 | int img_h = img.h; 99 | 100 | for (auto it = bboxs.begin(); it != bboxs.end(); it++) 101 | { 102 | ncnn::Mat img_t; 103 | copy_cut_border(img, img_t, it->y[0], img_h - it->y[1], it->x[0], img_w - it->x[1]); 104 | ncnn::Mat in = resize(img_t, 24, 24); 105 | in.substract_mean_normalize(this->mean_vals, this->norm_vals); 106 | ncnn::Extractor ex = Rnet.create_extractor(); 107 | ex.set_light_mode(true); 108 | ex.input("data", in); 109 | ncnn::Mat score, bbox; 110 | ex.extract("prob1", score); 111 | ex.extract("conv5_2", bbox); 112 | if ((float)score[1] > threshold[1]) 113 | { 114 | for (int c = 0; c < 4; c++) 115 | { 116 | it->regreCoord[c] = (float)bbox[c]; 117 | } 118 | it->score = (float)score[1]; 119 | results.push_back(*it); 120 | } 121 | } 122 | return results; 123 | } 124 | 125 | vector MtcnnDetector::Onet_Detect(ncnn::Mat img, vector bboxs) 126 | { 127 | vector results; 128 | 129 | int img_w = img.w; 130 | int img_h = img.h; 131 | 132 | for (auto it = bboxs.begin(); it != bboxs.end(); it++) 133 | { 134 | ncnn::Mat img_t; 135 | copy_cut_border(img, img_t, it->y[0], img_h - it->y[1], it->x[0], img_w - it->x[1]); 136 | ncnn::Mat in = resize(img_t, 48, 48); 137 | in.substract_mean_normalize(this->mean_vals, this->norm_vals); 138 | ncnn::Extractor ex = Onet.create_extractor(); 139 | ex.set_light_mode(true); 140 | ex.input("data", in); 141 | ncnn::Mat score, bbox, point; 142 | ex.extract("prob1", score); 143 | ex.extract("conv6_2", bbox); 144 | ex.extract("conv6_3", point); 145 | if ((float)score[1] > threshold[2]) 146 | { 147 | for (int c = 0; c < 4; c++) 148 | { 149 | it->regreCoord[c] = (float)bbox[c]; 150 | } 151 | for (int p = 0; p < 5; p++) 152 | { 153 | it->landmark[2 * p] = it->x[0] + (it->x[1] - it->x[0]) * point[p]; 154 | it->landmark[2 * p + 1] = it->y[0] + (it->y[1] - it->y[0]) * point[p + 5]; 155 | } 156 | it->score = (float)score[1]; 157 | results.push_back(*it); 158 | } 159 | } 160 | return results; 161 | } 162 | 163 | void MtcnnDetector::Lnet_Detect(ncnn::Mat img, vector &bboxes) 164 | { 165 | int img_w = img.w; 166 | int img_h = img.h; 167 | 168 | for (auto it = bboxes.begin(); it != bboxes.end(); it++) 169 | { 170 | int w = it->x[1] - it->x[0] + 1; 171 | int h = it->y[1] - it->y[0] + 1; 172 | int m = w > h ? w : h; 173 | m = (int)round(m * 0.25); 174 | if (m % 2 == 1) m++; 175 | m /= 2; 176 | 177 | ncnn::Mat in(24, 24, 15); 178 | 179 | for (int i = 0; i < 5; i++) 180 | { 181 | int px = it->landmark[2 * i]; 182 | int py = it->landmark[2 * i + 1]; 183 | ncnn::Mat cut; 184 | copy_cut_border(img, cut, py - m, img_h - py - m, px - m, img_w - px - m); 185 | ncnn::Mat resized = resize(cut, 24, 24); 186 | resized.substract_mean_normalize(this->mean_vals, this->norm_vals); 187 | for (int j = 0; j < 3; j++) 188 | memcpy(in.channel(3 * i + j), resized.channel(j), 24 * 24 * sizeof(float)); 189 | } 190 | 191 | ncnn::Extractor ex = Lnet.create_extractor(); 192 | ex.set_light_mode(true); 193 | ex.input("data", in); 194 | ncnn::Mat out1, out2, out3, out4, out5; 195 | 196 | ex.extract("fc5_1", out1); 197 | ex.extract("fc5_2", out2); 198 | ex.extract("fc5_3", out3); 199 | ex.extract("fc5_4", out4); 200 | ex.extract("fc5_5", out5); 201 | 202 | if (abs(out1[0] - 0.5) > 0.35) out1[0] = 0.5f; 203 | if (abs(out1[1] - 0.5) > 0.35) out1[1] = 0.5f; 204 | if (abs(out2[0] - 0.5) > 0.35) out2[0] = 0.5f; 205 | if (abs(out2[1] - 0.5) > 0.35) out2[1] = 0.5f; 206 | if (abs(out3[0] - 0.5) > 0.35) out3[0] = 0.5f; 207 | if (abs(out3[1] - 0.5) > 0.35) out3[1] = 0.5f; 208 | if (abs(out4[0] - 0.5) > 0.35) out4[0] = 0.5f; 209 | if (abs(out4[1] - 0.5) > 0.35) out4[1] = 0.5f; 210 | if (abs(out5[0] - 0.5) > 0.35) out5[0] = 0.5f; 211 | if (abs(out5[1] - 0.5) > 0.35) out5[1] = 0.5f; 212 | 213 | it->landmark[0] += (int)round((out1[0] - 0.5) * m * 2); 214 | it->landmark[1] += (int)round((out1[1] - 0.5) * m * 2); 215 | it->landmark[2] += (int)round((out2[0] - 0.5) * m * 2); 216 | it->landmark[3] += (int)round((out2[1] - 0.5) * m * 2); 217 | it->landmark[4] += (int)round((out3[0] - 0.5) * m * 2); 218 | it->landmark[5] += (int)round((out3[1] - 0.5) * m * 2); 219 | it->landmark[6] += (int)round((out4[0] - 0.5) * m * 2); 220 | it->landmark[7] += (int)round((out4[1] - 0.5) * m * 2); 221 | it->landmark[8] += (int)round((out5[0] - 0.5) * m * 2); 222 | it->landmark[9] += (int)round((out5[1] - 0.5) * m * 2); 223 | } 224 | } 225 | 226 | vector MtcnnDetector::generateBbox(ncnn::Mat score, ncnn::Mat loc, float scale, float thresh) 227 | { 228 | int stride = 2; 229 | int cellsize = 12; 230 | float *p = score.channel(1); 231 | float inv_scale = 1.0f / scale; 232 | vector results; 233 | for (int row = 0; row < score.h; row++) 234 | { 235 | for (int col = 0; col < score.w; col++) 236 | { 237 | if (*p > thresh) 238 | { 239 | FaceInfo box; 240 | box.score = *p; 241 | box.x[0] = round((stride * col + 1) * inv_scale); 242 | box.y[0] = round((stride * row + 1) * inv_scale); 243 | box.x[1] = round((stride * col + 1 + cellsize) * inv_scale); 244 | box.y[1] = round((stride * row + 1 + cellsize) * inv_scale); 245 | box.area = (box.x[1] - box.x[0]) * (box.y[1] - box.y[0]); 246 | int index = row * score.w + col; 247 | for (int c = 0; c < 4; c++) 248 | box.regreCoord[c] = loc.channel(c)[index]; 249 | results.push_back(box); 250 | } 251 | p++; 252 | } 253 | } 254 | return results; 255 | } 256 | 257 | bool cmpScore(FaceInfo x, FaceInfo y) 258 | { 259 | if (x.score > y.score) 260 | return true; 261 | else 262 | return false; 263 | } 264 | 265 | float calcIOU(FaceInfo box1, FaceInfo box2, string mode) 266 | { 267 | int maxX = max(box1.x[0], box2.x[0]); 268 | int maxY = max(box1.y[0], box2.y[0]); 269 | int minX = min(box1.x[1], box2.x[1]); 270 | int minY = min(box1.y[1], box2.y[1]); 271 | int width = ((minX - maxX + 1) > 0) ? (minX - maxX + 1) : 0; 272 | int height = ((minY - maxY + 1) > 0) ? (minY - maxY + 1) : 0; 273 | int inter = width * height; 274 | if (!mode.compare("union")) 275 | return float(inter) / (box1.area + box2.area - float(inter)); 276 | else if (!mode.compare("min")) 277 | return float(inter) / (box1.area < box2.area ? box1.area : box2.area); 278 | else 279 | return 0; 280 | } 281 | 282 | void MtcnnDetector::doNms(vector &bboxs, float nms_thresh, string mode) 283 | { 284 | if (bboxs.empty()) 285 | return; 286 | sort(bboxs.begin(), bboxs.end(), cmpScore); 287 | for (int i = 0; i < bboxs.size(); i++) 288 | if (bboxs[i].score > 0) 289 | for (int j = i + 1; j < bboxs.size(); j++) 290 | if (bboxs[j].score > 0) 291 | { 292 | float iou = calcIOU(bboxs[i], bboxs[j], mode); 293 | if (iou > nms_thresh) 294 | bboxs[j].score = 0; 295 | } 296 | for (auto it = bboxs.begin(); it != bboxs.end();) 297 | if ((*it).score == 0) 298 | bboxs.erase(it); 299 | else 300 | it++; 301 | } 302 | 303 | void MtcnnDetector::refine(vector &bboxs, int height, int width, bool flag) 304 | { 305 | if (bboxs.empty()) 306 | return; 307 | for (auto it = bboxs.begin(); it != bboxs.end(); it++) 308 | { 309 | float bw = it->x[1] - it->x[0] + 1; 310 | float bh = it->y[1] - it->y[0] + 1; 311 | float x0 = it->x[0] + it->regreCoord[0] * bw; 312 | float y0 = it->y[0] + it->regreCoord[1] * bh; 313 | float x1 = it->x[1] + it->regreCoord[2] * bw; 314 | float y1 = it->y[1] + it->regreCoord[3] * bh; 315 | 316 | if (flag) 317 | { 318 | float w = x1 - x0 + 1; 319 | float h = y1 - y0 + 1; 320 | float m = (h > w) ? h : w; 321 | x0 = x0 + w * 0.5 - m * 0.5; 322 | y0 = y0 + h * 0.5 - m * 0.5; 323 | x1 = x0 + m - 1; 324 | y1 = y0 + m - 1; 325 | } 326 | it->x[0] = round(x0); 327 | it->y[0] = round(y0); 328 | it->x[1] = round(x1); 329 | it->y[1] = round(y1); 330 | 331 | if (it->x[0] < 0) it->x[0] = 0; 332 | if (it->y[0] < 0) it->y[0] = 0; 333 | if (it->x[1] > width) it->x[1] = width - 1; 334 | if (it->y[1] > height) it->y[1] = height - 1; 335 | 336 | it->area = (it->x[1] - it->x[0]) * (it->y[1] - it->y[0]); 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /arcface/mtcnn.h: -------------------------------------------------------------------------------- 1 | #ifndef MTCNN_H 2 | #define MTCNN_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "net.h" 10 | #include "base.h" 11 | 12 | using namespace std; 13 | 14 | class MtcnnDetector { 15 | public: 16 | MtcnnDetector(string model_folder = "."); 17 | ~MtcnnDetector(); 18 | vector Detect(ncnn::Mat img); 19 | private: 20 | float minsize = 20; 21 | float threshold[3] = {0.6f, 0.7f, 0.8f}; 22 | float factor = 0.709f; 23 | const float mean_vals[3] = {127.5f, 127.5f, 127.5f}; 24 | const float norm_vals[3] = {0.0078125f, 0.0078125f, 0.0078125f}; 25 | ncnn::Net Pnet; 26 | ncnn::Net Rnet; 27 | ncnn::Net Onet; 28 | ncnn::Net Lnet; 29 | vector Pnet_Detect(ncnn::Mat img); 30 | vector Rnet_Detect(ncnn::Mat img, vector bboxs); 31 | vector Onet_Detect(ncnn::Mat img, vector bboxs); 32 | void Lnet_Detect(ncnn::Mat img, vector &bboxs); 33 | vector generateBbox(ncnn::Mat score, ncnn::Mat loc, float scale, float thresh); 34 | void doNms(vector &bboxs, float nms_thresh, string mode); 35 | void refine(vector &bboxs, int height, int width, bool flag = false); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /image/fbb1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/image/fbb1.jpeg -------------------------------------------------------------------------------- /image/fbb2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/image/fbb2.jpeg -------------------------------------------------------------------------------- /image/gyy1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/image/gyy1.jpeg -------------------------------------------------------------------------------- /image/gyy2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/image/gyy2.jpeg -------------------------------------------------------------------------------- /models/det1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/models/det1.bin -------------------------------------------------------------------------------- /models/det1.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 12 13 3 | Input data 0 1 data 4 | Convolution conv1 1 1 data conv1 0=10 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=270 5 | PReLU prelu1 1 1 conv1 prelu1 0=10 6 | Pooling pool1 1 1 prelu1 pool1 0=0 1=2 2=2 3=0 4=0 5=0 7 | Convolution conv2 1 1 pool1 conv2 0=16 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=1440 8 | PReLU prelu2 1 1 conv2 prelu2 0=16 9 | Convolution conv3 1 1 prelu2 conv3 0=32 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=4608 10 | PReLU prelu3 1 1 conv3 prelu3 0=32 11 | Split splitncnn_0 1 2 prelu3 prelu3_splitncnn_0 prelu3_splitncnn_1 12 | Convolution conv4_2 1 1 prelu3_splitncnn_1 conv4_2 0=4 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=128 13 | Convolution conv4_1 1 1 prelu3_splitncnn_0 conv4_1 0=2 1=1 11=1 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=64 14 | Softmax prob1 1 1 conv4_1 prob1 15 | -------------------------------------------------------------------------------- /models/det2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/models/det2.bin -------------------------------------------------------------------------------- /models/det2.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 16 17 3 | Input data 0 1 data 4 | Convolution conv1 1 1 data conv1 0=28 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=756 5 | PReLU prelu1 1 1 conv1 prelu1 0=28 6 | Pooling pool1 1 1 prelu1 pool1 0=0 1=3 2=2 3=0 4=0 5=0 7 | Convolution conv2 1 1 pool1 conv2 0=48 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12096 8 | PReLU prelu2 1 1 conv2 prelu2 0=48 9 | Pooling pool2 1 1 prelu2 pool2 0=0 1=3 2=2 3=0 4=0 5=0 10 | Convolution conv3 1 1 pool2 conv3 0=64 1=2 11=2 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12288 11 | PReLU prelu3 1 1 conv3 prelu3 0=64 12 | InnerProduct conv4 1 1 prelu3 conv4 0=128 1=1 2=73728 13 | PReLU prelu4 1 1 conv4 prelu4 0=128 14 | Split splitncnn_0 1 2 prelu4 prelu4_splitncnn_0 prelu4_splitncnn_1 15 | InnerProduct conv5_2 1 1 prelu4_splitncnn_1 conv5_2 0=4 1=1 2=512 16 | InnerProduct conv5_1 1 1 prelu4_splitncnn_0 conv5_1 0=2 1=1 2=256 17 | Input prob1_label 0 1 prob1_label 18 | Softmax prob1 1 1 conv5_1 prob1 19 | -------------------------------------------------------------------------------- /models/det3.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/models/det3.bin -------------------------------------------------------------------------------- /models/det3.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 20 22 3 | Input data 0 1 data 4 | Convolution conv1 1 1 data conv1 0=32 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=864 5 | PReLU prelu1 1 1 conv1 prelu1 0=32 6 | Pooling pool1 1 1 prelu1 pool1 0=0 1=3 2=2 3=0 4=0 5=0 7 | Convolution conv2 1 1 pool1 conv2 0=64 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=18432 8 | PReLU prelu2 1 1 conv2 prelu2 0=64 9 | Pooling pool2 1 1 prelu2 pool2 0=0 1=3 2=2 3=0 4=0 5=0 10 | Convolution conv3 1 1 pool2 conv3 0=64 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=36864 11 | PReLU prelu3 1 1 conv3 prelu3 0=64 12 | Pooling pool3 1 1 prelu3 pool3 0=0 1=2 2=2 3=0 4=0 5=0 13 | Convolution conv4 1 1 pool3 conv4 0=128 1=2 11=2 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=32768 14 | PReLU prelu4 1 1 conv4 prelu4 0=128 15 | InnerProduct conv5 1 1 prelu4 conv5 0=256 1=1 2=294912 16 | PReLU prelu5 1 1 conv5 prelu5 0=256 17 | Split splitncnn_0 1 3 prelu5 prelu5_splitncnn_0 prelu5_splitncnn_1 prelu5_splitncnn_2 18 | InnerProduct conv6_3 1 1 prelu5_splitncnn_2 conv6_3 0=10 1=1 2=2560 19 | InnerProduct conv6_2 1 1 prelu5_splitncnn_1 conv6_2 0=4 1=1 2=1024 20 | InnerProduct conv6_1 1 1 prelu5_splitncnn_0 conv6_1 0=2 1=1 2=512 21 | Input prob1_label 0 1 prob1_label 22 | Softmax prob1 1 1 conv6_1 prob1 23 | -------------------------------------------------------------------------------- /models/det4.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/models/det4.bin -------------------------------------------------------------------------------- /models/det4.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 61 73 3 | Input data 0 1 data 4 | Slice slice 1 5 data slice slice_subncnn_1 slice_subncnn_2 slice_subncnn_3 slice_subncnn_4 -23300=5,-233,-233,-233,-233,-233 5 | Convolution conv1_1 1 1 slice conv1_1 0=28 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=756 6 | PReLU prelu1_1 1 1 conv1_1 prelu1_1 0=28 7 | Pooling pool1_1 1 1 prelu1_1 pool1_1 0=0 1=3 2=2 3=0 4=0 5=0 8 | Convolution conv2_1 1 1 pool1_1 conv2_1 0=48 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12096 9 | PReLU prelu2_1 1 1 conv2_1 prelu2_1 0=48 10 | Pooling pool2_1 1 1 prelu2_1 pool2_1 0=0 1=3 2=2 3=0 4=0 5=0 11 | Convolution conv3_1 1 1 pool2_1 conv3_1 0=64 1=2 11=2 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12288 12 | PReLU prelu3_1 1 1 conv3_1 prelu3_1 0=64 13 | Convolution conv1_2 1 1 slice_subncnn_1 conv1_2 0=28 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=756 14 | PReLU prelu1_2 1 1 conv1_2 prelu1_2 0=28 15 | Pooling pool1_2 1 1 prelu1_2 pool1_2 0=0 1=3 2=2 3=0 4=0 5=0 16 | Convolution conv2_2 1 1 pool1_2 conv2_2 0=48 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12096 17 | PReLU prelu2_2 1 1 conv2_2 prelu2_2 0=48 18 | Pooling pool2_2 1 1 prelu2_2 pool2_2 0=0 1=3 2=2 3=0 4=0 5=0 19 | Convolution conv3_2 1 1 pool2_2 conv3_2 0=64 1=2 11=2 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12288 20 | PReLU prelu3_2 1 1 conv3_2 prelu3_2 0=64 21 | Convolution conv1_3 1 1 slice_subncnn_2 conv1_3 0=28 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=756 22 | PReLU prelu1_3 1 1 conv1_3 prelu1_3 0=28 23 | Pooling pool1_3 1 1 prelu1_3 pool1_3 0=0 1=3 2=2 3=0 4=0 5=0 24 | Convolution conv2_3 1 1 pool1_3 conv2_3 0=48 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12096 25 | PReLU prelu2_3 1 1 conv2_3 prelu2_3 0=48 26 | Pooling pool2_3 1 1 prelu2_3 pool2_3 0=0 1=3 2=2 3=0 4=0 5=0 27 | Convolution conv3_3 1 1 pool2_3 conv3_3 0=64 1=2 11=2 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12288 28 | PReLU prelu3_3 1 1 conv3_3 prelu3_3 0=64 29 | Convolution conv1_4 1 1 slice_subncnn_3 conv1_4 0=28 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=756 30 | PReLU prelu1_4 1 1 conv1_4 prelu1_4 0=28 31 | Pooling pool1_4 1 1 prelu1_4 pool1_4 0=0 1=3 2=2 3=0 4=0 5=0 32 | Convolution conv2_4 1 1 pool1_4 conv2_4 0=48 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12096 33 | PReLU prelu2_4 1 1 conv2_4 prelu2_4 0=48 34 | Pooling pool2_4 1 1 prelu2_4 pool2_4 0=0 1=3 2=2 3=0 4=0 5=0 35 | Convolution conv3_4 1 1 pool2_4 conv3_4 0=64 1=2 11=2 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12288 36 | PReLU prelu3_4 1 1 conv3_4 prelu3_4 0=64 37 | Convolution conv1_5 1 1 slice_subncnn_4 conv1_5 0=28 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=756 38 | PReLU prelu1_5 1 1 conv1_5 prelu1_5 0=28 39 | Pooling pool1_5 1 1 prelu1_5 pool1_5 0=0 1=3 2=2 3=0 4=0 5=0 40 | Convolution conv2_5 1 1 pool1_5 conv2_5 0=48 1=3 11=3 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12096 41 | PReLU prelu2_5 1 1 conv2_5 prelu2_5 0=48 42 | Pooling pool2_5 1 1 prelu2_5 pool2_5 0=0 1=3 2=2 3=0 4=0 5=0 43 | Convolution conv3_5 1 1 pool2_5 conv3_5 0=64 1=2 11=2 2=1 12=1 3=1 13=1 4=0 14=0 5=1 6=12288 44 | PReLU prelu3_5 1 1 conv3_5 prelu3_5 0=64 45 | Concat concat 5 1 prelu3_1 prelu3_2 prelu3_3 prelu3_4 prelu3_5 concat 0=0 46 | InnerProduct fc4 1 1 concat fc4 0=256 1=1 2=737280 47 | PReLU prelu4 1 1 fc4 prelu4 0=256 48 | Split splitncnn_0 1 5 prelu4 prelu4_splitncnn_0 prelu4_splitncnn_1 prelu4_splitncnn_2 prelu4_splitncnn_3 prelu4_splitncnn_4 49 | InnerProduct fc4_1 1 1 prelu4_splitncnn_4 fc4_1 0=64 1=1 2=16384 50 | PReLU prelu4_1 1 1 fc4_1 prelu4_1 0=64 51 | InnerProduct fc5_1 1 1 prelu4_1 fc5_1 0=2 1=1 2=128 52 | InnerProduct fc4_2 1 1 prelu4_splitncnn_3 fc4_2 0=64 1=1 2=16384 53 | PReLU prelu4_2 1 1 fc4_2 prelu4_2 0=64 54 | InnerProduct fc5_2 1 1 prelu4_2 fc5_2 0=2 1=1 2=128 55 | InnerProduct fc4_3 1 1 prelu4_splitncnn_2 fc4_3 0=64 1=1 2=16384 56 | PReLU prelu4_3 1 1 fc4_3 prelu4_3 0=64 57 | InnerProduct fc5_3 1 1 prelu4_3 fc5_3 0=2 1=1 2=128 58 | InnerProduct fc4_4 1 1 prelu4_splitncnn_1 fc4_4 0=64 1=1 2=16384 59 | PReLU prelu4_4 1 1 fc4_4 prelu4_4 0=64 60 | InnerProduct fc5_4 1 1 prelu4_4 fc5_4 0=2 1=1 2=128 61 | InnerProduct fc4_5 1 1 prelu4_splitncnn_0 fc4_5 0=64 1=1 2=16384 62 | PReLU prelu4_5 1 1 fc4_5 prelu4_5 0=64 63 | InnerProduct fc5_5 1 1 prelu4_5 fc5_5 0=2 1=1 2=128 64 | -------------------------------------------------------------------------------- /models/mobilefacenet.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/models/mobilefacenet.bin -------------------------------------------------------------------------------- /models/mobilefacenet.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 160 172 3 | Input data 0 1 data 4 | BinaryOp _minusscalar0 1 1 data _minusscalar0 0=1 1=1 2=127.500000 5 | BinaryOp _mulscalar0 1 1 _minusscalar0 _mulscalar0 0=2 1=1 2=0.007812 6 | Convolution conv_1_conv2d 1 1 _mulscalar0 conv_1_conv2d 0=64 1=3 11=3 3=2 13=2 4=1 14=1 5=0 6=1728 7 | BatchNorm conv_1_batchnorm 1 1 conv_1_conv2d conv_1_batchnorm 0=64 8 | PReLU conv_1_relu 1 1 conv_1_batchnorm conv_1_relu 0=64 9 | ConvolutionDepthWise conv_2_dw_conv2d 1 1 conv_1_relu conv_2_dw_conv2d 0=64 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=576 7=64 10 | BatchNorm conv_2_dw_batchnorm 1 1 conv_2_dw_conv2d conv_2_dw_batchnorm 0=64 11 | PReLU conv_2_dw_relu 1 1 conv_2_dw_batchnorm conv_2_dw_relu 0=64 12 | Convolution dconv_23_conv_sep_conv2d 1 1 conv_2_dw_relu dconv_23_conv_sep_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 13 | BatchNorm dconv_23_conv_sep_batchnorm 1 1 dconv_23_conv_sep_conv2d dconv_23_conv_sep_batchnorm 0=128 14 | PReLU dconv_23_conv_sep_relu 1 1 dconv_23_conv_sep_batchnorm dconv_23_conv_sep_relu 0=128 15 | ConvolutionDepthWise dconv_23_conv_dw_conv2d 1 1 dconv_23_conv_sep_relu dconv_23_conv_dw_conv2d 0=128 1=3 11=3 3=2 13=2 4=1 14=1 5=0 6=1152 7=128 16 | BatchNorm dconv_23_conv_dw_batchnorm 1 1 dconv_23_conv_dw_conv2d dconv_23_conv_dw_batchnorm 0=128 17 | PReLU dconv_23_conv_dw_relu 1 1 dconv_23_conv_dw_batchnorm dconv_23_conv_dw_relu 0=128 18 | Convolution dconv_23_conv_proj_conv2d 1 1 dconv_23_conv_dw_relu dconv_23_conv_proj_conv2d 0=64 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 19 | BatchNorm dconv_23_conv_proj_batchnorm 1 1 dconv_23_conv_proj_conv2d dconv_23_conv_proj_batchnorm 0=64 20 | Split splitncnn_0 1 2 dconv_23_conv_proj_batchnorm dconv_23_conv_proj_batchnorm_splitncnn_0 dconv_23_conv_proj_batchnorm_splitncnn_1 21 | Convolution res_3_block0_conv_sep_conv2d 1 1 dconv_23_conv_proj_batchnorm_splitncnn_1 res_3_block0_conv_sep_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 22 | BatchNorm res_3_block0_conv_sep_batchnorm 1 1 res_3_block0_conv_sep_conv2d res_3_block0_conv_sep_batchnorm 0=128 23 | PReLU res_3_block0_conv_sep_relu 1 1 res_3_block0_conv_sep_batchnorm res_3_block0_conv_sep_relu 0=128 24 | ConvolutionDepthWise res_3_block0_conv_dw_conv2d 1 1 res_3_block0_conv_sep_relu res_3_block0_conv_dw_conv2d 0=128 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=1152 7=128 25 | BatchNorm res_3_block0_conv_dw_batchnorm 1 1 res_3_block0_conv_dw_conv2d res_3_block0_conv_dw_batchnorm 0=128 26 | PReLU res_3_block0_conv_dw_relu 1 1 res_3_block0_conv_dw_batchnorm res_3_block0_conv_dw_relu 0=128 27 | Convolution res_3_block0_conv_proj_conv2d 1 1 res_3_block0_conv_dw_relu res_3_block0_conv_proj_conv2d 0=64 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 28 | BatchNorm res_3_block0_conv_proj_batchnorm 1 1 res_3_block0_conv_proj_conv2d res_3_block0_conv_proj_batchnorm 0=64 29 | BinaryOp _plus0 2 1 res_3_block0_conv_proj_batchnorm dconv_23_conv_proj_batchnorm_splitncnn_0 _plus0 0=0 30 | Split splitncnn_1 1 2 _plus0 _plus0_splitncnn_0 _plus0_splitncnn_1 31 | Convolution res_3_block1_conv_sep_conv2d 1 1 _plus0_splitncnn_1 res_3_block1_conv_sep_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 32 | BatchNorm res_3_block1_conv_sep_batchnorm 1 1 res_3_block1_conv_sep_conv2d res_3_block1_conv_sep_batchnorm 0=128 33 | PReLU res_3_block1_conv_sep_relu 1 1 res_3_block1_conv_sep_batchnorm res_3_block1_conv_sep_relu 0=128 34 | ConvolutionDepthWise res_3_block1_conv_dw_conv2d 1 1 res_3_block1_conv_sep_relu res_3_block1_conv_dw_conv2d 0=128 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=1152 7=128 35 | BatchNorm res_3_block1_conv_dw_batchnorm 1 1 res_3_block1_conv_dw_conv2d res_3_block1_conv_dw_batchnorm 0=128 36 | PReLU res_3_block1_conv_dw_relu 1 1 res_3_block1_conv_dw_batchnorm res_3_block1_conv_dw_relu 0=128 37 | Convolution res_3_block1_conv_proj_conv2d 1 1 res_3_block1_conv_dw_relu res_3_block1_conv_proj_conv2d 0=64 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 38 | BatchNorm res_3_block1_conv_proj_batchnorm 1 1 res_3_block1_conv_proj_conv2d res_3_block1_conv_proj_batchnorm 0=64 39 | BinaryOp _plus1 2 1 res_3_block1_conv_proj_batchnorm _plus0_splitncnn_0 _plus1 0=0 40 | Split splitncnn_2 1 2 _plus1 _plus1_splitncnn_0 _plus1_splitncnn_1 41 | Convolution res_3_block2_conv_sep_conv2d 1 1 _plus1_splitncnn_1 res_3_block2_conv_sep_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 42 | BatchNorm res_3_block2_conv_sep_batchnorm 1 1 res_3_block2_conv_sep_conv2d res_3_block2_conv_sep_batchnorm 0=128 43 | PReLU res_3_block2_conv_sep_relu 1 1 res_3_block2_conv_sep_batchnorm res_3_block2_conv_sep_relu 0=128 44 | ConvolutionDepthWise res_3_block2_conv_dw_conv2d 1 1 res_3_block2_conv_sep_relu res_3_block2_conv_dw_conv2d 0=128 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=1152 7=128 45 | BatchNorm res_3_block2_conv_dw_batchnorm 1 1 res_3_block2_conv_dw_conv2d res_3_block2_conv_dw_batchnorm 0=128 46 | PReLU res_3_block2_conv_dw_relu 1 1 res_3_block2_conv_dw_batchnorm res_3_block2_conv_dw_relu 0=128 47 | Convolution res_3_block2_conv_proj_conv2d 1 1 res_3_block2_conv_dw_relu res_3_block2_conv_proj_conv2d 0=64 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 48 | BatchNorm res_3_block2_conv_proj_batchnorm 1 1 res_3_block2_conv_proj_conv2d res_3_block2_conv_proj_batchnorm 0=64 49 | BinaryOp _plus2 2 1 res_3_block2_conv_proj_batchnorm _plus1_splitncnn_0 _plus2 0=0 50 | Split splitncnn_3 1 2 _plus2 _plus2_splitncnn_0 _plus2_splitncnn_1 51 | Convolution res_3_block3_conv_sep_conv2d 1 1 _plus2_splitncnn_1 res_3_block3_conv_sep_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 52 | BatchNorm res_3_block3_conv_sep_batchnorm 1 1 res_3_block3_conv_sep_conv2d res_3_block3_conv_sep_batchnorm 0=128 53 | PReLU res_3_block3_conv_sep_relu 1 1 res_3_block3_conv_sep_batchnorm res_3_block3_conv_sep_relu 0=128 54 | ConvolutionDepthWise res_3_block3_conv_dw_conv2d 1 1 res_3_block3_conv_sep_relu res_3_block3_conv_dw_conv2d 0=128 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=1152 7=128 55 | BatchNorm res_3_block3_conv_dw_batchnorm 1 1 res_3_block3_conv_dw_conv2d res_3_block3_conv_dw_batchnorm 0=128 56 | PReLU res_3_block3_conv_dw_relu 1 1 res_3_block3_conv_dw_batchnorm res_3_block3_conv_dw_relu 0=128 57 | Convolution res_3_block3_conv_proj_conv2d 1 1 res_3_block3_conv_dw_relu res_3_block3_conv_proj_conv2d 0=64 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=8192 58 | BatchNorm res_3_block3_conv_proj_batchnorm 1 1 res_3_block3_conv_proj_conv2d res_3_block3_conv_proj_batchnorm 0=64 59 | BinaryOp _plus3 2 1 res_3_block3_conv_proj_batchnorm _plus2_splitncnn_0 _plus3 0=0 60 | Convolution dconv_34_conv_sep_conv2d 1 1 _plus3 dconv_34_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=16384 61 | BatchNorm dconv_34_conv_sep_batchnorm 1 1 dconv_34_conv_sep_conv2d dconv_34_conv_sep_batchnorm 0=256 62 | PReLU dconv_34_conv_sep_relu 1 1 dconv_34_conv_sep_batchnorm dconv_34_conv_sep_relu 0=256 63 | ConvolutionDepthWise dconv_34_conv_dw_conv2d 1 1 dconv_34_conv_sep_relu dconv_34_conv_dw_conv2d 0=256 1=3 11=3 3=2 13=2 4=1 14=1 5=0 6=2304 7=256 64 | BatchNorm dconv_34_conv_dw_batchnorm 1 1 dconv_34_conv_dw_conv2d dconv_34_conv_dw_batchnorm 0=256 65 | PReLU dconv_34_conv_dw_relu 1 1 dconv_34_conv_dw_batchnorm dconv_34_conv_dw_relu 0=256 66 | Convolution dconv_34_conv_proj_conv2d 1 1 dconv_34_conv_dw_relu dconv_34_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 67 | BatchNorm dconv_34_conv_proj_batchnorm 1 1 dconv_34_conv_proj_conv2d dconv_34_conv_proj_batchnorm 0=128 68 | Split splitncnn_4 1 2 dconv_34_conv_proj_batchnorm dconv_34_conv_proj_batchnorm_splitncnn_0 dconv_34_conv_proj_batchnorm_splitncnn_1 69 | Convolution res_4_block0_conv_sep_conv2d 1 1 dconv_34_conv_proj_batchnorm_splitncnn_1 res_4_block0_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 70 | BatchNorm res_4_block0_conv_sep_batchnorm 1 1 res_4_block0_conv_sep_conv2d res_4_block0_conv_sep_batchnorm 0=256 71 | PReLU res_4_block0_conv_sep_relu 1 1 res_4_block0_conv_sep_batchnorm res_4_block0_conv_sep_relu 0=256 72 | ConvolutionDepthWise res_4_block0_conv_dw_conv2d 1 1 res_4_block0_conv_sep_relu res_4_block0_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 73 | BatchNorm res_4_block0_conv_dw_batchnorm 1 1 res_4_block0_conv_dw_conv2d res_4_block0_conv_dw_batchnorm 0=256 74 | PReLU res_4_block0_conv_dw_relu 1 1 res_4_block0_conv_dw_batchnorm res_4_block0_conv_dw_relu 0=256 75 | Convolution res_4_block0_conv_proj_conv2d 1 1 res_4_block0_conv_dw_relu res_4_block0_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 76 | BatchNorm res_4_block0_conv_proj_batchnorm 1 1 res_4_block0_conv_proj_conv2d res_4_block0_conv_proj_batchnorm 0=128 77 | BinaryOp _plus4 2 1 res_4_block0_conv_proj_batchnorm dconv_34_conv_proj_batchnorm_splitncnn_0 _plus4 0=0 78 | Split splitncnn_5 1 2 _plus4 _plus4_splitncnn_0 _plus4_splitncnn_1 79 | Convolution res_4_block1_conv_sep_conv2d 1 1 _plus4_splitncnn_1 res_4_block1_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 80 | BatchNorm res_4_block1_conv_sep_batchnorm 1 1 res_4_block1_conv_sep_conv2d res_4_block1_conv_sep_batchnorm 0=256 81 | PReLU res_4_block1_conv_sep_relu 1 1 res_4_block1_conv_sep_batchnorm res_4_block1_conv_sep_relu 0=256 82 | ConvolutionDepthWise res_4_block1_conv_dw_conv2d 1 1 res_4_block1_conv_sep_relu res_4_block1_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 83 | BatchNorm res_4_block1_conv_dw_batchnorm 1 1 res_4_block1_conv_dw_conv2d res_4_block1_conv_dw_batchnorm 0=256 84 | PReLU res_4_block1_conv_dw_relu 1 1 res_4_block1_conv_dw_batchnorm res_4_block1_conv_dw_relu 0=256 85 | Convolution res_4_block1_conv_proj_conv2d 1 1 res_4_block1_conv_dw_relu res_4_block1_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 86 | BatchNorm res_4_block1_conv_proj_batchnorm 1 1 res_4_block1_conv_proj_conv2d res_4_block1_conv_proj_batchnorm 0=128 87 | BinaryOp _plus5 2 1 res_4_block1_conv_proj_batchnorm _plus4_splitncnn_0 _plus5 0=0 88 | Split splitncnn_6 1 2 _plus5 _plus5_splitncnn_0 _plus5_splitncnn_1 89 | Convolution res_4_block2_conv_sep_conv2d 1 1 _plus5_splitncnn_1 res_4_block2_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 90 | BatchNorm res_4_block2_conv_sep_batchnorm 1 1 res_4_block2_conv_sep_conv2d res_4_block2_conv_sep_batchnorm 0=256 91 | PReLU res_4_block2_conv_sep_relu 1 1 res_4_block2_conv_sep_batchnorm res_4_block2_conv_sep_relu 0=256 92 | ConvolutionDepthWise res_4_block2_conv_dw_conv2d 1 1 res_4_block2_conv_sep_relu res_4_block2_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 93 | BatchNorm res_4_block2_conv_dw_batchnorm 1 1 res_4_block2_conv_dw_conv2d res_4_block2_conv_dw_batchnorm 0=256 94 | PReLU res_4_block2_conv_dw_relu 1 1 res_4_block2_conv_dw_batchnorm res_4_block2_conv_dw_relu 0=256 95 | Convolution res_4_block2_conv_proj_conv2d 1 1 res_4_block2_conv_dw_relu res_4_block2_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 96 | BatchNorm res_4_block2_conv_proj_batchnorm 1 1 res_4_block2_conv_proj_conv2d res_4_block2_conv_proj_batchnorm 0=128 97 | BinaryOp _plus6 2 1 res_4_block2_conv_proj_batchnorm _plus5_splitncnn_0 _plus6 0=0 98 | Split splitncnn_7 1 2 _plus6 _plus6_splitncnn_0 _plus6_splitncnn_1 99 | Convolution res_4_block3_conv_sep_conv2d 1 1 _plus6_splitncnn_1 res_4_block3_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 100 | BatchNorm res_4_block3_conv_sep_batchnorm 1 1 res_4_block3_conv_sep_conv2d res_4_block3_conv_sep_batchnorm 0=256 101 | PReLU res_4_block3_conv_sep_relu 1 1 res_4_block3_conv_sep_batchnorm res_4_block3_conv_sep_relu 0=256 102 | ConvolutionDepthWise res_4_block3_conv_dw_conv2d 1 1 res_4_block3_conv_sep_relu res_4_block3_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 103 | BatchNorm res_4_block3_conv_dw_batchnorm 1 1 res_4_block3_conv_dw_conv2d res_4_block3_conv_dw_batchnorm 0=256 104 | PReLU res_4_block3_conv_dw_relu 1 1 res_4_block3_conv_dw_batchnorm res_4_block3_conv_dw_relu 0=256 105 | Convolution res_4_block3_conv_proj_conv2d 1 1 res_4_block3_conv_dw_relu res_4_block3_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 106 | BatchNorm res_4_block3_conv_proj_batchnorm 1 1 res_4_block3_conv_proj_conv2d res_4_block3_conv_proj_batchnorm 0=128 107 | BinaryOp _plus7 2 1 res_4_block3_conv_proj_batchnorm _plus6_splitncnn_0 _plus7 0=0 108 | Split splitncnn_8 1 2 _plus7 _plus7_splitncnn_0 _plus7_splitncnn_1 109 | Convolution res_4_block4_conv_sep_conv2d 1 1 _plus7_splitncnn_1 res_4_block4_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 110 | BatchNorm res_4_block4_conv_sep_batchnorm 1 1 res_4_block4_conv_sep_conv2d res_4_block4_conv_sep_batchnorm 0=256 111 | PReLU res_4_block4_conv_sep_relu 1 1 res_4_block4_conv_sep_batchnorm res_4_block4_conv_sep_relu 0=256 112 | ConvolutionDepthWise res_4_block4_conv_dw_conv2d 1 1 res_4_block4_conv_sep_relu res_4_block4_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 113 | BatchNorm res_4_block4_conv_dw_batchnorm 1 1 res_4_block4_conv_dw_conv2d res_4_block4_conv_dw_batchnorm 0=256 114 | PReLU res_4_block4_conv_dw_relu 1 1 res_4_block4_conv_dw_batchnorm res_4_block4_conv_dw_relu 0=256 115 | Convolution res_4_block4_conv_proj_conv2d 1 1 res_4_block4_conv_dw_relu res_4_block4_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 116 | BatchNorm res_4_block4_conv_proj_batchnorm 1 1 res_4_block4_conv_proj_conv2d res_4_block4_conv_proj_batchnorm 0=128 117 | BinaryOp _plus8 2 1 res_4_block4_conv_proj_batchnorm _plus7_splitncnn_0 _plus8 0=0 118 | Split splitncnn_9 1 2 _plus8 _plus8_splitncnn_0 _plus8_splitncnn_1 119 | Convolution res_4_block5_conv_sep_conv2d 1 1 _plus8_splitncnn_1 res_4_block5_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 120 | BatchNorm res_4_block5_conv_sep_batchnorm 1 1 res_4_block5_conv_sep_conv2d res_4_block5_conv_sep_batchnorm 0=256 121 | PReLU res_4_block5_conv_sep_relu 1 1 res_4_block5_conv_sep_batchnorm res_4_block5_conv_sep_relu 0=256 122 | ConvolutionDepthWise res_4_block5_conv_dw_conv2d 1 1 res_4_block5_conv_sep_relu res_4_block5_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 123 | BatchNorm res_4_block5_conv_dw_batchnorm 1 1 res_4_block5_conv_dw_conv2d res_4_block5_conv_dw_batchnorm 0=256 124 | PReLU res_4_block5_conv_dw_relu 1 1 res_4_block5_conv_dw_batchnorm res_4_block5_conv_dw_relu 0=256 125 | Convolution res_4_block5_conv_proj_conv2d 1 1 res_4_block5_conv_dw_relu res_4_block5_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 126 | BatchNorm res_4_block5_conv_proj_batchnorm 1 1 res_4_block5_conv_proj_conv2d res_4_block5_conv_proj_batchnorm 0=128 127 | BinaryOp _plus9 2 1 res_4_block5_conv_proj_batchnorm _plus8_splitncnn_0 _plus9 0=0 128 | Convolution dconv_45_conv_sep_conv2d 1 1 _plus9 dconv_45_conv_sep_conv2d 0=512 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=65536 129 | BatchNorm dconv_45_conv_sep_batchnorm 1 1 dconv_45_conv_sep_conv2d dconv_45_conv_sep_batchnorm 0=512 130 | PReLU dconv_45_conv_sep_relu 1 1 dconv_45_conv_sep_batchnorm dconv_45_conv_sep_relu 0=512 131 | ConvolutionDepthWise dconv_45_conv_dw_conv2d 1 1 dconv_45_conv_sep_relu dconv_45_conv_dw_conv2d 0=512 1=3 11=3 3=2 13=2 4=1 14=1 5=0 6=4608 7=512 132 | BatchNorm dconv_45_conv_dw_batchnorm 1 1 dconv_45_conv_dw_conv2d dconv_45_conv_dw_batchnorm 0=512 133 | PReLU dconv_45_conv_dw_relu 1 1 dconv_45_conv_dw_batchnorm dconv_45_conv_dw_relu 0=512 134 | Convolution dconv_45_conv_proj_conv2d 1 1 dconv_45_conv_dw_relu dconv_45_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=65536 135 | BatchNorm dconv_45_conv_proj_batchnorm 1 1 dconv_45_conv_proj_conv2d dconv_45_conv_proj_batchnorm 0=128 136 | Split splitncnn_10 1 2 dconv_45_conv_proj_batchnorm dconv_45_conv_proj_batchnorm_splitncnn_0 dconv_45_conv_proj_batchnorm_splitncnn_1 137 | Convolution res_5_block0_conv_sep_conv2d 1 1 dconv_45_conv_proj_batchnorm_splitncnn_1 res_5_block0_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 138 | BatchNorm res_5_block0_conv_sep_batchnorm 1 1 res_5_block0_conv_sep_conv2d res_5_block0_conv_sep_batchnorm 0=256 139 | PReLU res_5_block0_conv_sep_relu 1 1 res_5_block0_conv_sep_batchnorm res_5_block0_conv_sep_relu 0=256 140 | ConvolutionDepthWise res_5_block0_conv_dw_conv2d 1 1 res_5_block0_conv_sep_relu res_5_block0_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 141 | BatchNorm res_5_block0_conv_dw_batchnorm 1 1 res_5_block0_conv_dw_conv2d res_5_block0_conv_dw_batchnorm 0=256 142 | PReLU res_5_block0_conv_dw_relu 1 1 res_5_block0_conv_dw_batchnorm res_5_block0_conv_dw_relu 0=256 143 | Convolution res_5_block0_conv_proj_conv2d 1 1 res_5_block0_conv_dw_relu res_5_block0_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 144 | BatchNorm res_5_block0_conv_proj_batchnorm 1 1 res_5_block0_conv_proj_conv2d res_5_block0_conv_proj_batchnorm 0=128 145 | BinaryOp _plus10 2 1 res_5_block0_conv_proj_batchnorm dconv_45_conv_proj_batchnorm_splitncnn_0 _plus10 0=0 146 | Split splitncnn_11 1 2 _plus10 _plus10_splitncnn_0 _plus10_splitncnn_1 147 | Convolution res_5_block1_conv_sep_conv2d 1 1 _plus10_splitncnn_1 res_5_block1_conv_sep_conv2d 0=256 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 148 | BatchNorm res_5_block1_conv_sep_batchnorm 1 1 res_5_block1_conv_sep_conv2d res_5_block1_conv_sep_batchnorm 0=256 149 | PReLU res_5_block1_conv_sep_relu 1 1 res_5_block1_conv_sep_batchnorm res_5_block1_conv_sep_relu 0=256 150 | ConvolutionDepthWise res_5_block1_conv_dw_conv2d 1 1 res_5_block1_conv_sep_relu res_5_block1_conv_dw_conv2d 0=256 1=3 11=3 3=1 13=1 4=1 14=1 5=0 6=2304 7=256 151 | BatchNorm res_5_block1_conv_dw_batchnorm 1 1 res_5_block1_conv_dw_conv2d res_5_block1_conv_dw_batchnorm 0=256 152 | PReLU res_5_block1_conv_dw_relu 1 1 res_5_block1_conv_dw_batchnorm res_5_block1_conv_dw_relu 0=256 153 | Convolution res_5_block1_conv_proj_conv2d 1 1 res_5_block1_conv_dw_relu res_5_block1_conv_proj_conv2d 0=128 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=32768 154 | BatchNorm res_5_block1_conv_proj_batchnorm 1 1 res_5_block1_conv_proj_conv2d res_5_block1_conv_proj_batchnorm 0=128 155 | BinaryOp _plus11 2 1 res_5_block1_conv_proj_batchnorm _plus10_splitncnn_0 _plus11 0=0 156 | Convolution conv_6sep_conv2d 1 1 _plus11 conv_6sep_conv2d 0=512 1=1 11=1 3=1 13=1 4=0 14=0 5=0 6=65536 157 | BatchNorm conv_6sep_batchnorm 1 1 conv_6sep_conv2d conv_6sep_batchnorm 0=512 158 | PReLU conv_6sep_relu 1 1 conv_6sep_batchnorm conv_6sep_relu 0=512 159 | ConvolutionDepthWise conv_6dw7_7_conv2d 1 1 conv_6sep_relu conv_6dw7_7_conv2d 0=512 1=7 11=7 3=1 13=1 4=0 14=0 5=0 6=25088 7=512 160 | BatchNorm conv_6dw7_7_batchnorm 1 1 conv_6dw7_7_conv2d conv_6dw7_7_batchnorm 0=512 161 | InnerProduct pre_fc1 1 1 conv_6dw7_7_batchnorm pre_fc1 0=128 1=1 2=65536 162 | BatchNorm fc1 1 1 pre_fc1 fc1 0=128 163 | -------------------------------------------------------------------------------- /ncnn/include/benchmark.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BENCHMARK_H 16 | #define NCNN_BENCHMARK_H 17 | 18 | #include "platform.h" 19 | #include "mat.h" 20 | #include "layer.h" 21 | 22 | namespace ncnn { 23 | 24 | // get now timestamp in ms 25 | double get_current_time(); 26 | 27 | #if NCNN_BENCHMARK 28 | 29 | void benchmark(const Layer* layer, double start, double end); 30 | void benchmark(const Layer* layer, const Mat& bottom_blob, Mat& top_blob, double start, double end); 31 | 32 | #endif // NCNN_BENCHMARK 33 | 34 | } // namespace ncnn 35 | 36 | #endif // NCNN_BENCHMARK_H 37 | -------------------------------------------------------------------------------- /ncnn/include/blob.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BLOB_H 16 | #define NCNN_BLOB_H 17 | 18 | #include 19 | #include 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Blob 25 | { 26 | public: 27 | // empty 28 | Blob(); 29 | 30 | public: 31 | #if NCNN_STRING 32 | // blob name 33 | std::string name; 34 | #endif // NCNN_STRING 35 | // layer index which produce this blob as output 36 | int producer; 37 | // layer index which need this blob as input 38 | std::vector consumers; 39 | }; 40 | 41 | } // namespace ncnn 42 | 43 | #endif // NCNN_BLOB_H 44 | -------------------------------------------------------------------------------- /ncnn/include/cpu.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_CPU_H 16 | #define NCNN_CPU_H 17 | 18 | namespace ncnn { 19 | 20 | // test optional cpu features 21 | // neon = armv7 neon or aarch64 asimd 22 | int cpu_support_arm_neon(); 23 | // vfpv4 = armv7 fp16 + fma 24 | int cpu_support_arm_vfpv4(); 25 | // asimdhp = aarch64 asimd half precision 26 | int cpu_support_arm_asimdhp(); 27 | 28 | // cpu info 29 | int get_cpu_count(); 30 | 31 | // bind all threads on little clusters if powersave enabled 32 | // affacts HMP arch cpu like ARM big.LITTLE 33 | // only implemented on android at the moment 34 | // switching powersave is expensive and not thread-safe 35 | // 0 = all cores enabled(default) 36 | // 1 = only little clusters enabled 37 | // 2 = only big clusters enabled 38 | // return 0 if success for setter function 39 | int get_cpu_powersave(); 40 | int set_cpu_powersave(int powersave); 41 | 42 | // misc function wrapper for openmp routines 43 | int get_omp_num_threads(); 44 | void set_omp_num_threads(int num_threads); 45 | 46 | int get_omp_dynamic(); 47 | void set_omp_dynamic(int dynamic); 48 | 49 | } // namespace ncnn 50 | 51 | #endif // NCNN_CPU_H 52 | -------------------------------------------------------------------------------- /ncnn/include/layer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_H 16 | #define NCNN_LAYER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include "mat.h" 22 | #include "modelbin.h" 23 | #include "paramdict.h" 24 | #include "platform.h" 25 | 26 | namespace ncnn { 27 | 28 | class Layer 29 | { 30 | public: 31 | // empty 32 | Layer(); 33 | // virtual destructor 34 | virtual ~Layer(); 35 | 36 | // load layer specific parameter from parsed dict 37 | // return 0 if success 38 | virtual int load_param(const ParamDict& pd); 39 | 40 | // load layer specific weight data from model binary 41 | // return 0 if success 42 | virtual int load_model(const ModelBin& mb); 43 | 44 | public: 45 | // one input and one output blob 46 | bool one_blob_only; 47 | 48 | // support inplace inference 49 | bool support_inplace; 50 | 51 | public: 52 | // implement inference 53 | // return 0 if success 54 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs) const; 55 | virtual int forward(const Mat& bottom_blob, Mat& top_blob) const; 56 | 57 | // implement inplace inference 58 | // return 0 if success 59 | virtual int forward_inplace(std::vector& bottom_top_blobs) const; 60 | virtual int forward_inplace(Mat& bottom_top_blob) const; 61 | 62 | public: 63 | #if NCNN_STRING 64 | // layer type name 65 | std::string type; 66 | // layer name 67 | std::string name; 68 | #endif // NCNN_STRING 69 | // blob index which this layer needs as input 70 | std::vector bottoms; 71 | // blob index which this layer produces as output 72 | std::vector tops; 73 | }; 74 | 75 | // layer factory function 76 | typedef Layer* (*layer_creator_func)(); 77 | 78 | struct layer_registry_entry 79 | { 80 | #if NCNN_STRING 81 | // layer type name 82 | const char* name; 83 | #endif // NCNN_STRING 84 | // layer factory entry 85 | layer_creator_func creator; 86 | }; 87 | 88 | #if NCNN_STRING 89 | // get layer type from type name 90 | int layer_to_index(const char* type); 91 | // create layer from type name 92 | Layer* create_layer(const char* type); 93 | #endif // NCNN_STRING 94 | // create layer from layer type 95 | Layer* create_layer(int index); 96 | 97 | #define DEFINE_LAYER_CREATOR(name) \ 98 | ::ncnn::Layer* name##_layer_creator() { return new name; } 99 | 100 | } // namespace ncnn 101 | 102 | #endif // NCNN_LAYER_H 103 | -------------------------------------------------------------------------------- /ncnn/include/layer_type.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_TYPE_H 16 | #define NCNN_LAYER_TYPE_H 17 | 18 | namespace ncnn { 19 | 20 | namespace LayerType { 21 | enum 22 | { 23 | #include "layer_type_enum.h" 24 | CustomBit = (1<<8), 25 | }; 26 | } // namespace LayerType 27 | 28 | } // namespace ncnn 29 | 30 | #endif // NCNN_LAYER_TYPE_H 31 | -------------------------------------------------------------------------------- /ncnn/include/layer_type_enum.h: -------------------------------------------------------------------------------- 1 | AbsVal = 0, 2 | ArgMax = 1, 3 | BatchNorm = 2, 4 | Bias = 3, 5 | BNLL = 4, 6 | Concat = 5, 7 | Convolution = 6, 8 | Crop = 7, 9 | Deconvolution = 8, 10 | Dropout = 9, 11 | Eltwise = 10, 12 | ELU = 11, 13 | Embed = 12, 14 | Exp = 13, 15 | Flatten = 14, 16 | InnerProduct = 15, 17 | Input = 16, 18 | Log = 17, 19 | LRN = 18, 20 | MemoryData = 19, 21 | MVN = 20, 22 | Pooling = 21, 23 | Power = 22, 24 | PReLU = 23, 25 | Proposal = 24, 26 | Reduction = 25, 27 | ReLU = 26, 28 | Reshape = 27, 29 | ROIPooling = 28, 30 | Scale = 29, 31 | Sigmoid = 30, 32 | Slice = 31, 33 | Softmax = 32, 34 | Split = 33, 35 | SPP = 34, 36 | TanH = 35, 37 | Threshold = 36, 38 | Tile = 37, 39 | RNN = 38, 40 | LSTM = 39, 41 | BinaryOp = 40, 42 | UnaryOp = 41, 43 | ConvolutionDepthWise = 42, 44 | Padding = 43, 45 | Squeeze = 44, 46 | ExpandDims = 45, 47 | Normalize = 46, 48 | Permute = 47, 49 | PriorBox = 48, 50 | DetectionOutput = 49, 51 | Interp = 50, 52 | DeconvolutionDepthWise = 51, 53 | ShuffleChannel = 52, 54 | InstanceNorm = 53, 55 | Clip = 54, 56 | Reorg = 55, 57 | YoloDetectionOutput = 56, 58 | -------------------------------------------------------------------------------- /ncnn/include/mat.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MAT_H 16 | #define NCNN_MAT_H 17 | 18 | #include 19 | #include 20 | #if __ARM_NEON 21 | #include 22 | #endif 23 | #include "platform.h" 24 | 25 | namespace ncnn { 26 | 27 | // the three dimension matrix 28 | class Mat 29 | { 30 | public: 31 | // empty 32 | Mat(); 33 | // vec 34 | Mat(int w, size_t elemsize = 4); 35 | // image 36 | Mat(int w, int h, size_t elemsize = 4); 37 | // dim 38 | Mat(int w, int h, int c, size_t elemsize = 4); 39 | // copy 40 | Mat(const Mat& m); 41 | // external vec 42 | Mat(int w, void* data, size_t elemsize = 4); 43 | // external image 44 | Mat(int w, int h, void* data, size_t elemsize = 4); 45 | // external dim 46 | Mat(int w, int h, int c, void* data, size_t elemsize = 4); 47 | // release 48 | ~Mat(); 49 | // assign 50 | Mat& operator=(const Mat& m); 51 | // set all 52 | void fill(float v); 53 | template void fill(T v); 54 | // deep copy 55 | Mat clone() const; 56 | // reshape vec 57 | Mat reshape(int w) const; 58 | // reshape image 59 | Mat reshape(int w, int h) const; 60 | // reshape dim 61 | Mat reshape(int w, int h, int c) const; 62 | // allocate vec 63 | void create(int w, size_t elemsize = 4); 64 | // allocate image 65 | void create(int w, int h, size_t elemsize = 4); 66 | // allocate dim 67 | void create(int w, int h, int c, size_t elemsize = 4); 68 | // refcount++ 69 | void addref(); 70 | // refcount-- 71 | void release(); 72 | 73 | bool empty() const; 74 | size_t total() const; 75 | 76 | // data reference 77 | Mat channel(int c); 78 | const Mat channel(int c) const; 79 | float* row(int y); 80 | const float* row(int y) const; 81 | template T* row(int y); 82 | template const T* row(int y) const; 83 | 84 | // access raw data 85 | template operator T*(); 86 | template operator const T*() const; 87 | 88 | // convenient access float vec element 89 | float& operator[](int i); 90 | const float& operator[](int i) const; 91 | 92 | #if NCNN_PIXEL 93 | enum 94 | { 95 | PIXEL_CONVERT_SHIFT = 16, 96 | PIXEL_FORMAT_MASK = 0x0000ffff, 97 | PIXEL_CONVERT_MASK = 0xffff0000, 98 | 99 | PIXEL_RGB = 1, 100 | PIXEL_BGR = (1 << 1), 101 | PIXEL_GRAY = (1 << 2), 102 | PIXEL_RGBA = (1 << 3), 103 | 104 | PIXEL_RGB2BGR = PIXEL_RGB | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 105 | PIXEL_RGB2GRAY = PIXEL_RGB | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 106 | 107 | PIXEL_BGR2RGB = PIXEL_BGR | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 108 | PIXEL_BGR2GRAY = PIXEL_BGR | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 109 | 110 | PIXEL_GRAY2RGB = PIXEL_GRAY | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 111 | PIXEL_GRAY2BGR = PIXEL_GRAY | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 112 | 113 | PIXEL_RGBA2RGB = PIXEL_RGBA | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 114 | PIXEL_RGBA2BGR = PIXEL_RGBA | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 115 | PIXEL_RGBA2GRAY = PIXEL_RGBA | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 116 | }; 117 | // convenient construct from pixel data 118 | static Mat from_pixels(const unsigned char* pixels, int type, int w, int h); 119 | // convenient construct from pixel data and resize to specific size 120 | static Mat from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int target_width, int target_height); 121 | 122 | // convenient export to pixel data 123 | void to_pixels(unsigned char* pixels, int type) const; 124 | // convenient export to pixel data and resize to specific size 125 | void to_pixels_resize(unsigned char* pixels, int type, int target_width, int target_height) const; 126 | #endif // NCNN_PIXEL 127 | 128 | // substract channel-wise mean values, then multiply by normalize values, pass 0 to skip 129 | void substract_mean_normalize(const float* mean_vals, const float* norm_vals); 130 | 131 | // convenient construct from half precisoin floating point data 132 | static Mat from_float16(const unsigned short* data, int size); 133 | 134 | // pointer to the data 135 | void* data; 136 | 137 | // pointer to the reference counter 138 | // when points to user-allocated data, the pointer is NULL 139 | int* refcount; 140 | 141 | // element size in bytes 142 | // 4 = float32/int32 143 | // 2 = float16 144 | // 1 = int8/uint8 145 | // 0 = empty 146 | size_t elemsize; 147 | 148 | // the dimensionality 149 | int dims; 150 | 151 | int w; 152 | int h; 153 | int c; 154 | 155 | size_t cstep; 156 | }; 157 | 158 | // misc function 159 | #if NCNN_PIXEL 160 | // image pixel bilinear resize 161 | void resize_bilinear_c1(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 162 | void resize_bilinear_c3(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 163 | void resize_bilinear_c4(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 164 | #endif // NCNN_PIXEL 165 | 166 | // mat process 167 | enum 168 | { 169 | BORDER_CONSTANT = 0, 170 | BORDER_REPLICATE = 1, 171 | }; 172 | void copy_make_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int type, float v); 173 | void copy_cut_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right); 174 | void resize_bilinear(const Mat& src, Mat& dst, int w, int h); 175 | 176 | // the alignment of all the allocated buffers 177 | #define MALLOC_ALIGN 16 178 | 179 | // Aligns a pointer to the specified number of bytes 180 | // ptr Aligned pointer 181 | // n Alignment size that must be a power of two 182 | template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) 183 | { 184 | return (_Tp*)(((size_t)ptr + n-1) & -n); 185 | } 186 | 187 | // Aligns a buffer size to the specified number of bytes 188 | // The function returns the minimum number that is greater or equal to sz and is divisible by n 189 | // sz Buffer size to align 190 | // n Alignment size that must be a power of two 191 | static inline size_t alignSize(size_t sz, int n) 192 | { 193 | return (sz + n-1) & -n; 194 | } 195 | 196 | static inline void* fastMalloc(size_t size) 197 | { 198 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 199 | if (!udata) 200 | return 0; 201 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 202 | adata[-1] = udata; 203 | return adata; 204 | } 205 | 206 | static inline void fastFree(void* ptr) 207 | { 208 | if (ptr) 209 | { 210 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 211 | free(udata); 212 | } 213 | } 214 | 215 | // exchange-add operation for atomic operations on reference counters 216 | #if defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) 217 | // atomic increment on the linux version of the Intel(tm) compiler 218 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta) 219 | #elif defined __GNUC__ 220 | # if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) 221 | # ifdef __ATOMIC_ACQ_REL 222 | # define NCNN_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) 223 | # else 224 | # define NCNN_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), delta, 4) 225 | # endif 226 | # else 227 | # if defined __ATOMIC_ACQ_REL && !defined __clang__ 228 | // version for gcc >= 4.7 229 | # define NCNN_XADD(addr, delta) (int)__atomic_fetch_add((unsigned*)(addr), (unsigned)(delta), __ATOMIC_ACQ_REL) 230 | # else 231 | # define NCNN_XADD(addr, delta) (int)__sync_fetch_and_add((unsigned*)(addr), (unsigned)(delta)) 232 | # endif 233 | # endif 234 | #elif defined _MSC_VER && !defined RC_INVOKED 235 | # include 236 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta) 237 | #else 238 | static inline void NCNN_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; } 239 | #endif 240 | 241 | inline Mat::Mat() 242 | : data(0), refcount(0), elemsize(0), dims(0), w(0), h(0), c(0), cstep(0) 243 | { 244 | } 245 | 246 | inline Mat::Mat(int _w, size_t _elemsize) 247 | : data(0), refcount(0), dims(0) 248 | { 249 | create(_w, _elemsize); 250 | } 251 | 252 | inline Mat::Mat(int _w, int _h, size_t _elemsize) 253 | : data(0), refcount(0), dims(0) 254 | { 255 | create(_w, _h, _elemsize); 256 | } 257 | 258 | inline Mat::Mat(int _w, int _h, int _c, size_t _elemsize) 259 | : data(0), refcount(0), dims(0) 260 | { 261 | create(_w, _h, _c, _elemsize); 262 | } 263 | 264 | inline Mat::Mat(const Mat& m) 265 | : data(m.data), refcount(m.refcount), elemsize(m.elemsize), dims(m.dims) 266 | { 267 | if (refcount) 268 | NCNN_XADD(refcount, 1); 269 | 270 | w = m.w; 271 | h = m.h; 272 | c = m.c; 273 | 274 | cstep = m.cstep; 275 | } 276 | 277 | inline Mat::Mat(int _w, void* _data, size_t _elemsize) 278 | : data(_data), refcount(0), elemsize(_elemsize), dims(1) 279 | { 280 | w = _w; 281 | h = 1; 282 | c = 1; 283 | 284 | cstep = w; 285 | } 286 | 287 | inline Mat::Mat(int _w, int _h, void* _data, size_t _elemsize) 288 | : data(_data), refcount(0), elemsize(_elemsize), dims(2) 289 | { 290 | w = _w; 291 | h = _h; 292 | c = 1; 293 | 294 | cstep = w * h; 295 | } 296 | 297 | inline Mat::Mat(int _w, int _h, int _c, void* _data, size_t _elemsize) 298 | : data(_data), refcount(0), elemsize(_elemsize), dims(3) 299 | { 300 | w = _w; 301 | h = _h; 302 | c = _c; 303 | 304 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 305 | } 306 | 307 | inline Mat::~Mat() 308 | { 309 | release(); 310 | } 311 | 312 | inline Mat& Mat::operator=(const Mat& m) 313 | { 314 | if (this == &m) 315 | return *this; 316 | 317 | if (m.refcount) 318 | NCNN_XADD(m.refcount, 1); 319 | 320 | release(); 321 | 322 | data = m.data; 323 | refcount = m.refcount; 324 | elemsize = m.elemsize; 325 | 326 | dims = m.dims; 327 | w = m.w; 328 | h = m.h; 329 | c = m.c; 330 | 331 | cstep = m.cstep; 332 | 333 | return *this; 334 | } 335 | 336 | inline void Mat::fill(float _v) 337 | { 338 | int size = total(); 339 | float* ptr = (float*)data; 340 | 341 | #if __ARM_NEON 342 | int nn = size >> 2; 343 | int remain = size - (nn << 2); 344 | #else 345 | int remain = size; 346 | #endif // __ARM_NEON 347 | 348 | #if __ARM_NEON 349 | float32x4_t _c = vdupq_n_f32(_v); 350 | #if __aarch64__ 351 | if (nn > 0) 352 | { 353 | asm volatile ( 354 | "0: \n" 355 | "subs %w0, %w0, #1 \n" 356 | "st1 {%4.4s}, [%1], #16 \n" 357 | "bne 0b \n" 358 | : "=r"(nn), // %0 359 | "=r"(ptr) // %1 360 | : "0"(nn), 361 | "1"(ptr), 362 | "w"(_c) // %4 363 | : "cc", "memory" 364 | ); 365 | } 366 | #else 367 | if (nn > 0) 368 | { 369 | asm volatile( 370 | "0: \n" 371 | "subs %0, #1 \n" 372 | "vst1.f32 {%e4-%f4}, [%1 :128]!\n" 373 | "bne 0b \n" 374 | : "=r"(nn), // %0 375 | "=r"(ptr) // %1 376 | : "0"(nn), 377 | "1"(ptr), 378 | "w"(_c) // %4 379 | : "cc", "memory" 380 | ); 381 | } 382 | #endif // __aarch64__ 383 | #endif // __ARM_NEON 384 | for (; remain>0; remain--) 385 | { 386 | *ptr++ = _v; 387 | } 388 | } 389 | 390 | template 391 | inline void Mat::fill(T _v) 392 | { 393 | int size = total(); 394 | T* ptr = (T*)data; 395 | for (int i=0; i 0) 415 | { 416 | memcpy(m.data, data, total() * elemsize); 417 | } 418 | 419 | return m; 420 | } 421 | 422 | inline Mat Mat::reshape(int _w) const 423 | { 424 | if (w * h * c != _w) 425 | return Mat(); 426 | 427 | if (dims == 3 && cstep != (size_t)w * h) 428 | { 429 | Mat m; 430 | m.create(_w, elemsize); 431 | 432 | // flatten 433 | for (int i=0; i 0) 547 | { 548 | size_t totalsize = total() * elemsize; 549 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 550 | refcount = (int*)(((unsigned char*)data) + totalsize); 551 | *refcount = 1; 552 | } 553 | } 554 | 555 | inline void Mat::create(int _w, int _h, size_t _elemsize) 556 | { 557 | if (dims == 2 && w == _w && h == _h && elemsize == _elemsize) 558 | return; 559 | 560 | release(); 561 | 562 | elemsize = _elemsize; 563 | 564 | dims = 2; 565 | w = _w; 566 | h = _h; 567 | c = 1; 568 | 569 | cstep = w * h; 570 | 571 | if (total() > 0) 572 | { 573 | size_t totalsize = total() * elemsize; 574 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 575 | refcount = (int*)(((unsigned char*)data) + totalsize); 576 | *refcount = 1; 577 | } 578 | } 579 | 580 | inline void Mat::create(int _w, int _h, int _c, size_t _elemsize) 581 | { 582 | if (dims == 3 && w == _w && h == _h && c == _c && elemsize == _elemsize) 583 | return; 584 | 585 | release(); 586 | 587 | elemsize = _elemsize; 588 | 589 | dims = 3; 590 | w = _w; 591 | h = _h; 592 | c = _c; 593 | 594 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 595 | 596 | if (total() > 0) 597 | { 598 | size_t totalsize = total() * elemsize; 599 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 600 | refcount = (int*)(((unsigned char*)data) + totalsize); 601 | *refcount = 1; 602 | } 603 | } 604 | 605 | inline void Mat::addref() 606 | { 607 | if (refcount) 608 | NCNN_XADD(refcount, 1); 609 | } 610 | 611 | inline void Mat::release() 612 | { 613 | if (refcount && NCNN_XADD(refcount, -1) == 1) 614 | fastFree(data); 615 | 616 | data = 0; 617 | 618 | elemsize = 0; 619 | 620 | dims = 0; 621 | w = 0; 622 | h = 0; 623 | c = 0; 624 | 625 | cstep = 0; 626 | 627 | refcount = 0; 628 | } 629 | 630 | inline bool Mat::empty() const 631 | { 632 | return data == 0 || total() == 0; 633 | } 634 | 635 | inline size_t Mat::total() const 636 | { 637 | return cstep * c; 638 | } 639 | 640 | inline Mat Mat::channel(int c) 641 | { 642 | return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize); 643 | } 644 | 645 | inline const Mat Mat::channel(int c) const 646 | { 647 | return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize); 648 | } 649 | 650 | inline float* Mat::row(int y) 651 | { 652 | return (float*)data + w * y; 653 | } 654 | 655 | inline const float* Mat::row(int y) const 656 | { 657 | return (const float*)data + w * y; 658 | } 659 | 660 | template 661 | inline T* Mat::row(int y) 662 | { 663 | return (T*)data + w * y; 664 | } 665 | 666 | template 667 | inline const T* Mat::row(int y) const 668 | { 669 | return (const T*)data + w * y; 670 | } 671 | 672 | template 673 | inline Mat::operator T*() 674 | { 675 | return (T*)data; 676 | } 677 | 678 | template 679 | inline Mat::operator const T*() const 680 | { 681 | return (const T*)data; 682 | } 683 | 684 | inline float& Mat::operator[](int i) 685 | { 686 | return ((float*)data)[i]; 687 | } 688 | 689 | inline const float& Mat::operator[](int i) const 690 | { 691 | return ((const float*)data)[i]; 692 | } 693 | 694 | } // namespace ncnn 695 | 696 | #endif // NCNN_MAT_H 697 | -------------------------------------------------------------------------------- /ncnn/include/modelbin.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MODELBIN_H 16 | #define NCNN_MODELBIN_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Net; 25 | class ModelBin 26 | { 27 | public: 28 | // element type 29 | // 0 = auto 30 | // 1 = float32 31 | // 2 = float16 32 | // 3 = uint8 33 | // load vec 34 | virtual Mat load(int w, int type) const = 0; 35 | // load image 36 | virtual Mat load(int w, int h, int type) const; 37 | // load dim 38 | virtual Mat load(int w, int h, int c, int type) const; 39 | }; 40 | 41 | #if NCNN_STDIO 42 | class ModelBinFromStdio : public ModelBin 43 | { 44 | public: 45 | // construct from file 46 | ModelBinFromStdio(FILE* binfp); 47 | 48 | virtual Mat load(int w, int type) const; 49 | 50 | protected: 51 | FILE* binfp; 52 | }; 53 | #endif // NCNN_STDIO 54 | 55 | class ModelBinFromMemory : public ModelBin 56 | { 57 | public: 58 | // construct from external memory 59 | ModelBinFromMemory(const unsigned char*& mem); 60 | 61 | virtual Mat load(int w, int type) const; 62 | 63 | protected: 64 | const unsigned char*& mem; 65 | }; 66 | 67 | class ModelBinFromMatArray : public ModelBin 68 | { 69 | public: 70 | // construct from weight blob array 71 | ModelBinFromMatArray(const Mat* weights); 72 | 73 | virtual Mat load(int w, int type) const; 74 | 75 | protected: 76 | mutable const Mat* weights; 77 | }; 78 | 79 | } // namespace ncnn 80 | 81 | #endif // NCNN_MODELBIN_H 82 | -------------------------------------------------------------------------------- /ncnn/include/net.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_NET_H 16 | #define NCNN_NET_H 17 | 18 | #include 19 | #include 20 | #include "blob.h" 21 | #include "layer.h" 22 | #include "mat.h" 23 | #include "platform.h" 24 | 25 | namespace ncnn { 26 | 27 | class Extractor; 28 | class Net 29 | { 30 | public: 31 | // empty init 32 | Net(); 33 | // clear and destroy 34 | ~Net(); 35 | 36 | #if NCNN_STRING 37 | // register custom layer by layer type name 38 | // return 0 if success 39 | int register_custom_layer(const char* type, layer_creator_func creator); 40 | #endif // NCNN_STRING 41 | // register custom layer by layer type 42 | // return 0 if success 43 | int register_custom_layer(int index, layer_creator_func creator); 44 | 45 | #if NCNN_STDIO 46 | #if NCNN_STRING 47 | // load network structure from plain param file 48 | // return 0 if success 49 | int load_param(FILE* fp); 50 | int load_param(const char* protopath); 51 | #endif // NCNN_STRING 52 | // load network structure from binary param file 53 | // return 0 if success 54 | int load_param_bin(FILE* fp); 55 | int load_param_bin(const char* protopath); 56 | 57 | // load network weight data from model file 58 | // return 0 if success 59 | int load_model(FILE* fp); 60 | int load_model(const char* modelpath); 61 | #endif // NCNN_STDIO 62 | 63 | // load network structure from external memory 64 | // memory pointer must be 32-bit aligned 65 | // return bytes consumed 66 | int load_param(const unsigned char* mem); 67 | 68 | // reference network weight data from external memory 69 | // weight data is not copied but referenced 70 | // so external memory should be retained when used 71 | // memory pointer must be 32-bit aligned 72 | // return bytes consumed 73 | int load_model(const unsigned char* mem); 74 | 75 | // unload network structure and weight data 76 | void clear(); 77 | 78 | // construct an Extractor from network 79 | Extractor create_extractor() const; 80 | 81 | protected: 82 | friend class Extractor; 83 | #if NCNN_STRING 84 | int find_blob_index_by_name(const char* name) const; 85 | int find_layer_index_by_name(const char* name) const; 86 | int custom_layer_to_index(const char* type); 87 | Layer* create_custom_layer(const char* type); 88 | #endif // NCNN_STRING 89 | Layer* create_custom_layer(int index); 90 | int forward_layer(int layer_index, std::vector& blob_mats, bool lightmode) const; 91 | 92 | protected: 93 | std::vector blobs; 94 | std::vector layers; 95 | 96 | std::vector custom_layer_registry; 97 | }; 98 | 99 | class Extractor 100 | { 101 | public: 102 | // enable light mode 103 | // intermediate blob will be recycled when enabled 104 | // enabled by default 105 | void set_light_mode(bool enable); 106 | 107 | // set thread count for this extractor 108 | // this will overwrite the global setting 109 | // default count is system depended 110 | void set_num_threads(int num_threads); 111 | 112 | #if NCNN_STRING 113 | // set input by blob name 114 | // return 0 if success 115 | int input(const char* blob_name, const Mat& in); 116 | 117 | // get result by blob name 118 | // return 0 if success 119 | int extract(const char* blob_name, Mat& feat); 120 | #endif // NCNN_STRING 121 | 122 | // set input by blob index 123 | // return 0 if success 124 | int input(int blob_index, const Mat& in); 125 | 126 | // get result by blob index 127 | // return 0 if success 128 | int extract(int blob_index, Mat& feat); 129 | 130 | protected: 131 | friend Extractor Net::create_extractor() const; 132 | Extractor(const Net* net, int blob_count); 133 | 134 | private: 135 | const Net* net; 136 | std::vector blob_mats; 137 | bool lightmode; 138 | int num_threads; 139 | }; 140 | 141 | } // namespace ncnn 142 | 143 | #endif // NCNN_NET_H 144 | -------------------------------------------------------------------------------- /ncnn/include/opencv.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_OPENCV_H 16 | #define NCNN_OPENCV_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_OPENCV 21 | 22 | #include 23 | #include 24 | #include "mat.h" 25 | 26 | // minimal opencv style data structure implementation 27 | namespace cv 28 | { 29 | 30 | struct Size 31 | { 32 | Size() : width(0), height(0) {} 33 | Size(int _w, int _h) : width(_w), height(_h) {} 34 | 35 | int width; 36 | int height; 37 | }; 38 | 39 | template 40 | struct Rect_ 41 | { 42 | Rect_() : x(0), y(0), width(0), height(0) {} 43 | Rect_(_Tp _x, _Tp _y, _Tp _w, _Tp _h) : x(_x), y(_y), width(_w), height(_h) {} 44 | 45 | _Tp x; 46 | _Tp y; 47 | _Tp width; 48 | _Tp height; 49 | 50 | // area 51 | _Tp area() const 52 | { 53 | return width * height; 54 | } 55 | }; 56 | 57 | template static inline Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 58 | { 59 | _Tp x1 = std::max(a.x, b.x), y1 = std::max(a.y, b.y); 60 | a.width = std::min(a.x + a.width, b.x + b.width) - x1; 61 | a.height = std::min(a.y + a.height, b.y + b.height) - y1; 62 | a.x = x1; a.y = y1; 63 | if( a.width <= 0 || a.height <= 0 ) 64 | a = Rect_<_Tp>(); 65 | return a; 66 | } 67 | 68 | template static inline Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 69 | { 70 | _Tp x1 = std::min(a.x, b.x), y1 = std::min(a.y, b.y); 71 | a.width = std::max(a.x + a.width, b.x + b.width) - x1; 72 | a.height = std::max(a.y + a.height, b.y + b.height) - y1; 73 | a.x = x1; a.y = y1; 74 | return a; 75 | } 76 | 77 | template static inline Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 78 | { 79 | Rect_<_Tp> c = a; 80 | return c &= b; 81 | } 82 | 83 | template static inline Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 84 | { 85 | Rect_<_Tp> c = a; 86 | return c |= b; 87 | } 88 | 89 | typedef Rect_ Rect; 90 | typedef Rect_ Rect2f; 91 | 92 | template 93 | struct Point_ 94 | { 95 | Point_() : x(0), y(0) {} 96 | Point_(_Tp _x, _Tp _y) : x(_x), y(_y) {} 97 | 98 | _Tp x; 99 | _Tp y; 100 | }; 101 | 102 | typedef Point_ Point; 103 | typedef Point_ Point2f; 104 | 105 | #define CV_8UC1 1 106 | #define CV_8UC3 3 107 | #define CV_8UC4 4 108 | #define CV_32FC1 4 109 | 110 | struct Mat 111 | { 112 | Mat() : data(0), refcount(0), rows(0), cols(0), c(0) {} 113 | 114 | Mat(int _rows, int _cols, int flags) : data(0), refcount(0) 115 | { 116 | create(_rows, _cols, flags); 117 | } 118 | 119 | // copy 120 | Mat(const Mat& m) : data(m.data), refcount(m.refcount) 121 | { 122 | if (refcount) 123 | NCNN_XADD(refcount, 1); 124 | 125 | rows = m.rows; 126 | cols = m.cols; 127 | c = m.c; 128 | } 129 | 130 | Mat(int _rows, int _cols, int flags, void* _data) : data((unsigned char*)_data), refcount(0) 131 | { 132 | rows = _rows; 133 | cols = _cols; 134 | c = flags; 135 | } 136 | 137 | ~Mat() 138 | { 139 | release(); 140 | } 141 | 142 | // assign 143 | Mat& operator=(const Mat& m) 144 | { 145 | if (this == &m) 146 | return *this; 147 | 148 | if (m.refcount) 149 | NCNN_XADD(m.refcount, 1); 150 | 151 | release(); 152 | 153 | data = m.data; 154 | refcount = m.refcount; 155 | 156 | rows = m.rows; 157 | cols = m.cols; 158 | c = m.c; 159 | 160 | return *this; 161 | } 162 | 163 | void create(int _rows, int _cols, int flags) 164 | { 165 | release(); 166 | 167 | rows = _rows; 168 | cols = _cols; 169 | c = flags; 170 | 171 | if (total() > 0) 172 | { 173 | // refcount address must be aligned, so we expand totalsize here 174 | size_t totalsize = (total() + 3) >> 2 << 2; 175 | data = (unsigned char*)ncnn::fastMalloc(totalsize + (int)sizeof(*refcount)); 176 | refcount = (int*)(((unsigned char*)data) + totalsize); 177 | *refcount = 1; 178 | } 179 | } 180 | 181 | void release() 182 | { 183 | if (refcount && NCNN_XADD(refcount, -1) == 1) 184 | ncnn::fastFree(data); 185 | 186 | data = 0; 187 | 188 | rows = 0; 189 | cols = 0; 190 | c = 0; 191 | 192 | refcount = 0; 193 | } 194 | 195 | Mat clone() const 196 | { 197 | if (empty()) 198 | return Mat(); 199 | 200 | Mat m(rows, cols, c); 201 | 202 | if (total() > 0) 203 | { 204 | memcpy(m.data, data, total()); 205 | } 206 | 207 | return m; 208 | } 209 | 210 | bool empty() const { return data == 0 || total() == 0; } 211 | 212 | int channels() const { return c; } 213 | 214 | size_t total() const { return cols * rows * c; } 215 | 216 | const unsigned char* ptr(int y) const { return data + y * cols * c; } 217 | 218 | unsigned char* ptr(int y) { return data + y * cols * c; } 219 | 220 | // roi 221 | Mat operator()( const Rect& roi ) const 222 | { 223 | if (empty()) 224 | return Mat(); 225 | 226 | Mat m(roi.height, roi.width, c); 227 | 228 | int sy = roi.y; 229 | for (int y = 0; y < roi.height; y++) 230 | { 231 | const unsigned char* sptr = ptr(sy) + roi.x * c; 232 | unsigned char* dptr = m.ptr(y); 233 | memcpy(dptr, sptr, roi.width * c); 234 | sy++; 235 | } 236 | 237 | return m; 238 | } 239 | 240 | unsigned char* data; 241 | 242 | // pointer to the reference counter; 243 | // when points to user-allocated data, the pointer is NULL 244 | int* refcount; 245 | 246 | int rows; 247 | int cols; 248 | 249 | int c; 250 | 251 | }; 252 | 253 | #define CV_LOAD_IMAGE_GRAYSCALE 1 254 | #define CV_LOAD_IMAGE_COLOR 3 255 | Mat imread(const std::string& path, int flags); 256 | void imwrite(const std::string& path, const Mat& m); 257 | 258 | #if NCNN_PIXEL 259 | void resize(const Mat& src, Mat& dst, const Size& size, float sw = 0.f, float sh = 0.f, int flags = 0); 260 | #endif // NCNN_PIXEL 261 | 262 | } // namespace cv 263 | 264 | #endif // NCNN_OPENCV 265 | 266 | #endif // NCNN_OPENCV_H 267 | -------------------------------------------------------------------------------- /ncnn/include/paramdict.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PARAMDICT_H 16 | #define NCNN_PARAMDICT_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | // at most 20 parameters 23 | #define NCNN_MAX_PARAM_COUNT 20 24 | 25 | namespace ncnn { 26 | 27 | class Net; 28 | class ParamDict 29 | { 30 | public: 31 | // empty 32 | ParamDict(); 33 | 34 | // get int 35 | int get(int id, int def) const; 36 | // get float 37 | float get(int id, float def) const; 38 | // get array 39 | Mat get(int id, const Mat& def) const; 40 | 41 | // set int 42 | void set(int id, int i); 43 | // set float 44 | void set(int id, float f); 45 | // set array 46 | void set(int id, const Mat& v); 47 | 48 | protected: 49 | friend class Net; 50 | 51 | void clear(); 52 | 53 | #if NCNN_STDIO 54 | #if NCNN_STRING 55 | int load_param(FILE* fp); 56 | #endif // NCNN_STRING 57 | int load_param_bin(FILE* fp); 58 | #endif // NCNN_STDIO 59 | int load_param(const unsigned char*& mem); 60 | 61 | protected: 62 | struct 63 | { 64 | int loaded; 65 | union { int i; float f; }; 66 | Mat v; 67 | } params[NCNN_MAX_PARAM_COUNT]; 68 | }; 69 | 70 | } // namespace ncnn 71 | 72 | #endif // NCNN_PARAMDICT_H 73 | -------------------------------------------------------------------------------- /ncnn/include/platform.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PLATFORM_H 16 | #define NCNN_PLATFORM_H 17 | 18 | #define NCNN_STDIO 1 19 | #define NCNN_STRING 1 20 | #define NCNN_OPENCV 0 21 | #define NCNN_BENCHMARK 0 22 | #define NCNN_PIXEL 1 23 | #define NCNN_PIXEL_ROTATE 0 24 | 25 | #endif // NCNN_PLATFORM_H 26 | -------------------------------------------------------------------------------- /ncnn/lib/libncnn.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KangKangLoveCat/insightface_ncnn/70333fa3bea56f6949a0914e4a921b9a61764d96/ncnn/lib/libncnn.a --------------------------------------------------------------------------------