| | |
| | | # Compiled Object files, Static and Dynamic libs (Shared Objects) |
| | | *.o |
| | | *.a |
| | | *.so |
| | | |
| | | # Folders |
| | | _obj |
| | |
| | | |
| | | *.exe |
| | | *.test |
| | | libyolo.so |
New file |
| | |
| | | #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 |
New file |
| | |
| | | #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 |
New file |
| | |
| | | #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 |
New file |
| | |
| | | #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" { // 告诉编译器下列代码要以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 |
New file |
| | |
| | | #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 |
| | | */ |
New file |
| | |
| | | #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); |
| | | } |
| | | |
New file |
| | |
| | | #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 |
New file |
| | |
| | | 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 |
| | | } |