From 0d5baaae256f7c3cab15d27aa8ffbf5e6db68318 Mon Sep 17 00:00:00 2001
From: zhangmeng <775834166@qq.com>
Date: 星期一, 09 十二月 2019 13:20:27 +0800
Subject: [PATCH] update

---
 .gitignore                |    2 
 csrc/struct.h             |   30 
 detector.h                |   22 
 darknet/include/yolo.hpp  |  641 +++++++++++++++++++
 goyolo.go                 |  216 ++++++
 csrc/yolo.cpp             |  159 ++++
 csrc/yolo.h               |   42 +
 darknet/include/darknet.h |  812 ++++++++++++++++++++++++
 darknet/lib/libdarknet.so |    0 
 detector.cpp              |   44 +
 10 files changed, 1,967 insertions(+), 1 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8365624..faf104a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
 # Compiled Object files, Static and Dynamic libs (Shared Objects)
 *.o
 *.a
-*.so
 
 # Folders
 _obj
@@ -21,3 +20,4 @@
 
 *.exe
 *.test
+libyolo.so
diff --git a/csrc/struct.h b/csrc/struct.h
new file mode 100644
index 0000000..0b2e53c
--- /dev/null
+++ b/csrc/struct.h
@@ -0,0 +1,30 @@
+#ifndef _yolo_struct_h_
+#define _yolo_struct_h_
+
+typedef struct _cPOINT {
+    int x;
+    int y;
+} cPOINT;
+
+typedef struct _cRECT {
+    int left;
+    int top;
+    int right;
+    int bottom;
+} cRECT;
+
+typedef struct _cIMAGE{
+    unsigned char *data;
+    int width;
+    int height;
+    int channel;
+} cIMAGE;
+
+typedef struct _cObjInfo
+{
+    cRECT rcObj;
+    int typ;
+    float prob;
+} cObjInfo;
+
+#endif
\ No newline at end of file
diff --git a/csrc/yolo.cpp b/csrc/yolo.cpp
new file mode 100644
index 0000000..b217ff5
--- /dev/null
+++ b/csrc/yolo.cpp
@@ -0,0 +1,159 @@
+#include "yolo.h"
+
+#include "yolo.hpp"
+
+#include <fstream>
+#include <vector>
+#include <stdexcept>
+
+#include "struct.h"
+
+namespace cppyolo
+{
+    sdkyolo::sdkyolo(const char *cfg, const char *weights, const char *name, const int gpu)
+    :det_(NULL)
+    ,infos_(NULL)
+    ,obj_cnt_(0)
+    ,image_(NULL)
+    ,width_(0)
+    ,height_(0)
+    ,channel_(0)
+    {
+        names_.clear();
+        if (!init(cfg, weights, name, gpu)){
+			throw std::runtime_error("init yolo error");
+        }
+    }
+
+    sdkyolo::~sdkyolo()
+    {
+        if (det_) delete det_;
+    }
+
+    static void objects_names_from_file(std::string filename, std::vector<std::string> &names){
+        std::ifstream file(filename);
+
+        if (!file.is_open()){
+            printf("open %s file error\n", filename.c_str());
+            return;
+        }
+        for(std::string line; getline(file, line);) names.push_back(line);
+
+        printf("names count %d\n", names.size());
+    }
+
+    const char* sdkyolo::obj_name_by_type(const int typ)const{
+        if(names_.empty() || typ < 0 || typ >= names_.size()) return NULL;
+        return names_.at(typ).c_str();
+    }
+
+    bool sdkyolo::init(const char *cfg, const char *weights, const char *name, const int gpu){
+        if (det_) return true;
+
+        if(!cfg || !weights || !name){
+            printf("init Detector error\n");
+            return false;
+        }
+    
+        if(names_.empty())
+            objects_names_from_file(name, names_);
+
+        det_ = new Detector(cfg, weights, gpu);
+        return true;
+    }
+
+    int sdkyolo::buffer_to_image(const unsigned char *data, const int w, const int h, const int color_channel){
+        
+        int size = w*h;
+        int size2 = size*2;
+    
+        int c = color_channel;
+        if (w != width_ || h != height_ || color_channel != channel_){
+            if (image_){
+                free(image_->data);
+                delete image_;
+            }
+            image_ = new image_t;
+            image_->h = h;
+            image_->w = w;
+            image_->c = c;
+            image_->data = (float*)calloc(h*w*c, sizeof(float));
+        }
+
+        // image im = make_image(w, h, c);
+        const unsigned char *srcData = data;
+    
+        int count = 0;
+        switch(c){
+            case 1:{
+                for (; count < size; ){
+                    image_->data[count] = 
+                    image_->data[w*h + count] = 
+                    image_->data[w*h*2 + count] = 
+                    (float)(srcData[count])/255.0;
+    
+                    ++count;
+                }
+                break;
+            }
+            case 3:{
+                float* desData = image_->data;
+    
+                for(int i = 0;i<size;i++){
+                    *(desData) = *(srcData + 2) /255.0f;
+                    *(desData+size) = *(srcData + 1) /255.0f;
+                    *(desData+size2) = *(srcData) /255.0f;
+    
+                    desData++;
+                    srcData+=3;
+                }
+                break;
+            }
+    
+            default:
+                printf("Channel number not supported.\n");
+                break;
+        }
+
+	    return 0;
+    }
+
+    int sdkyolo::detect(const cIMAGE *img, const float thrsh, const bool use_mean, void **objs, int *objCount){
+        if (!det_) return -1;
+
+        const int color_channel = img->channel;
+        buffer_to_image(img->data, img->width, img->height, color_channel);
+
+        
+        std::vector<bbox_t> result_vec = det_->detect(*image_, thrsh, use_mean);
+		// det->free_image(*im);
+        // delete im;
+
+        if (obj_cnt_ < result_vec.size()){
+            free(infos_);
+
+            obj_cnt_ = result_vec.size();
+            infos_ = (cObjInfo*)malloc(obj_cnt_ * sizeof(cObjInfo));
+        }
+
+        int count = 0;
+        for(auto &i : result_vec){
+            
+            cObjInfo info;
+            info.typ = i.obj_id;
+            info.prob = i.prob;
+            info.rcObj.left = i.x;
+			info.rcObj.top = i.y;
+			info.rcObj.right = i.x+i.w;
+            info.rcObj.bottom = i.y+i.h;
+            
+            infos_[count++] = info;
+        }
+        
+        *objCount = count;
+        *objs = infos_;
+
+        return count;
+    }
+
+} // namespace cppyolo
diff --git a/csrc/yolo.h b/csrc/yolo.h
new file mode 100644
index 0000000..caf4e2b
--- /dev/null
+++ b/csrc/yolo.h
@@ -0,0 +1,42 @@
+#ifndef _cpp_yolo_h_
+#define _cpp_yolo_h_
+
+#include <vector>
+#include <string>
+
+#include "struct.h"
+
+struct image_t;
+
+class Detector;
+
+namespace cppyolo
+{
+    class sdkyolo{
+
+    public: 
+        sdkyolo(const char *cfg, const char *weights, const char *name, const int gpu);
+        ~sdkyolo();
+
+    public: 
+        int detect(const cIMAGE *img, const float thrsh, const bool use_mean, void **objs, int *objCount);
+        const char* obj_name_by_type(const int typ)const;
+    private: 
+        bool init(const char *cfg, const char *weights, const char *name, const int gpu);
+        int buffer_to_image(const unsigned char *data, const int w, const int h, const int color_channel);
+
+    private: 
+        Detector *det_;
+        cObjInfo *infos_;
+        int obj_cnt_;
+        std::vector<std::string> names_;
+
+        image_t *image_;
+        int width_;
+        int height_;
+        int channel_;
+    };
+} // namespace cppyolo
+
+
+#endif
\ No newline at end of file
diff --git a/darknet/include/darknet.h b/darknet/include/darknet.h
new file mode 100755
index 0000000..c3f5628
--- /dev/null
+++ b/darknet/include/darknet.h
@@ -0,0 +1,812 @@
+#ifndef DARKNET_API
+#define DARKNET_API
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+
+#define SECRET_NUM -1234
+extern int gpu_index;
+
+#ifdef GPU
+    #define BLOCK 512
+
+    #include "cuda_runtime.h"
+    #include "curand.h"
+    #include "cublas_v2.h"
+
+    #ifdef CUDNN
+    #include "cudnn.h"
+    #endif
+#endif
+
+#ifndef __cplusplus
+    #ifdef OPENCV
+    #include "opencv2/highgui/highgui_c.h"
+    #include "opencv2/imgproc/imgproc_c.h"
+    #include "opencv2/core/version.hpp"
+    #if CV_MAJOR_VERSION == 3
+    #include "opencv2/videoio/videoio_c.h"
+    #include "opencv2/imgcodecs/imgcodecs_c.h"
+    #endif
+    #endif
+#endif
+
+typedef struct{
+    int classes;
+    char **names;
+} metadata;
+
+metadata get_metadata(char *file);
+
+typedef struct{
+    int *leaf;
+    int n;
+    int *parent;
+    int *child;
+    int *group;
+    char **name;
+
+    int groups;
+    int *group_size;
+    int *group_offset;
+} tree;
+tree *read_tree(char *filename);
+
+typedef enum{
+    LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN
+} ACTIVATION;
+
+typedef enum{
+    MULT, ADD, SUB, DIV
+} BINARY_ACTIVATION;
+
+typedef enum {
+    CONVOLUTIONAL,
+    DECONVOLUTIONAL,
+    CONNECTED,
+    MAXPOOL,
+    SOFTMAX,
+    DETECTION,
+    DROPOUT,
+    CROP,
+    ROUTE,
+    COST,
+    NORMALIZATION,
+    AVGPOOL,
+    LOCAL,
+    SHORTCUT,
+    ACTIVE,
+    RNN,
+    GRU,
+    LSTM,
+    CRNN,
+    BATCHNORM,
+    NETWORK,
+    XNOR,
+    REGION,
+    YOLO,
+    REORG,
+    UPSAMPLE,
+    LOGXENT,
+    L2NORM,
+    BLANK
+} LAYER_TYPE;
+
+typedef enum{
+    SSE, MASKED, L1, SEG, SMOOTH,WGAN
+} COST_TYPE;
+
+typedef struct{
+    int batch;
+    float learning_rate;
+    float momentum;
+    float decay;
+    int adam;
+    float B1;
+    float B2;
+    float eps;
+    int t;
+} update_args;
+
+struct network;
+typedef struct network network;
+
+struct layer;
+typedef struct layer layer;
+
+struct layer{
+    LAYER_TYPE type;
+    ACTIVATION activation;
+    COST_TYPE cost_type;
+    void (*forward)   (struct layer, struct network);
+    void (*backward)  (struct layer, struct network);
+    void (*update)    (struct layer, update_args);
+    void (*forward_gpu)   (struct layer, struct network);
+    void (*backward_gpu)  (struct layer, struct network);
+    void (*update_gpu)    (struct layer, update_args);
+    int batch_normalize;
+    int shortcut;
+    int batch;
+    int forced;
+    int flipped;
+    int inputs;
+    int outputs;
+    int nweights;
+    int nbiases;
+    int extra;
+    int truths;
+    int h,w,c;
+    int out_h, out_w, out_c;
+    int n;
+    int max_boxes;
+    int groups;
+    int size;
+    int side;
+    int stride;
+    int reverse;
+    int flatten;
+    int spatial;
+    int pad;
+    int sqrt;
+    int flip;
+    int index;
+    int binary;
+    int xnor;
+    int steps;
+    int hidden;
+    int truth;
+    float smooth;
+    float dot;
+    float angle;
+    float jitter;
+    float saturation;
+    float exposure;
+    float shift;
+    float ratio;
+    float learning_rate_scale;
+    float clip;
+    int softmax;
+    int classes;
+    int coords;
+    int background;
+    int rescore;
+    int objectness;
+    int joint;
+    int noadjust;
+    int reorg;
+    int log;
+    int tanh;
+    int *mask;
+    int total;
+
+    float alpha;
+    float beta;
+    float kappa;
+
+    float coord_scale;
+    float object_scale;
+    float noobject_scale;
+    float mask_scale;
+    float class_scale;
+    int bias_match;
+    int random;
+    float ignore_thresh;
+    float truth_thresh;
+    float thresh;
+    float focus;
+    int classfix;
+    int absolute;
+
+    int onlyforward;
+    int stopbackward;
+    int dontload;
+    int dontsave;
+    int dontloadscales;
+
+    float temperature;
+    float probability;
+    float scale;
+
+    char  * cweights;
+    int   * indexes;
+    int   * input_layers;
+    int   * input_sizes;
+    int   * map;
+    float * rand;
+    float * cost;
+    float * state;
+    float * prev_state;
+    float * forgot_state;
+    float * forgot_delta;
+    float * state_delta;
+    float * combine_cpu;
+    float * combine_delta_cpu;
+
+    float * concat;
+    float * concat_delta;
+
+    float * binary_weights;
+
+    float * biases;
+    float * bias_updates;
+
+    float * scales;
+    float * scale_updates;
+
+    float * weights;
+    float * weight_updates;
+
+    float * delta;
+    float * output;
+    float * loss;
+    float * squared;
+    float * norms;
+
+    float * spatial_mean;
+    float * mean;
+    float * variance;
+
+    float * mean_delta;
+    float * variance_delta;
+
+    float * rolling_mean;
+    float * rolling_variance;
+
+    float * x;
+    float * x_norm;
+
+    float * m;
+    float * v;
+    
+    float * bias_m;
+    float * bias_v;
+    float * scale_m;
+    float * scale_v;
+
+
+    float *z_cpu;
+    float *r_cpu;
+    float *h_cpu;
+    float * prev_state_cpu;
+
+    float *temp_cpu;
+    float *temp2_cpu;
+    float *temp3_cpu;
+
+    float *dh_cpu;
+    float *hh_cpu;
+    float *prev_cell_cpu;
+    float *cell_cpu;
+    float *f_cpu;
+    float *i_cpu;
+    float *g_cpu;
+    float *o_cpu;
+    float *c_cpu;
+    float *dc_cpu; 
+
+    float * binary_input;
+
+    struct layer *input_layer;
+    struct layer *self_layer;
+    struct layer *output_layer;
+
+    struct layer *reset_layer;
+    struct layer *update_layer;
+    struct layer *state_layer;
+
+    struct layer *input_gate_layer;
+    struct layer *state_gate_layer;
+    struct layer *input_save_layer;
+    struct layer *state_save_layer;
+    struct layer *input_state_layer;
+    struct layer *state_state_layer;
+
+    struct layer *input_z_layer;
+    struct layer *state_z_layer;
+
+    struct layer *input_r_layer;
+    struct layer *state_r_layer;
+
+    struct layer *input_h_layer;
+    struct layer *state_h_layer;
+	
+    struct layer *wz;
+    struct layer *uz;
+    struct layer *wr;
+    struct layer *ur;
+    struct layer *wh;
+    struct layer *uh;
+    struct layer *uo;
+    struct layer *wo;
+    struct layer *uf;
+    struct layer *wf;
+    struct layer *ui;
+    struct layer *wi;
+    struct layer *ug;
+    struct layer *wg;
+
+    tree *softmax_tree;
+
+    size_t workspace_size;
+
+#ifdef GPU
+    int *indexes_gpu;
+
+    float *z_gpu;
+    float *r_gpu;
+    float *h_gpu;
+
+    float *temp_gpu;
+    float *temp2_gpu;
+    float *temp3_gpu;
+
+    float *dh_gpu;
+    float *hh_gpu;
+    float *prev_cell_gpu;
+    float *cell_gpu;
+    float *f_gpu;
+    float *i_gpu;
+    float *g_gpu;
+    float *o_gpu;
+    float *c_gpu;
+    float *dc_gpu; 
+
+    float *m_gpu;
+    float *v_gpu;
+    float *bias_m_gpu;
+    float *scale_m_gpu;
+    float *bias_v_gpu;
+    float *scale_v_gpu;
+
+    float * combine_gpu;
+    float * combine_delta_gpu;
+
+    float * prev_state_gpu;
+    float * forgot_state_gpu;
+    float * forgot_delta_gpu;
+    float * state_gpu;
+    float * state_delta_gpu;
+    float * gate_gpu;
+    float * gate_delta_gpu;
+    float * save_gpu;
+    float * save_delta_gpu;
+    float * concat_gpu;
+    float * concat_delta_gpu;
+
+    float * binary_input_gpu;
+    float * binary_weights_gpu;
+
+    float * mean_gpu;
+    float * variance_gpu;
+
+    float * rolling_mean_gpu;
+    float * rolling_variance_gpu;
+
+    float * variance_delta_gpu;
+    float * mean_delta_gpu;
+
+    float * x_gpu;
+    float * x_norm_gpu;
+    float * weights_gpu;
+    float * weight_updates_gpu;
+    float * weight_change_gpu;
+
+    float * biases_gpu;
+    float * bias_updates_gpu;
+    float * bias_change_gpu;
+
+    float * scales_gpu;
+    float * scale_updates_gpu;
+    float * scale_change_gpu;
+
+    float * output_gpu;
+    float * loss_gpu;
+    float * delta_gpu;
+    float * rand_gpu;
+    float * squared_gpu;
+    float * norms_gpu;
+#ifdef CUDNN
+    cudnnTensorDescriptor_t srcTensorDesc, dstTensorDesc;
+    cudnnTensorDescriptor_t dsrcTensorDesc, ddstTensorDesc;
+    cudnnTensorDescriptor_t normTensorDesc;
+    cudnnFilterDescriptor_t weightDesc;
+    cudnnFilterDescriptor_t dweightDesc;
+    cudnnConvolutionDescriptor_t convDesc;
+    cudnnConvolutionFwdAlgo_t fw_algo;
+    cudnnConvolutionBwdDataAlgo_t bd_algo;
+    cudnnConvolutionBwdFilterAlgo_t bf_algo;
+#endif
+#endif
+};
+
+void free_layer(layer);
+
+typedef enum {
+    CONSTANT, STEP, EXP, POLY, STEPS, SIG, RANDOM
+} learning_rate_policy;
+
+typedef struct network{
+    int n;
+    int batch;
+    size_t *seen;
+    int *t;
+    float epoch;
+    int subdivisions;
+    layer *layers;
+    float *output;
+    learning_rate_policy policy;
+
+    float learning_rate;
+    float momentum;
+    float decay;
+    float gamma;
+    float scale;
+    float power;
+    int time_steps;
+    int step;
+    int max_batches;
+    float *scales;
+    int   *steps;
+    int num_steps;
+    int burn_in;
+
+    int adam;
+    float B1;
+    float B2;
+    float eps;
+
+    int inputs;
+    int outputs;
+    int truths;
+    int notruth;
+    int h, w, c;
+    int max_crop;
+    int min_crop;
+    float max_ratio;
+    float min_ratio;
+    int center;
+    float angle;
+    float aspect;
+    float exposure;
+    float saturation;
+    float hue;
+    int random;
+
+    int gpu_index;
+    tree *hierarchy;
+
+    float *input;
+    float *truth;
+    float *delta;
+    float *workspace;
+    int train;
+    int index;
+    float *cost;
+    float clip;
+
+#ifdef GPU
+    float *input_gpu;
+    float *truth_gpu;
+    float *delta_gpu;
+    float *output_gpu;
+#endif
+
+} network;
+
+typedef struct {
+    int w;
+    int h;
+    float scale;
+    float rad;
+    float dx;
+    float dy;
+    float aspect;
+} augment_args;
+
+typedef struct {
+    int w;
+    int h;
+    int c;
+    float *data;
+} image;
+
+typedef struct{
+    float x, y, w, h;
+} box;
+
+typedef struct detection{
+    box bbox;
+    int classes;
+    float *prob;
+    float *mask;
+    float objectness;
+    int sort_class;
+} detection;
+
+typedef struct matrix{
+    int rows, cols;
+    float **vals;
+} matrix;
+
+
+typedef struct{
+    int w, h;
+    matrix X;
+    matrix y;
+    int shallow;
+    int *num_boxes;
+    box **boxes;
+} data;
+
+typedef enum {
+    CLASSIFICATION_DATA, DETECTION_DATA, CAPTCHA_DATA, REGION_DATA, IMAGE_DATA, COMPARE_DATA, WRITING_DATA, SWAG_DATA, TAG_DATA, OLD_CLASSIFICATION_DATA, STUDY_DATA, DET_DATA, SUPER_DATA, LETTERBOX_DATA, REGRESSION_DATA, SEGMENTATION_DATA, INSTANCE_DATA
+} data_type;
+
+typedef struct load_args{
+    int threads;
+    char **paths;
+    char *path;
+    int n;
+    int m;
+    char **labels;
+    int h;
+    int w;
+    int out_w;
+    int out_h;
+    int nh;
+    int nw;
+    int num_boxes;
+    int min, max, size;
+    int classes;
+    int background;
+    int scale;
+    int center;
+    int coords;
+    float jitter;
+    float angle;
+    float aspect;
+    float saturation;
+    float exposure;
+    float hue;
+    data *d;
+    image *im;
+    image *resized;
+    data_type type;
+    tree *hierarchy;
+} load_args;
+
+typedef struct{
+    int id;
+    float x,y,w,h;
+    float left, right, top, bottom;
+} box_label;
+
+
+void free_data(data d);
+
+typedef struct node{
+    void *val;
+    struct node *next;
+    struct node *prev;
+} node;
+
+typedef struct list{
+    int size;
+    node *front;
+    node *back;
+} list;
+
+#ifdef __cplusplus
+extern "C" {               // 鍛婅瘔缂栬瘧鍣ㄤ笅鍒椾唬鐮佽浠閾炬帴绾﹀畾鐨勬ā寮忚繘琛岄摼鎺�
+#endif
+
+//#todo
+network *load_network(char *cfg, char *weights, int clear);
+load_args get_base_args(network *net);
+
+pthread_t load_data(load_args args);
+list *read_data_cfg(char *filename);
+list *read_cfg(char *filename);
+unsigned char *read_file(char *filename);
+data resize_data(data orig, int w, int h);
+data *tile_data(data orig, int divs, int size);
+data select_data(data *orig, int *inds);
+
+void forward_network(network *net);
+void backward_network(network *net);
+void update_network(network *net);
+
+
+float dot_cpu(int N, float *X, int INCX, float *Y, int INCY);
+void axpy_cpu(int N, float ALPHA, float *X, int INCX, float *Y, int INCY);
+void copy_cpu(int N, float *X, int INCX, float *Y, int INCY);
+void scal_cpu(int N, float ALPHA, float *X, int INCX);
+void fill_cpu(int N, float ALPHA, float * X, int INCX);
+void normalize_cpu(float *x, float *mean, float *variance, int batch, int filters, int spatial);
+void softmax(float *input, int n, float temp, int stride, float *output);
+
+int best_3d_shift_r(image a, image b, int min, int max);
+
+image get_label(image **characters, char *string, int size);
+void draw_label(image a, int r, int c, image label, const float *rgb);
+void save_image_png(image im, const char *name);
+void get_next_batch(data d, int n, int offset, float *X, float *y);
+void grayscale_image_3c(image im);
+void normalize_image(image p);
+void matrix_to_csv(matrix m);
+float train_network_sgd(network *net, data d, int n);
+void rgbgr_image(image im);
+data copy_data(data d);
+data concat_data(data d1, data d2);
+data load_cifar10_data(char *filename);
+float matrix_topk_accuracy(matrix truth, matrix guess, int k);
+void matrix_add_matrix(matrix from, matrix to);
+void scale_matrix(matrix m, float scale);
+matrix csv_to_matrix(char *filename);
+float *network_accuracies(network *net, data d, int n);
+float train_network_datum(network *net);
+image make_random_image(int w, int h, int c);
+
+void denormalize_connected_layer(layer l);
+void denormalize_convolutional_layer(layer l);
+void statistics_connected_layer(layer l);
+void rescale_weights(layer l, float scale, float trans);
+void rgbgr_weights(layer l);
+image *get_weights(layer l);
+
+void demo(char *cfgfile, char *weightfile, float thresh, int cam_index, const char *filename, char **names, int classes, int frame_skip, char *prefix, int avg, float hier_thresh, int w, int h, int fps, int fullscreen);
+void get_detection_detections(layer l, int w, int h, float thresh, detection *dets);
+
+char *option_find_str(list *l, char *key, char *def);
+int option_find_int(list *l, char *key, int def);
+int option_find_int_quiet(list *l, char *key, int def);
+
+network *parse_network_cfg(char *filename);
+void save_weights(network *net, char *filename);
+void load_weights(network *net, char *filename);
+void save_weights_upto(network *net, char *filename, int cutoff);
+void load_weights_upto(network *net, char *filename, int start, int cutoff);
+
+void zero_objectness(layer l);
+void get_region_detections(layer l, int w, int h, int netw, int neth, float thresh, int *map, float tree_thresh, int relative, detection *dets);
+int get_yolo_detections(layer l, int w, int h, int netw, int neth, float thresh, int *map, int relative, detection *dets);
+void free_network(network *net);
+void set_batch_network(network *net, int b);
+void set_temp_network(network *net, float t);
+image load_image(char *filename, int w, int h, int c);
+image load_image_color(char *filename, int w, int h);
+image make_image(int w, int h, int c);
+image resize_image(image im, int w, int h);
+void censor_image(image im, int dx, int dy, int w, int h);
+image letterbox_image(image im, int w, int h);
+image crop_image(image im, int dx, int dy, int w, int h);
+image center_crop_image(image im, int w, int h);
+image resize_min(image im, int min);
+image resize_max(image im, int max);
+image threshold_image(image im, float thresh);
+image mask_to_rgb(image mask);
+int resize_network(network *net, int w, int h);
+void free_matrix(matrix m);
+void test_resize(char *filename);
+void save_image(image p, const char *name);
+void show_image(image p, const char *name);
+image copy_image(image p);
+void draw_box_width(image a, int x1, int y1, int x2, int y2, int w, float r, float g, float b);
+float get_current_rate(network *net);
+void composite_3d(char *f1, char *f2, char *out, int delta);
+data load_data_old(char **paths, int n, int m, char **labels, int k, int w, int h);
+size_t get_current_batch(network *net);
+void constrain_image(image im);
+image get_network_image_layer(network *net, int i);
+layer get_network_output_layer(network *net);
+void top_predictions(network *net, int n, int *index);
+void flip_image(image a);
+image float_to_image(int w, int h, int c, float *data);
+void ghost_image(image source, image dest, int dx, int dy);
+float network_accuracy(network *net, data d);
+void random_distort_image(image im, float hue, float saturation, float exposure);
+void fill_image(image m, float s);
+image grayscale_image(image im);
+void rotate_image_cw(image im, int times);
+double what_time_is_it_now();
+image rotate_image(image m, float rad);
+void visualize_network(network *net);
+float box_iou(box a, box b);
+data load_all_cifar10();
+box_label *read_boxes(char *filename, int *n);
+box float_to_box(float *f, int stride);
+void draw_detections(image im, detection *dets, int num, float thresh, char **names, image **alphabet, int classes);
+
+matrix network_predict_data(network *net, data test);
+image **load_alphabet();
+image get_network_image(network *net);
+float *network_predict(network *net, float *input);
+
+int network_width(network *net);
+int network_height(network *net);
+float *network_predict_image(network *net, image im);
+void network_detect(network *net, image im, float thresh, float hier_thresh, float nms, detection *dets);
+detection *get_network_boxes(network *net, int w, int h, float thresh, float hier, int *map, int relative, int *num);
+void free_detections(detection *dets, int n);
+
+void reset_network_state(network *net, int b);
+
+char **get_labels(char *filename);
+void do_nms_obj(detection *dets, int total, int classes, float thresh);
+void do_nms_sort(detection *dets, int total, int classes, float thresh);
+
+matrix make_matrix(int rows, int cols);
+
+void free_image(image m);
+float train_network(network *net, data d);
+pthread_t load_data_in_thread(load_args args);
+void load_data_blocking(load_args args);
+list *get_paths(char *filename);
+void hierarchy_predictions(float *predictions, int n, tree *hier, int only_leaves, int stride);
+void change_leaves(tree *t, char *leaf_list);
+
+int find_int_arg(int argc, char **argv, char *arg, int def);
+float find_float_arg(int argc, char **argv, char *arg, float def);
+int find_arg(int argc, char* argv[], char *arg);
+char *find_char_arg(int argc, char **argv, char *arg, char *def);
+char *basecfg(char *cfgfile);
+void find_replace(char *str, char *orig, char *rep, char *output);
+void free_ptrs(void **ptrs, int n);
+char *fgetl(FILE *fp);
+void strip(char *s);
+float sec(clock_t clocks);
+void **list_to_array(list *l);
+void top_k(float *a, int n, int k, int *index);
+int *read_map(char *filename);
+void error(const char *s);
+int max_index(float *a, int n);
+int max_int_index(int *a, int n);
+int sample_array(float *a, int n);
+int *random_index_order(int min, int max);
+void free_list(list *l);
+float mse_array(float *a, int n);
+float variance_array(float *a, int n);
+float mag_array(float *a, int n);
+void scale_array(float *a, int n, float s);
+float mean_array(float *a, int n);
+float sum_array(float *a, int n);
+void normalize_array(float *a, int n);
+int *read_intlist(char *s, int *n, int d);
+size_t rand_size_t();
+float rand_normal();
+float rand_uniform(float min, float max);
+
+#ifdef GPU
+void axpy_gpu(int N, float ALPHA, float * X, int INCX, float * Y, int INCY);
+void fill_gpu(int N, float ALPHA, float * X, int INCX);
+void scal_gpu(int N, float ALPHA, float * X, int INCX);
+void copy_gpu(int N, float * X, int INCX, float * Y, int INCY);
+
+void cuda_set_device(int n);
+void cuda_free(float *x_gpu);
+float *cuda_make_array(float *x, size_t n);
+void cuda_pull_array(float *x_gpu, float *x, size_t n);
+float cuda_mag_array(float *x_gpu, size_t n);
+void cuda_push_array(float *x_gpu, float *x, size_t n);
+
+void forward_network_gpu(network *net);
+void backward_network_gpu(network *net);
+void update_network_gpu(network *net);
+
+float train_networks(network **nets, int n, data d, int interval);
+void sync_nets(network **nets, int n, int interval);
+void harmless_update_network_gpu(network *net);
+#endif
+
+#ifndef __cplusplus
+#ifdef OPENCV
+image get_image_from_stream(CvCapture *cap);
+#endif
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/darknet/include/yolo.hpp b/darknet/include/yolo.hpp
new file mode 100644
index 0000000..00c2a5b
--- /dev/null
+++ b/darknet/include/yolo.hpp
@@ -0,0 +1,641 @@
+#pragma once
+#ifdef YOLODLL_EXPORTS
+#if defined(_MSC_VER)
+#define YOLODLL_API __declspec(dllexport) 
+#else
+#define YOLODLL_API __attribute__((visibility("default")))
+#endif
+#else
+#if defined(_MSC_VER)
+#define YOLODLL_API __declspec(dllimport) 
+#else
+#define YOLODLL_API
+#endif
+#endif
+
+struct bbox_t {
+	unsigned int x, y, w, h;	// (x,y) - top-left corner, (w, h) - width & height of bounded box
+	float prob;					// confidence - probability that the object was found correctly
+	unsigned int obj_id;		// class of object - from range [0, classes-1]
+	unsigned int track_id;		// tracking id for video (0 - untracked, 1 - inf - tracked object)
+	unsigned int frames_counter;// counter of frames on which the object was detected
+};
+
+struct image_t {
+	int h;						// height
+	int w;						// width
+	int c;						// number of chanels (3 - for RGB)
+	float *data;				// pointer to the image data
+};
+
+#ifdef __cplusplus
+#include <memory>
+#include <vector>
+#include <deque>
+#include <algorithm>
+
+#ifdef OPENCV
+#include <opencv2/opencv.hpp>			// C++
+#include "opencv2/highgui/highgui_c.h"	// C
+#include "opencv2/imgproc/imgproc_c.h"	// C
+#endif	// OPENCV
+
+class Detector {
+	std::shared_ptr<void> detector_gpu_ptr;
+	std::deque<std::vector<bbox_t>> prev_bbox_vec_deque;
+	const int cur_gpu_id;
+public:
+	float nms = .4;
+	bool wait_stream;
+
+	YOLODLL_API Detector(std::string cfg_filename, std::string weight_filename, int gpu_id = 0);
+	YOLODLL_API ~Detector();
+
+	YOLODLL_API std::vector<bbox_t> detect(std::string image_filename, float thresh = 0.2, bool use_mean = false);
+	YOLODLL_API std::vector<bbox_t> detect(image_t img, float thresh = 0.2, bool use_mean = false);
+	static YOLODLL_API image_t load_image(std::string image_filename);
+	static YOLODLL_API void free_image(image_t m);
+	YOLODLL_API int get_net_width() const;
+	YOLODLL_API int get_net_height() const;
+
+	YOLODLL_API std::vector<bbox_t> tracking_id(std::vector<bbox_t> cur_bbox_vec, bool const change_history = true, 
+												int const frames_story = 10, int const max_dist = 150);
+
+	std::vector<bbox_t> detect_resized(image_t img, int init_w, int init_h, float thresh = 0.2, bool use_mean = false)
+	{
+		if (img.data == NULL)
+			throw std::runtime_error("Image is empty");
+		auto detection_boxes = detect(img, thresh, use_mean);
+		float wk = (float)init_w / img.w, hk = (float)init_h / img.h;
+		for (auto &i : detection_boxes) i.x *= wk, i.w *= wk, i.y *= hk, i.h *= hk;
+		return detection_boxes;
+	}
+
+#ifdef OPENCV
+	std::vector<bbox_t> detect(cv::Mat mat, float thresh = 0.2, bool use_mean = false)
+	{
+		if(mat.data == NULL)
+			throw std::runtime_error("Image is empty");
+		auto image_ptr = mat_to_image_resize(mat);
+		return detect_resized(*image_ptr, mat.cols, mat.rows, thresh, use_mean);
+	}
+
+	std::shared_ptr<image_t> mat_to_image_resize(cv::Mat mat) const
+	{
+		if (mat.data == NULL) return std::shared_ptr<image_t>(NULL);
+		cv::Mat det_mat;
+		cv::resize(mat, det_mat, cv::Size(get_net_width(), get_net_height()));
+		return mat_to_image(det_mat);
+	}
+
+	static std::shared_ptr<image_t> mat_to_image(cv::Mat img_src)
+	{
+		cv::Mat img;
+		cv::cvtColor(img_src, img, cv::COLOR_RGB2BGR);
+		std::shared_ptr<image_t> image_ptr(new image_t, [](image_t *img) { free_image(*img); delete img; });
+		std::shared_ptr<IplImage> ipl_small = std::make_shared<IplImage>(img);
+		*image_ptr = ipl_to_image(ipl_small.get());
+		return image_ptr;
+	}
+
+private:
+
+	static image_t ipl_to_image(IplImage* src)
+	{
+		unsigned char *data = (unsigned char *)src->imageData;
+		int h = src->height;
+		int w = src->width;
+		int c = src->nChannels;
+		int step = src->widthStep;
+		image_t out = make_image_custom(w, h, c);
+		int count = 0;
+
+		for (int k = 0; k < c; ++k) {
+			for (int i = 0; i < h; ++i) {
+				int i_step = i*step;
+				for (int j = 0; j < w; ++j) {
+					out.data[count++] = data[i_step + j*c + k] / 255.;
+				}
+			}
+		}
+
+		return out;
+	}
+
+	static image_t make_empty_image(int w, int h, int c)
+	{
+		image_t out;
+		out.data = 0;
+		out.h = h;
+		out.w = w;
+		out.c = c;
+		return out;
+	}
+
+	static image_t make_image_custom(int w, int h, int c)
+	{
+		image_t out = make_empty_image(w, h, c);
+		out.data = (float *)calloc(h*w*c, sizeof(float));
+		return out;
+	}
+
+#endif	// OPENCV
+
+};
+
+
+
+#if defined(TRACK_OPTFLOW) && defined(OPENCV) && defined(GPU)
+
+#include <opencv2/cudaoptflow.hpp>
+#include <opencv2/cudaimgproc.hpp>
+#include <opencv2/cudaarithm.hpp>
+#include <opencv2/core/cuda.hpp>
+
+class Tracker_optflow {
+public:
+	const int gpu_count;
+	const int gpu_id;
+	const int flow_error;
+
+
+	Tracker_optflow(int _gpu_id = 0, int win_size = 9, int max_level = 3, int iterations = 8000, int _flow_error = -1) :
+		gpu_count(cv::cuda::getCudaEnabledDeviceCount()), gpu_id(std::min(_gpu_id, gpu_count-1)),
+		flow_error((_flow_error > 0)? _flow_error:(win_size*4))
+	{
+		int const old_gpu_id = cv::cuda::getDevice();
+		cv::cuda::setDevice(gpu_id);
+
+		stream = cv::cuda::Stream();
+
+		sync_PyrLKOpticalFlow_gpu = cv::cuda::SparsePyrLKOpticalFlow::create();
+		sync_PyrLKOpticalFlow_gpu->setWinSize(cv::Size(win_size, win_size));	// 9, 15, 21, 31
+		sync_PyrLKOpticalFlow_gpu->setMaxLevel(max_level);		// +- 3 pt
+		sync_PyrLKOpticalFlow_gpu->setNumIters(iterations);	// 2000, def: 30
+
+		cv::cuda::setDevice(old_gpu_id);
+	}
+
+	// just to avoid extra allocations
+	cv::cuda::GpuMat src_mat_gpu;
+	cv::cuda::GpuMat dst_mat_gpu, dst_grey_gpu;
+	cv::cuda::GpuMat prev_pts_flow_gpu, cur_pts_flow_gpu;
+	cv::cuda::GpuMat status_gpu, err_gpu;
+
+	cv::cuda::GpuMat src_grey_gpu;	// used in both functions
+	cv::Ptr<cv::cuda::SparsePyrLKOpticalFlow> sync_PyrLKOpticalFlow_gpu;
+	cv::cuda::Stream stream;
+
+	std::vector<bbox_t> cur_bbox_vec;
+	std::vector<bool> good_bbox_vec_flags;
+	cv::Mat prev_pts_flow_cpu;
+
+	void update_cur_bbox_vec(std::vector<bbox_t> _cur_bbox_vec)
+	{
+		cur_bbox_vec = _cur_bbox_vec;
+		good_bbox_vec_flags = std::vector<bool>(cur_bbox_vec.size(), true);
+		cv::Mat prev_pts, cur_pts_flow_cpu;
+
+		for (auto &i : cur_bbox_vec) {
+			float x_center = (i.x + i.w / 2.0F);
+			float y_center = (i.y + i.h / 2.0F);
+			prev_pts.push_back(cv::Point2f(x_center, y_center));
+		}
+
+		if (prev_pts.rows == 0)
+			prev_pts_flow_cpu = cv::Mat();
+		else
+			cv::transpose(prev_pts, prev_pts_flow_cpu);
+
+		if (prev_pts_flow_gpu.cols < prev_pts_flow_cpu.cols) {
+			prev_pts_flow_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), prev_pts_flow_cpu.type());
+			cur_pts_flow_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), prev_pts_flow_cpu.type());
+
+			status_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), CV_8UC1);
+			err_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), CV_32FC1);
+		}
+
+		prev_pts_flow_gpu.upload(cv::Mat(prev_pts_flow_cpu), stream);
+	}
+
+
+	void update_tracking_flow(cv::Mat src_mat, std::vector<bbox_t> _cur_bbox_vec)
+	{
+		int const old_gpu_id = cv::cuda::getDevice();
+		if (old_gpu_id != gpu_id)
+			cv::cuda::setDevice(gpu_id);
+
+		if (src_mat.channels() == 3) {
+			if (src_mat_gpu.cols == 0) {
+				src_mat_gpu = cv::cuda::GpuMat(src_mat.size(), src_mat.type());
+				src_grey_gpu = cv::cuda::GpuMat(src_mat.size(), CV_8UC1);
+			}
+
+			update_cur_bbox_vec(_cur_bbox_vec);
+
+			//src_grey_gpu.upload(src_mat, stream);	// use BGR
+			src_mat_gpu.upload(src_mat, stream);
+			cv::cuda::cvtColor(src_mat_gpu, src_grey_gpu, CV_BGR2GRAY, 1, stream);
+		}
+		if (old_gpu_id != gpu_id)
+			cv::cuda::setDevice(old_gpu_id);
+	}
+
+
+	std::vector<bbox_t> tracking_flow(cv::Mat dst_mat, bool check_error = true)
+	{
+		if (sync_PyrLKOpticalFlow_gpu.empty()) {
+			std::cout << "sync_PyrLKOpticalFlow_gpu isn't initialized \n";
+			return cur_bbox_vec;
+		}
+
+		int const old_gpu_id = cv::cuda::getDevice();
+		if(old_gpu_id != gpu_id)
+			cv::cuda::setDevice(gpu_id);
+
+		if (dst_mat_gpu.cols == 0) {
+			dst_mat_gpu = cv::cuda::GpuMat(dst_mat.size(), dst_mat.type());
+			dst_grey_gpu = cv::cuda::GpuMat(dst_mat.size(), CV_8UC1);
+		}
+
+		//dst_grey_gpu.upload(dst_mat, stream);	// use BGR
+		dst_mat_gpu.upload(dst_mat, stream);
+		cv::cuda::cvtColor(dst_mat_gpu, dst_grey_gpu, CV_BGR2GRAY, 1, stream);
+
+		if (src_grey_gpu.rows != dst_grey_gpu.rows || src_grey_gpu.cols != dst_grey_gpu.cols) {
+			stream.waitForCompletion();
+			src_grey_gpu = dst_grey_gpu.clone();
+			cv::cuda::setDevice(old_gpu_id);
+			return cur_bbox_vec;
+		}
+
+		////sync_PyrLKOpticalFlow_gpu.sparse(src_grey_gpu, dst_grey_gpu, prev_pts_flow_gpu, cur_pts_flow_gpu, status_gpu, &err_gpu);	// OpenCV 2.4.x
+		sync_PyrLKOpticalFlow_gpu->calc(src_grey_gpu, dst_grey_gpu, prev_pts_flow_gpu, cur_pts_flow_gpu, status_gpu, err_gpu, stream);	// OpenCV 3.x
+
+		cv::Mat cur_pts_flow_cpu;
+		cur_pts_flow_gpu.download(cur_pts_flow_cpu, stream);
+
+		dst_grey_gpu.copyTo(src_grey_gpu, stream);
+
+		cv::Mat err_cpu, status_cpu;
+		err_gpu.download(err_cpu, stream);
+		status_gpu.download(status_cpu, stream);
+
+		stream.waitForCompletion();
+
+		std::vector<bbox_t> result_bbox_vec;
+
+		if (err_cpu.cols == cur_bbox_vec.size() && status_cpu.cols == cur_bbox_vec.size()) 
+		{
+			for (size_t i = 0; i < cur_bbox_vec.size(); ++i)
+			{
+				cv::Point2f cur_key_pt = cur_pts_flow_cpu.at<cv::Point2f>(0, i);
+				cv::Point2f prev_key_pt = prev_pts_flow_cpu.at<cv::Point2f>(0, i);
+
+				float moved_x = cur_key_pt.x - prev_key_pt.x;
+				float moved_y = cur_key_pt.y - prev_key_pt.y;
+
+				if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i])
+					if (err_cpu.at<float>(0, i) < flow_error && status_cpu.at<unsigned char>(0, i) != 0 &&
+						((float)cur_bbox_vec[i].x + moved_x) > 0 && ((float)cur_bbox_vec[i].y + moved_y) > 0)
+					{
+						cur_bbox_vec[i].x += moved_x + 0.5;
+						cur_bbox_vec[i].y += moved_y + 0.5;
+						result_bbox_vec.push_back(cur_bbox_vec[i]);
+					}
+					else good_bbox_vec_flags[i] = false;
+				else good_bbox_vec_flags[i] = false;
+
+				//if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]);
+			}
+		}
+
+		cur_pts_flow_gpu.swap(prev_pts_flow_gpu);
+		cur_pts_flow_cpu.copyTo(prev_pts_flow_cpu);
+
+		if (old_gpu_id != gpu_id)
+			cv::cuda::setDevice(old_gpu_id);
+
+		return result_bbox_vec;
+	}
+
+};
+
+#elif defined(TRACK_OPTFLOW) && defined(OPENCV)
+
+//#include <opencv2/optflow.hpp>
+#include <opencv2/video/tracking.hpp>
+
+class Tracker_optflow {
+public:
+	const int flow_error;
+
+
+	Tracker_optflow(int win_size = 9, int max_level = 3, int iterations = 8000, int _flow_error = -1) :
+		flow_error((_flow_error > 0)? _flow_error:(win_size*4))
+	{
+		sync_PyrLKOpticalFlow = cv::SparsePyrLKOpticalFlow::create();
+		sync_PyrLKOpticalFlow->setWinSize(cv::Size(win_size, win_size));	// 9, 15, 21, 31
+		sync_PyrLKOpticalFlow->setMaxLevel(max_level);		// +- 3 pt
+
+	}
+
+	// just to avoid extra allocations
+	cv::Mat dst_grey;
+	cv::Mat prev_pts_flow, cur_pts_flow;
+	cv::Mat status, err;
+
+	cv::Mat src_grey;	// used in both functions
+	cv::Ptr<cv::SparsePyrLKOpticalFlow> sync_PyrLKOpticalFlow;
+
+	std::vector<bbox_t> cur_bbox_vec;
+	std::vector<bool> good_bbox_vec_flags;
+
+	void update_cur_bbox_vec(std::vector<bbox_t> _cur_bbox_vec)
+	{
+		cur_bbox_vec = _cur_bbox_vec;
+		good_bbox_vec_flags = std::vector<bool>(cur_bbox_vec.size(), true);
+		cv::Mat prev_pts, cur_pts_flow;
+
+		for (auto &i : cur_bbox_vec) {
+			float x_center = (i.x + i.w / 2.0F);
+			float y_center = (i.y + i.h / 2.0F);
+			prev_pts.push_back(cv::Point2f(x_center, y_center));
+		}
+
+		if (prev_pts.rows == 0)
+			prev_pts_flow = cv::Mat();
+		else
+			cv::transpose(prev_pts, prev_pts_flow);
+	}
+
+
+	void update_tracking_flow(cv::Mat new_src_mat, std::vector<bbox_t> _cur_bbox_vec)
+	{
+		if (new_src_mat.channels() == 3) {
+
+			update_cur_bbox_vec(_cur_bbox_vec);
+
+			cv::cvtColor(new_src_mat, src_grey, CV_BGR2GRAY, 1);
+		}
+	}
+
+
+	std::vector<bbox_t> tracking_flow(cv::Mat new_dst_mat, bool check_error = true)
+	{
+		if (sync_PyrLKOpticalFlow.empty()) {
+			std::cout << "sync_PyrLKOpticalFlow isn't initialized \n";
+			return cur_bbox_vec;
+		}
+
+		cv::cvtColor(new_dst_mat, dst_grey, CV_BGR2GRAY, 1);
+
+		if (src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols) {
+			src_grey = dst_grey.clone();
+			return cur_bbox_vec;
+		}
+
+		if (prev_pts_flow.cols < 1) {
+			return cur_bbox_vec;
+		}
+
+		////sync_PyrLKOpticalFlow_gpu.sparse(src_grey_gpu, dst_grey_gpu, prev_pts_flow_gpu, cur_pts_flow_gpu, status_gpu, &err_gpu);	// OpenCV 2.4.x
+		sync_PyrLKOpticalFlow->calc(src_grey, dst_grey, prev_pts_flow, cur_pts_flow, status, err);	// OpenCV 3.x
+
+		dst_grey.copyTo(src_grey);
+
+		std::vector<bbox_t> result_bbox_vec;
+
+		if (err.rows == cur_bbox_vec.size() && status.rows == cur_bbox_vec.size())
+		{
+			for (size_t i = 0; i < cur_bbox_vec.size(); ++i)
+			{
+				cv::Point2f cur_key_pt = cur_pts_flow.at<cv::Point2f>(0, i);
+				cv::Point2f prev_key_pt = prev_pts_flow.at<cv::Point2f>(0, i);
+
+				float moved_x = cur_key_pt.x - prev_key_pt.x;
+				float moved_y = cur_key_pt.y - prev_key_pt.y;
+
+				if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i])
+					if (err.at<float>(0, i) < flow_error && status.at<unsigned char>(0, i) != 0 &&
+						((float)cur_bbox_vec[i].x + moved_x) > 0 && ((float)cur_bbox_vec[i].y + moved_y) > 0)
+					{
+						cur_bbox_vec[i].x += moved_x + 0.5;
+						cur_bbox_vec[i].y += moved_y + 0.5;
+						result_bbox_vec.push_back(cur_bbox_vec[i]);
+					}
+					else good_bbox_vec_flags[i] = false;
+				else good_bbox_vec_flags[i] = false;
+
+				//if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]);
+			}
+		}
+
+		prev_pts_flow = cur_pts_flow.clone();
+
+		return result_bbox_vec;
+	}
+
+};
+#else
+
+class Tracker_optflow {};
+
+#endif	// defined(TRACK_OPTFLOW) && defined(OPENCV)
+
+
+#ifdef OPENCV
+
+static cv::Scalar obj_id_to_color(int obj_id) {
+	int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } };
+	int const offset = obj_id * 123457 % 6;
+	int const color_scale = 150 + (obj_id * 123457) % 100;
+	cv::Scalar color(colors[offset][0], colors[offset][1], colors[offset][2]);
+	color *= color_scale;
+	return color;
+}
+
+class preview_boxes_t {
+	enum { frames_history = 30 };	// how long to keep the history saved
+
+	struct preview_box_track_t {
+		unsigned int track_id, obj_id, last_showed_frames_ago;
+		bool current_detection;
+		bbox_t bbox;
+		cv::Mat mat_obj, mat_resized_obj;
+		preview_box_track_t() : track_id(0), obj_id(0), last_showed_frames_ago(frames_history), current_detection(false) {}
+	};
+	std::vector<preview_box_track_t> preview_box_track_id;
+	size_t const preview_box_size, bottom_offset;
+	bool const one_off_detections;
+public:
+	preview_boxes_t(size_t _preview_box_size = 100, size_t _bottom_offset = 100, bool _one_off_detections = false) :
+		preview_box_size(_preview_box_size), bottom_offset(_bottom_offset), one_off_detections(_one_off_detections)
+	{}
+
+	void set(cv::Mat src_mat, std::vector<bbox_t> result_vec)
+	{
+		size_t const count_preview_boxes = src_mat.cols / preview_box_size;
+		if (preview_box_track_id.size() != count_preview_boxes) preview_box_track_id.resize(count_preview_boxes);
+
+		// increment frames history
+		for (auto &i : preview_box_track_id)
+			i.last_showed_frames_ago = std::min((unsigned)frames_history, i.last_showed_frames_ago + 1);
+
+		// occupy empty boxes
+		for (auto &k : result_vec) {
+			bool found = false;
+			// find the same (track_id)
+			for (auto &i : preview_box_track_id) {
+				if (i.track_id == k.track_id) {
+					if (!one_off_detections) i.last_showed_frames_ago = 0; // for tracked objects
+					found = true;
+					break;
+				}
+			}
+			if (!found) {
+				// find empty box
+				for (auto &i : preview_box_track_id) {
+					if (i.last_showed_frames_ago == frames_history) {
+						if (!one_off_detections && k.frames_counter == 0) break; // don't show if obj isn't tracked yet
+						i.track_id = k.track_id;
+						i.obj_id = k.obj_id;
+						i.bbox = k;
+						i.last_showed_frames_ago = 0;
+						break;
+					}
+				}
+			}
+		}
+
+		// draw preview box (from old or current frame)
+		for (size_t i = 0; i < preview_box_track_id.size(); ++i)
+		{
+			// get object image
+			cv::Mat dst = preview_box_track_id[i].mat_resized_obj;
+			preview_box_track_id[i].current_detection = false;
+
+			for (auto &k : result_vec) {
+				if (preview_box_track_id[i].track_id == k.track_id) {
+					if (one_off_detections && preview_box_track_id[i].last_showed_frames_ago > 0) {
+						preview_box_track_id[i].last_showed_frames_ago = frames_history; break;
+					}
+					bbox_t b = k;
+					cv::Rect r(b.x, b.y, b.w, b.h);
+					cv::Rect img_rect(cv::Point2i(0, 0), src_mat.size());
+					cv::Rect rect_roi = r & img_rect;
+					if (rect_roi.width > 1 || rect_roi.height > 1) {
+						cv::Mat roi = src_mat(rect_roi);
+						cv::resize(roi, dst, cv::Size(preview_box_size, preview_box_size), cv::INTER_NEAREST);
+						preview_box_track_id[i].mat_obj = roi.clone();
+						preview_box_track_id[i].mat_resized_obj = dst.clone();
+						preview_box_track_id[i].current_detection = true;
+						preview_box_track_id[i].bbox = k;
+					}
+					break;
+				}
+			}
+		}
+	}
+
+
+	void draw(cv::Mat draw_mat, bool show_small_boxes = false)
+	{
+		// draw preview box (from old or current frame)
+		for (size_t i = 0; i < preview_box_track_id.size(); ++i)
+		{
+			auto &prev_box = preview_box_track_id[i];
+
+			// draw object image
+			cv::Mat dst = prev_box.mat_resized_obj;
+			if (prev_box.last_showed_frames_ago < frames_history &&
+				dst.size() == cv::Size(preview_box_size, preview_box_size))
+			{
+				cv::Rect dst_rect_roi(cv::Point2i(i * preview_box_size, draw_mat.rows - bottom_offset), dst.size());
+				cv::Mat dst_roi = draw_mat(dst_rect_roi);
+				dst.copyTo(dst_roi);
+
+				cv::Scalar color = obj_id_to_color(prev_box.obj_id);
+				int thickness = (prev_box.current_detection) ? 5 : 1;
+				cv::rectangle(draw_mat, dst_rect_roi, color, thickness);
+
+				unsigned int const track_id = prev_box.track_id;
+				std::string track_id_str = (track_id > 0) ? std::to_string(track_id) : "";
+				putText(draw_mat, track_id_str, dst_rect_roi.tl() - cv::Point2i(-4, 5), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.9, cv::Scalar(0, 0, 0), 2);
+
+				std::string size_str = std::to_string(prev_box.bbox.w) + "x" + std::to_string(prev_box.bbox.h);
+				putText(draw_mat, size_str, dst_rect_roi.tl() + cv::Point2i(0, 12), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0, 0, 0), 1);
+
+				if (!one_off_detections && prev_box.current_detection) {
+					cv::line(draw_mat, dst_rect_roi.tl() + cv::Point2i(preview_box_size, 0),
+						cv::Point2i(prev_box.bbox.x, prev_box.bbox.y + prev_box.bbox.h),
+						color);
+				}
+
+				if (one_off_detections && show_small_boxes) {
+					cv::Rect src_rect_roi(cv::Point2i(prev_box.bbox.x, prev_box.bbox.y),
+						cv::Size(prev_box.bbox.w, prev_box.bbox.h));
+					unsigned int const color_history = (255 * prev_box.last_showed_frames_ago) / frames_history;
+					color = cv::Scalar(255 - 3 * color_history, 255 - 2 * color_history, 255 - 1 * color_history);
+					if (prev_box.mat_obj.size() == src_rect_roi.size()) {
+						prev_box.mat_obj.copyTo(draw_mat(src_rect_roi));
+					}
+					cv::rectangle(draw_mat, src_rect_roi, color, thickness);
+					putText(draw_mat, track_id_str, src_rect_roi.tl() - cv::Point2i(0, 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0, 0, 0), 1);
+				}
+			}
+		}
+	}
+};
+#endif	// OPENCV
+
+//extern "C" {
+#endif	// __cplusplus
+
+/*
+	// C - wrappers
+	YOLODLL_API void create_detector(char const* cfg_filename, char const* weight_filename, int gpu_id);
+	YOLODLL_API void delete_detector();
+	YOLODLL_API bbox_t* detect_custom(image_t img, float thresh, bool use_mean, int *result_size);
+	YOLODLL_API bbox_t* detect_resized(image_t img, int init_w, int init_h, float thresh, bool use_mean, int *result_size);
+	YOLODLL_API bbox_t* detect(image_t img, int *result_size);
+	YOLODLL_API image_t load_img(char *image_filename);
+	YOLODLL_API void free_img(image_t m);
+
+#ifdef __cplusplus
+}	// extern "C"
+
+static std::shared_ptr<void> c_detector_ptr;
+static std::vector<bbox_t> c_result_vec;
+
+void create_detector(char const* cfg_filename, char const* weight_filename, int gpu_id) {
+	c_detector_ptr = std::make_shared<YOLODLL_API Detector>(cfg_filename, weight_filename, gpu_id);
+}
+
+void delete_detector() { c_detector_ptr.reset(); }
+
+bbox_t* detect_custom(image_t img, float thresh, bool use_mean, int *result_size) {
+	c_result_vec = static_cast<Detector*>(c_detector_ptr.get())->detect(img, thresh, use_mean);
+	*result_size = c_result_vec.size();
+	return c_result_vec.data();
+}
+
+bbox_t* detect_resized(image_t img, int init_w, int init_h, float thresh, bool use_mean, int *result_size) {
+	c_result_vec = static_cast<Detector*>(c_detector_ptr.get())->detect_resized(img, init_w, init_h, thresh, use_mean);
+	*result_size = c_result_vec.size();
+	return c_result_vec.data();
+}
+
+bbox_t* detect(image_t img, int *result_size) {
+	return detect_custom(img, 0.24, true, result_size);
+}
+
+image_t load_img(char *image_filename) {
+	return static_cast<Detector*>(c_detector_ptr.get())->load_image(image_filename);
+}
+void free_img(image_t m) {
+	static_cast<Detector*>(c_detector_ptr.get())->free_image(m);
+}
+
+#endif	// __cplusplus
+*/
diff --git a/darknet/lib/libdarknet.so b/darknet/lib/libdarknet.so
new file mode 100755
index 0000000..e4a12c9
--- /dev/null
+++ b/darknet/lib/libdarknet.so
Binary files differ
diff --git a/detector.cpp b/detector.cpp
new file mode 100644
index 0000000..9701a90
--- /dev/null
+++ b/detector.cpp
@@ -0,0 +1,44 @@
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include "detector.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "csrc/yolo.h"
+
+#include "csrc/struct.h"
+
+#include "csrc/yolo.cpp"
+
+using namespace cppyolo;
+
+void* init(const char *cfg, const char *weights, const char *name, const int gpu){
+    return new sdkyolo(cfg, weights, name, gpu);
+}
+
+void release(void *handle){
+    if (handle){
+        sdkyolo *h = (sdkyolo*)handle;
+        delete h;
+    }
+}
+
+int detect(void *handle, 
+            const void *data, const int w, const int h, const int c,
+            const float thrsh, const int use_mean, 
+            void **objInfos, int *objCount){
+
+    sdkyolo *y = (sdkyolo*)handle;
+    cIMAGE img{(unsigned char*)data, w, h, c};
+    return y->detect(&img, thrsh, use_mean, objInfos, objCount);
+}
+
+const char* obj_name_by_type(void *handle, const int typ){
+    sdkyolo *h = (sdkyolo*)handle;
+    return h->obj_name_by_type(typ);
+}
+
diff --git a/detector.h b/detector.h
new file mode 100644
index 0000000..c9eb31e
--- /dev/null
+++ b/detector.h
@@ -0,0 +1,22 @@
+#ifndef _c_yolo_h_
+#define _c_yolo_h_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void* init(const char *cfg, const char *weights, const char *name, const int gpu);
+void release(void *handle);
+
+int detect(void *handle, 
+            const void *data, const int w, const int h, const int c,
+            const float thrsh, const int use_mean, 
+            void **objInfos, int *objCount);
+
+const char* obj_name_by_type(void *handle, const int typ);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/goyolo.go b/goyolo.go
new file mode 100644
index 0000000..fe1634d
--- /dev/null
+++ b/goyolo.go
@@ -0,0 +1,216 @@
+package main
+
+/*
+#cgo CFLAGS: -I${SRCDIR}/darknet/include -I/usr/local/cuda-8.0/include -w -g
+#cgo CXXFLAGS: -I${SRCDIR}/darknet/include -I/usr/local/cuda-8.0/include -w -g -std=c++11
+#cgo LDFLAGS: -L/usr/local/cuda-8.0/lib64 -L${SRCDIR}/darknet/lib
+#cgo LDFLAGS: -Wl,-rpath,${SRCDIR}/darknet/lib
+#cgo LDFLAGS: -ldarknet -lcudart -lcublas -lcurand -lcudnn -lrt -ldl -lpthread
+#include <stdlib.h>
+#include "detector.h"
+*/
+import "C"
+import "unsafe"
+
+// CPOINT pt
+type CPOINT struct {
+	X int32
+	Y int32
+}
+
+// CRECT rc
+type CRECT struct {
+	Left   int32
+	Top    int32
+	Right  int32
+	Bottom int32
+}
+
+// CIMAGE img
+type CIMAGE struct {
+	Data      *uint8
+	Width     int32
+	Height    int32
+	Channel   int32
+	Pad_cgo_0 [4]byte
+}
+
+// CObjInfo yolo
+type CObjInfo struct {
+	RcObj CRECT
+	Typ   int32
+	Prob  float32
+}
+
+// CObjTrackInfo track yolo objs info
+type CObjTrackInfo struct {
+	ObjInfo CObjInfo
+	ID      uint64
+}
+
+// YoloHandle wrap C
+type YoloHandle struct {
+	handle       unsafe.Pointer
+	LastYoloObjs []CObjTrackInfo //yolo璺熻釜鐨勪笂涓�甯т俊鎭�
+	LastTrackID  uint64          //yolo 琚娇鐢ㄧ殑ID
+}
+
+// RatioInterTrack 璺熻釜鍒ゆ柇閲嶅彔闃堝��
+const RatioInterTrack = 50 //璺熻釜鍒ゆ柇閲嶅彔闃堝��
+
+// SDKImage sdk image
+type SDKImage struct {
+	Data   []byte
+	Width  int
+	Height int
+}
+
+// NewYolo init yolo sdk
+func NewYolo(fc, fw, fn string, gi int) *YoloHandle {
+
+	c := C.CString(fc)
+	defer C.free(unsafe.Pointer(c))
+	w := C.CString(fw)
+	defer C.free(unsafe.Pointer(w))
+	n := C.CString(fn)
+	defer C.free(unsafe.Pointer(n))
+
+	g := C.int(gi)
+
+	p := C.init(c, w, n, g)
+	return &YoloHandle{handle: p}
+}
+
+// Free free
+func (y *YoloHandle) Free() {
+	if y != nil {
+		if y.handle != nil {
+			C.release(y.handle)
+		}
+	}
+}
+
+// CYoloObjInfoArrayToGoArray convert cObjInfo array to go
+func CYoloObjInfoArrayToGoArray(cArray unsafe.Pointer, count int) (goArray []CObjInfo) {
+	p := uintptr(cArray)
+
+	for i := 0; i < count; i++ {
+		j := *(*CObjInfo)(unsafe.Pointer(p))
+		goArray = append(goArray, j)
+		p += unsafe.Sizeof(j)
+	}
+	return
+}
+
+// YoloDetect yolo detect
+func (y *YoloHandle) YoloDetect(img SDKImage, thrsh float32, umns int) []CObjInfo {
+
+	data := img.Data
+	w := img.Width
+	h := img.Height
+
+	var count C.int
+	var cobjinfo unsafe.Pointer
+
+	ret := C.detect(y.handle,
+		unsafe.Pointer(&data[0]), C.int(w), C.int(h), 3,
+		C.float(thrsh), C.int(umns),
+		&cobjinfo, &count)
+
+	if ret == 0 {
+		return CYoloObjInfoArrayToGoArray(unsafe.Pointer(cobjinfo), int(count))
+	}
+	return nil
+}
+
+// YoloObjName obj name by type
+func (y *YoloHandle) YoloObjName(typ int) string {
+	p := C.obj_name_by_type(y.handle, C.int(typ))
+
+	return C.GoString(p)
+}
+
+func max(a, b int32) int32 {
+	if a < b {
+		return b
+	}
+	return a
+}
+
+func min(a, b int32) int32 {
+	if a < b {
+		return a
+	}
+	return b
+}
+
+func countInterAreaOfTwoRect(rect1 CRECT, rect2 CRECT) int32 {
+	xMin := min(rect1.Left, rect2.Left)
+	yMin := min(rect1.Top, rect2.Top)
+	xMax := max(rect1.Right, rect2.Right)
+	yMax := max(rect1.Bottom, rect2.Bottom)
+
+	wRect1 := rect1.Right - rect1.Left
+	hRect1 := rect1.Bottom - rect1.Top
+
+	wRect2 := rect2.Right - rect2.Left
+	hRect2 := rect2.Bottom - rect2.Top
+
+	wInter := wRect1 + wRect2 - (xMax - xMin)
+	hInter := hRect1 + hRect2 - (yMax - yMin)
+
+	if (wInter <= 0) || (hInter <= 0) {
+		return 0
+	}
+
+	areaInter := wInter * hInter
+	areaRect1 := wRect1 * hRect1
+	areaRect2 := wRect2 * hRect2
+	ratio := areaInter * 100 / min(areaRect1, areaRect2)
+
+	return ratio
+}
+
+// YoloDetectTrack yolo detect   (鍙瘑鍒汉)
+func (y *YoloHandle) YoloDetectTrack(img SDKImage, thrsh float32, umns int) (allObjs []CObjTrackInfo, newObjs []CObjTrackInfo) {
+
+	var tmp CObjTrackInfo
+	//LastYoloObjs
+	detectObjs := y.YoloDetect(img, thrsh, umns)
+
+	for _, vLast := range y.LastYoloObjs {
+		for i := 0; i < len(detectObjs); i++ {
+			//fmt.Println("vNew.Typ:", vNew.Typ)
+			if vLast.ObjInfo.Typ == detectObjs[i].Typ { //鍚屼竴绫诲埆锛屾瘮濡傞兘鏄汉浣�
+				ratio := countInterAreaOfTwoRect(vLast.ObjInfo.RcObj, detectObjs[i].RcObj)
+				if ratio >= RatioInterTrack {
+					//update LastYoloObjs
+					vLast.ObjInfo.RcObj = detectObjs[i].RcObj
+					vLast.ObjInfo.Prob = detectObjs[i].Prob
+
+					allObjs = append(allObjs, vLast)
+					detectObjs = append(detectObjs[:i], detectObjs[i+1:]...) //浠庢娴嬬洰鏍囬噷鍒犻櫎宸茬粡鏌ュ埌鐨勮窡韪洰鏍�
+					i--
+					break //涓婁竴甯ц窡韪殑鐩爣宸茬粡鎵惧埌锛屾棤闇�寰�涓嬪鐞嗗叾浠栨娴嬬洰鏍�
+				}
+			}
+		}
+	}
+
+	//澶勭悊鏂板嚭鐜扮殑鐩爣
+	if len(detectObjs) > 0 {
+		for _, vAdd := range detectObjs {
+			tmp.ObjInfo = vAdd
+			tmp.ID = y.LastTrackID
+			y.LastTrackID++
+
+			allObjs = append(allObjs, tmp)
+			newObjs = append(newObjs, tmp)
+		}
+	}
+
+	//鍒锋柊涓婁竴甯х殑璺熻釜鐩爣
+	y.LastYoloObjs = allObjs
+
+	return allObjs, newObjs
+}

--
Gitblit v1.8.0