Browse Source

C api (#1851)

tags/20200727
nihui GitHub 6 years ago
parent
commit
a33b353c36
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 626 additions and 3 deletions
  1. +1
    -0
      examples/CMakeLists.txt
  2. +117
    -0
      examples/squeezenet_c_api.cpp
  3. +2
    -0
      src/CMakeLists.txt
  4. +372
    -0
      src/c_api.cpp
  5. +130
    -0
      src/c_api.h
  6. +4
    -3
      src/net.h

+ 1
- 0
examples/CMakeLists.txt View File

@@ -17,6 +17,7 @@ if(OpenCV_FOUND)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src)

ncnn_add_example(squeezenet)
ncnn_add_example(squeezenet_c_api)
ncnn_add_example(fasterrcnn)
ncnn_add_example(rfcn)
ncnn_add_example(yolov2)


+ 117
- 0
examples/squeezenet_c_api.cpp View File

@@ -0,0 +1,117 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#include "c_api.h"

#include <algorithm>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <vector>

static int detect_squeezenet(const cv::Mat& bgr, std::vector<float>& cls_scores)
{
ncnn_net_t squeezenet = ncnn_net_create();

ncnn_option_t opt = ncnn_option_create();
ncnn_option_set_use_vulkan_compute(opt, 1);

ncnn_net_set_option(squeezenet, opt);

// the ncnn model https://github.com/nihui/ncnn-assets/tree/master/models
ncnn_net_load_param(squeezenet, "squeezenet_v1.1.param");
ncnn_net_load_model(squeezenet, "squeezenet_v1.1.bin");

ncnn_mat_t in = ncnn_mat_from_pixels_resize(bgr.data, NCNN_MAT_PIXEL_BGR, bgr.cols, bgr.rows, bgr.cols * 3, 227, 227);

const float mean_vals[3] = {104.f, 117.f, 123.f};
ncnn_mat_substract_mean_normalize(in, mean_vals, 0);

ncnn_extractor_t ex = ncnn_extractor_create(squeezenet);

ncnn_extractor_input(ex, "data", in);

ncnn_mat_t out;
ncnn_extractor_extract(ex, "prob", &out);

const int out_w = ncnn_mat_get_w(out);
const float* out_data = (const float*)ncnn_mat_get_data(out);

cls_scores.resize(out_w);
for (int j = 0; j < out_w; j++)
{
cls_scores[j] = out_data[j];
}

ncnn_mat_destroy(in);
ncnn_mat_destroy(out);

ncnn_extractor_destroy(ex);

ncnn_option_destroy(opt);

ncnn_net_destroy(squeezenet);

return 0;
}

static int print_topk(const std::vector<float>& cls_scores, int topk)
{
// partial sort topk with index
int size = cls_scores.size();
std::vector<std::pair<float, int> > vec;
vec.resize(size);
for (int i = 0; i < size; i++)
{
vec[i] = std::make_pair(cls_scores[i], i);
}

std::partial_sort(vec.begin(), vec.begin() + topk, vec.end(),
std::greater<std::pair<float, int> >());

// print topk and score
for (int i = 0; i < topk; i++)
{
float score = vec[i].first;
int index = vec[i].second;
fprintf(stderr, "%d = %f\n", index, score);
}

return 0;
}

int main(int argc, char** argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s [imagepath]\n", argv[0]);
return -1;
}

const char* imagepath = argv[1];

cv::Mat m = cv::imread(imagepath, 1);
if (m.empty())
{
fprintf(stderr, "cv::imread %s failed\n", imagepath);
return -1;
}

std::vector<float> cls_scores;
detect_squeezenet(m, cls_scores);

print_topk(cls_scores, 3);

return 0;
}

+ 2
- 0
src/CMakeLists.txt View File

@@ -23,6 +23,7 @@ set(ncnn_SRCS
allocator.cpp
benchmark.cpp
blob.cpp
c_api.cpp
command.cpp
cpu.cpp
datareader.cpp
@@ -425,6 +426,7 @@ if(NCNN_INSTALL_SDK)
install(FILES
allocator.h
blob.h
c_api.h
command.h
cpu.h
datareader.h


+ 372
- 0
src/c_api.cpp View File

@@ -0,0 +1,372 @@
/* Tencent is pleased to support the open source community by making ncnn available.
*
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

#include "c_api.h"

#include "mat.h"
#include "option.h"
#include "net.h"

using ncnn::Blob;
using ncnn::Extractor;
using ncnn::Layer;
using ncnn::Mat;
using ncnn::Net;
using ncnn::Option;

#ifdef __cplusplus
extern "C" {
#endif

/* mat api */
ncnn_mat_t ncnn_mat_create()
{
return (ncnn_mat_t)(new Mat());
}

ncnn_mat_t ncnn_mat_create_1d(int w)
{
return (ncnn_mat_t)(new Mat(w));
}

ncnn_mat_t ncnn_mat_create_2d(int w, int h)
{
return (ncnn_mat_t)(new Mat(w, h));
}

ncnn_mat_t ncnn_mat_create_3d(int w, int h, int c)
{
return (ncnn_mat_t)(new Mat(w, h, c));
}

ncnn_mat_t ncnn_mat_create_1d_packed(int w, size_t elemsize, int elempack)
{
return (ncnn_mat_t)(new Mat(w, elemsize, elempack));
}

ncnn_mat_t ncnn_mat_create_2d_packed(int w, int h, size_t elemsize, int elempack)
{
return (ncnn_mat_t)(new Mat(w, h, elemsize, elempack));
}

ncnn_mat_t ncnn_mat_create_3d_packed(int w, int h, int c, size_t elemsize, int elempack)
{
return (ncnn_mat_t)(new Mat(w, h, c, elemsize, elempack));
}

void ncnn_mat_destroy(ncnn_mat_t mat)
{
delete (Mat*)mat;
}

int ncnn_mat_get_dims(ncnn_mat_t mat)
{
return ((Mat*)mat)->dims;
}

int ncnn_mat_get_w(ncnn_mat_t mat)
{
return ((Mat*)mat)->w;
}

int ncnn_mat_get_h(ncnn_mat_t mat)
{
return ((Mat*)mat)->h;
}

int ncnn_mat_get_c(ncnn_mat_t mat)
{
return ((Mat*)mat)->c;
}

size_t ncnn_mat_get_elemsize(ncnn_mat_t mat)
{
return ((Mat*)mat)->elemsize;
}

int ncnn_mat_get_elempack(ncnn_mat_t mat)
{
return ((Mat*)mat)->elempack;
}

size_t ncnn_mat_get_cstep(ncnn_mat_t mat)
{
return ((Mat*)mat)->cstep;
}

void* ncnn_mat_get_data(ncnn_mat_t mat)
{
return ((Mat*)mat)->data;
}

/* mat pixel api */
ncnn_mat_t ncnn_mat_from_pixels(const unsigned char* pixels, int type, int w, int h, int stride)
{
return (ncnn_mat_t)(new Mat(Mat::from_pixels(pixels, type, w, h, stride)));
}

ncnn_mat_t ncnn_mat_from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int stride, int target_width, int target_height)
{
return (ncnn_mat_t)(new Mat(Mat::from_pixels_resize(pixels, type, w, h, stride, target_width, target_height)));
}

void ncnn_mat_to_pixels(ncnn_mat_t mat, unsigned char* pixels, int type, int stride)
{
((Mat*)mat)->to_pixels(pixels, type, stride);
}

void ncnn_mat_to_pixels_resize(ncnn_mat_t mat, unsigned char* pixels, int type, int target_width, int target_height, int target_stride)
{
((Mat*)mat)->to_pixels_resize(pixels, type, target_width, target_height, target_stride);
}

void ncnn_mat_substract_mean_normalize(ncnn_mat_t mat, const float* mean_vals, const float* norm_vals)
{
((Mat*)mat)->substract_mean_normalize(mean_vals, norm_vals);
}

/* option api */
ncnn_option_t ncnn_option_create()
{
return (ncnn_option_t)(new Option());
}

void ncnn_option_destroy(ncnn_option_t opt)
{
delete (Option*)opt;
}

int ncnn_option_get_num_threads(ncnn_option_t opt)
{
return ((Option*)opt)->num_threads;
}

void ncnn_option_set_num_threads(ncnn_option_t opt, int num_threads)
{
((Option*)opt)->num_threads = num_threads;
}

int ncnn_option_get_use_vulkan_compute(ncnn_option_t opt)
{
#if NCNN_VULKAN
return ((Option*)opt)->use_vulkan_compute;
#else
return 0;
#endif
}

void ncnn_option_set_use_vulkan_compute(ncnn_option_t opt, int use_vulkan_compute)
{
#if NCNN_VULKAN
((Option*)opt)->use_vulkan_compute = use_vulkan_compute;
#else
(void)opt;
(void)use_vulkan_compute;
#endif
}

/* blob api */
const char* ncnn_blob_get_name(ncnn_blob_t blob)
{
#if NCNN_STRING
return ((Blob*)blob)->name.c_str();
#else
return "";
#endif
}

int ncnn_blob_get_producer(ncnn_blob_t blob)
{
return ((Blob*)blob)->producer;
}

int ncnn_blob_get_consumer_count(ncnn_blob_t blob)
{
return (int)((Blob*)blob)->consumers.size();
}

int ncnn_blob_get_consumer(ncnn_blob_t blob, int i)
{
return ((Blob*)blob)->consumers[i];
}

void ncnn_blob_get_shape(ncnn_blob_t blob, int* dims, int* w, int* h, int* c)
{
const Mat& shape = ((Blob*)blob)->shape;
*dims = shape.dims;
*w = shape.w;
*h = shape.h;
*c = shape.c;
}

/* layer api */
const char* ncnn_layer_get_name(ncnn_layer_t layer)
{
#if NCNN_STRING
return ((Layer*)layer)->name.c_str();
#else
return "";
#endif
}

int ncnn_layer_get_typeindex(ncnn_layer_t layer)
{
return ((Layer*)layer)->typeindex;
}

const char* ncnn_layer_get_type(ncnn_layer_t layer)
{
#if NCNN_STRING
return ((Layer*)layer)->type.c_str();
#else
return "";
#endif
}

int ncnn_layer_get_bottom_count(ncnn_layer_t layer)
{
return (int)((Layer*)layer)->bottoms.size();
}

int ncnn_layer_get_bottom(ncnn_layer_t layer, int i)
{
return ((Layer*)layer)->bottoms[i];
}

int ncnn_layer_get_top_count(ncnn_layer_t layer)
{
return (int)((Layer*)layer)->tops.size();
}

int ncnn_layer_get_top(ncnn_layer_t layer, int i)
{
return ((Layer*)layer)->tops[i];
}

void ncnn_blob_get_bottom_shape(ncnn_layer_t layer, int i, int* dims, int* w, int* h, int* c)
{
const Mat& shape = ((Layer*)layer)->bottom_shapes[i];
*dims = shape.dims;
*w = shape.w;
*h = shape.h;
*c = shape.c;
}

void ncnn_blob_get_top_shape(ncnn_layer_t layer, int i, int* dims, int* w, int* h, int* c)
{
const Mat& shape = ((Layer*)layer)->top_shapes[i];
*dims = shape.dims;
*w = shape.w;
*h = shape.h;
*c = shape.c;
}

/* net api */
ncnn_net_t ncnn_net_create()
{
return (ncnn_net_t)(new Net);
}

void ncnn_net_destroy(ncnn_net_t net)
{
delete (Net*)net;
}

void ncnn_net_set_option(ncnn_net_t net, ncnn_option_t opt)
{
((Net*)net)->opt = *((Option*)opt);
}

int ncnn_net_load_param(ncnn_net_t net, const char* path)
{
#if NCNN_STDIO && NCNN_STRING
return ((Net*)net)->load_param(path);
#else
return -1;
#endif
}

int ncnn_net_load_model(ncnn_net_t net, const char* path)
{
#if NCNN_STDIO && NCNN_STRING
return ((Net*)net)->load_model(path);
#else
return -1;
#endif
}

int ncnn_net_get_layer_count(ncnn_net_t net)
{
return (int)((Net*)net)->layers.size();
}

ncnn_layer_t ncnn_net_get_layer(ncnn_net_t net, int i)
{
return (ncnn_layer_t)((Net*)net)->layers[i];
}

int ncnn_net_get_blob_count(ncnn_net_t net)
{
return (int)((Net*)net)->blobs.size();
}

ncnn_blob_t ncnn_net_get_blob(ncnn_net_t net, int i)
{
return (ncnn_blob_t) & ((Net*)net)->blobs[i];
}

/* extractor api */
ncnn_extractor_t ncnn_extractor_create(ncnn_net_t net)
{
return (ncnn_extractor_t)(new Extractor(((Net*)net)->create_extractor()));
}

void ncnn_extractor_destroy(ncnn_extractor_t ex)
{
delete (Extractor*)ex;
}

void ncnn_extractor_set_option(ncnn_extractor_t ex, ncnn_option_t opt)
{
((Extractor*)ex)->set_num_threads(((Option*)opt)->num_threads);
#if NCNN_VULKAN
((Extractor*)ex)->set_vulkan_compute(((Option*)opt)->use_vulkan_compute);
#endif
}

int ncnn_extractor_input(ncnn_extractor_t ex, const char* name, ncnn_mat_t mat)
{
#if NCNN_STRING
return ((Extractor*)ex)->input(name, *((Mat*)mat));
#else
return -1;
#endif
}

int ncnn_extractor_extract(ncnn_extractor_t ex, const char* name, ncnn_mat_t* mat)
{
#if NCNN_STRING
Mat mat0;
int ret = ((Extractor*)ex)->extract(name, mat0);
*mat = (ncnn_mat_t)(new Mat(mat0));
return ret;
#else
return -1;
#endif
}

#ifdef __cplusplus
} /* extern "C" */
#endif

+ 130
- 0
src/c_api.h View File

@@ -0,0 +1,130 @@
/* Tencent is pleased to support the open source community by making ncnn available.
*
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

#ifndef NCNN_C_API_H
#define NCNN_C_API_H

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/* mat api */
typedef struct __ncnn_mat_t* ncnn_mat_t;

ncnn_mat_t ncnn_mat_create();
ncnn_mat_t ncnn_mat_create_1d(int w);
ncnn_mat_t ncnn_mat_create_2d(int w, int h);
ncnn_mat_t ncnn_mat_create_3d(int w, int h, int c);
ncnn_mat_t ncnn_mat_create_1d_packed(int w, size_t elemsize, int elempack);
ncnn_mat_t ncnn_mat_create_2d_packed(int w, int h, size_t elemsize, int elempack);
ncnn_mat_t ncnn_mat_create_3d_packed(int w, int h, int c, size_t elemsize, int elempack);
void ncnn_mat_destroy(ncnn_mat_t mat);

int ncnn_mat_get_dims(ncnn_mat_t mat);
int ncnn_mat_get_w(ncnn_mat_t mat);
int ncnn_mat_get_h(ncnn_mat_t mat);
int ncnn_mat_get_c(ncnn_mat_t mat);
size_t ncnn_mat_get_elemsize(ncnn_mat_t mat);
int ncnn_mat_get_elempack(ncnn_mat_t mat);
size_t ncnn_mat_get_cstep(ncnn_mat_t mat);
void* ncnn_mat_get_data(ncnn_mat_t mat);

/* mat pixel api */
#define NCNN_MAT_PIXEL_RGB 1
#define NCNN_MAT_PIXEL_BGR 2
#define NCNN_MAT_PIXEL_GRAY 3
#define NCNN_MAT_PIXEL_RGBA 4
#define NCNN_MAT_PIXEL_BGRA 5
#define NCNN_MAT_PIXEL_X2Y(X, Y) (X | (Y << 16))
ncnn_mat_t ncnn_mat_from_pixels(const unsigned char* pixels, int type, int w, int h, int stride);
ncnn_mat_t ncnn_mat_from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int stride, int target_width, int target_height);
void ncnn_mat_to_pixels(ncnn_mat_t mat, unsigned char* pixels, int type, int stride);
void ncnn_mat_to_pixels_resize(ncnn_mat_t mat, unsigned char* pixels, int type, int target_width, int target_height, int target_stride);

void ncnn_mat_substract_mean_normalize(ncnn_mat_t mat, const float* mean_vals, const float* norm_vals);

/* option api */
typedef struct __ncnn_option_t* ncnn_option_t;

ncnn_option_t ncnn_option_create();
void ncnn_option_destroy(ncnn_option_t opt);

int ncnn_option_get_num_threads(ncnn_option_t opt);
void ncnn_option_set_num_threads(ncnn_option_t opt, int num_threads);

int ncnn_option_get_use_vulkan_compute(ncnn_option_t opt);
void ncnn_option_set_use_vulkan_compute(ncnn_option_t opt, int use_vulkan_compute);

/* blob api */
typedef struct __ncnn_blob_t* ncnn_blob_t;

const char* ncnn_blob_get_name(ncnn_blob_t blob);

int ncnn_blob_get_producer(ncnn_blob_t blob);
int ncnn_blob_get_consumer_count(ncnn_blob_t blob);
int ncnn_blob_get_consumer(ncnn_blob_t blob, int i);

void ncnn_blob_get_shape(ncnn_blob_t blob, int* dims, int* w, int* h, int* c);

/* layer api */
typedef struct __ncnn_layer_t* ncnn_layer_t;

const char* ncnn_layer_get_name(ncnn_layer_t layer);

int ncnn_layer_get_typeindex(ncnn_layer_t layer);
const char* ncnn_layer_get_type(ncnn_layer_t layer);

int ncnn_layer_get_bottom_count(ncnn_layer_t layer);
int ncnn_layer_get_bottom(ncnn_layer_t layer, int i);
int ncnn_layer_get_top_count(ncnn_layer_t layer);
int ncnn_layer_get_top(ncnn_layer_t layer, int i);

void ncnn_blob_get_bottom_shape(ncnn_layer_t layer, int i, int* dims, int* w, int* h, int* c);
void ncnn_blob_get_top_shape(ncnn_layer_t layer, int i, int* dims, int* w, int* h, int* c);

/* net api */
typedef struct __ncnn_net_t* ncnn_net_t;

ncnn_net_t ncnn_net_create();
void ncnn_net_destroy(ncnn_net_t net);

void ncnn_net_set_option(ncnn_net_t net, ncnn_option_t opt);

int ncnn_net_load_param(ncnn_net_t net, const char* path);
int ncnn_net_load_model(ncnn_net_t net, const char* path);

int ncnn_net_get_layer_count(ncnn_net_t net);
ncnn_layer_t ncnn_net_get_layer(ncnn_net_t net, int i);
int ncnn_net_get_blob_count(ncnn_net_t net);
ncnn_blob_t ncnn_net_get_blob(ncnn_net_t net, int i);

/* extractor api */
typedef struct __ncnn_extractor_t* ncnn_extractor_t;

ncnn_extractor_t ncnn_extractor_create(ncnn_net_t net);
void ncnn_extractor_destroy(ncnn_extractor_t ex);

void ncnn_extractor_set_option(ncnn_extractor_t ex, ncnn_option_t opt);

int ncnn_extractor_input(ncnn_extractor_t ex, const char* name, ncnn_mat_t mat);
int ncnn_extractor_extract(ncnn_extractor_t ex, const char* name, ncnn_mat_t* mat);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif // NCNN_C_API_H

+ 4
- 3
src/net.h View File

@@ -123,6 +123,10 @@ public:
// construct an Extractor from network
Extractor create_extractor() const;

public:
std::vector<Blob> blobs;
std::vector<Layer*> layers;

protected:
// parse the structure of network
// fuse int8 op dequantize and quantize by requantize
@@ -154,9 +158,6 @@ protected:
#endif // NCNN_VULKAN

protected:
std::vector<Blob> blobs;
std::vector<Layer*> layers;

std::vector<layer_registry_entry> custom_layer_registry;

#if NCNN_VULKAN


Loading…
Cancel
Save