diff --git a/src/layer.c b/src/layer.c index ccd0daf0..5fb5d240 100644 --- a/src/layer.c +++ b/src/layer.c @@ -28,8 +28,8 @@ void free_layer(layer l) #ifdef GPU if(l.indexes_gpu) cuda_free((float *)l.indexes_gpu); - if(l.weights_gpu) cuda_free(l.weights_gpu); - if(l.weight_updates_gpu) cuda_free(l.weight_updates_gpu); + //if(l.weights_gpu) cuda_free(l.weights_gpu); // duplicated + //if(l.weight_updates_gpu) cuda_free(l.weight_updates_gpu); // duplicated if(l.col_image_gpu) cuda_free(l.col_image_gpu); if(l.weights_gpu) cuda_free(l.weights_gpu); if(l.biases_gpu) cuda_free(l.biases_gpu); diff --git a/src/yolo_console_dll.cpp b/src/yolo_console_dll.cpp index 00eca16f..4938ba86 100644 --- a/src/yolo_console_dll.cpp +++ b/src/yolo_console_dll.cpp @@ -1,6 +1,7 @@ #include #include #include +#include //#define OPENCV @@ -21,36 +22,54 @@ void draw_boxes(cv::Mat mat_img, std::vector result_vec) { } #endif // OPENCV - -void show_result(std::vector result_vec) { +void show_result(std::vector const result_vec, std::vector const obj_names) { for (auto &i : result_vec) { + if (obj_names.size() > i.obj_id) std::cout << obj_names[i.obj_id] << " - "; std::cout << "obj_id = " << i.obj_id << " - x = " << i.x << ", y = " << i.y << ", w = " << i.w << ", h = " << i.h << ", prob = " << i.prob << std::endl; } } +std::vector objects_names_from_file(std::string const filename) { + std::ifstream file(filename); + std::vector file_lines; + if (!file.is_open()) return file_lines; + for(std::string line; file >> line;) file_lines.push_back(line); + std::cout << "object names loaded \n"; + return file_lines; +} int main() { Detector detector("yolo-voc.cfg", "yolo-voc.weights"); + auto obj_names = objects_names_from_file("data/voc.names"); + while (true) { std::string filename; std::cout << "input image filename: "; std::cin >> filename; if (filename.size() == 0) break; - + + try { #ifdef OPENCV - cv::Mat mat_img = cv::imread(filename); - std::vector result_vec = detector.detect(mat_img); - draw_boxes(mat_img, result_vec); + cv::Mat mat_img = cv::imread(filename); + std::vector result_vec = detector.detect(mat_img); + draw_boxes(mat_img, result_vec); #else - std::vector result_vec = detector.detect(filename); + //std::vector result_vec = detector.detect(filename); + + auto img = detector.load_image(filename); + std::vector result_vec = detector.detect(img); + detector.free_image(img); #endif - show_result(result_vec); + show_result(result_vec, obj_names); + } + catch (std::exception &e) { std::cerr << "exception: " << e.what() << "\n"; getchar(); } + catch (...) { std::cerr << "unknown exception \n"; getchar(); } } return 0; diff --git a/src/yolo_v2_class.cpp b/src/yolo_v2_class.cpp index 69cd5fc7..c58ebdac 100644 --- a/src/yolo_v2_class.cpp +++ b/src/yolo_v2_class.cpp @@ -1,6 +1,5 @@ #include "yolo_v2_class.hpp" - #include "network.h" extern "C" { @@ -12,40 +11,32 @@ extern "C" { #include "box.h" #include "image.h" #include "demo.h" - #include "option_list.h" - +#include "stb_image.h" } //#include #include #include - #define FRAMES 3 -#define ROI_PER_DETECTOR 100 - struct detector_gpu_t{ float **probs; box *boxes; network net; - //image det; - //image det_s; image images[FRAMES]; float *avg; float *predictions[FRAMES]; }; - YOLODLL_API Detector::Detector(std::string cfg_filename, std::string weight_filename, int gpu_id) { int old_gpu_index; cudaGetDevice(&old_gpu_index); detector_gpu_ptr = std::make_shared(); - detector_gpu_t &detector_gpu = *reinterpret_cast(detector_gpu_ptr.get()); cudaSetDevice(gpu_id); @@ -77,23 +68,63 @@ YOLODLL_API Detector::Detector(std::string cfg_filename, std::string weight_file cudaSetDevice(old_gpu_index); } + YOLODLL_API Detector::~Detector() { detector_gpu_t &detector_gpu = *reinterpret_cast(detector_gpu_ptr.get()); layer l = detector_gpu.net.layers[detector_gpu.net.n - 1]; - free(detector_gpu.boxes); free(detector_gpu.avg); - free(detector_gpu.predictions); - for (int j = 0; j < l.w*l.h*l.n; ++j) free(detector_gpu.probs[j]); + for (int j = 0; j < FRAMES; ++j) free(detector_gpu.predictions[j]); + for (int j = 0; j < FRAMES; ++j) if(detector_gpu.images[j].data) free(detector_gpu.images[j].data); + + free(detector_gpu.boxes); free(detector_gpu.probs); + for (int j = 0; j < l.w*l.h*l.n; ++j) free(detector_gpu.probs[j]); + + int old_gpu_index; + cudaGetDevice(&old_gpu_index); + cudaSetDevice(detector_gpu.net.gpu_index); + + free_network(detector_gpu.net); + + cudaSetDevice(old_gpu_index); } YOLODLL_API std::vector Detector::detect(std::string image_filename, float thresh) +{ + std::shared_ptr image_ptr(new image_t, [](image_t *img) { if (img->data) free(img->data); delete img; }); + *image_ptr = load_image(image_filename); + return detect(*image_ptr, thresh); +} + +static image load_image_stb(char *filename, int channels) +{ + int w, h, c; + unsigned char *data = stbi_load(filename, &w, &h, &c, channels); + if (!data) + throw std::runtime_error("file not found"); + if (channels) c = channels; + int i, j, k; + image im = make_image(w, h, c); + for (k = 0; k < c; ++k) { + for (j = 0; j < h; ++j) { + for (i = 0; i < w; ++i) { + int dst_index = i + w*j + w*h*k; + int src_index = k + c*i + c*w*j; + im.data[dst_index] = (float)data[src_index] / 255.; + } + } + } + free(data); + return im; +} + +YOLODLL_API image_t Detector::load_image(std::string image_filename) { char *input = const_cast(image_filename.data()); - image im = load_image_color(input, 0, 0); + image im = load_image_stb(input, 3); image_t img; img.c = im.c; @@ -101,10 +132,17 @@ YOLODLL_API std::vector Detector::detect(std::string image_filename, flo img.h = im.h; img.w = im.w; - return detect(img, thresh); + return img; } +YOLODLL_API void Detector::free_image(image_t m) +{ + if (m.data) { + free(m.data); + } +} + YOLODLL_API std::vector Detector::detect(image_t img, float thresh) { @@ -126,10 +164,6 @@ YOLODLL_API std::vector Detector::detect(image_t img, float thresh) image sized = resize_image(im, net.w, net.h); layer l = net.layers[net.n - 1]; - //box *boxes = (box *)calloc(l.w*l.h*l.n, sizeof(box)); - //float **probs = (float **)calloc(l.w*l.h*l.n, sizeof(float *)); - // (int j = 0; j < l.w*l.h*l.n; ++j) probs[j] = (float *)calloc(l.classes, sizeof(float *)); - float *X = sized.data; network_predict(net, X); @@ -159,6 +193,9 @@ YOLODLL_API std::vector Detector::detect(image_t img, float thresh) } } + if(sized.data) + free(sized.data); + cudaSetDevice(old_gpu_index); return bbox_vec; diff --git a/src/yolo_v2_class.hpp b/src/yolo_v2_class.hpp index f1c6576c..e3d79331 100644 --- a/src/yolo_v2_class.hpp +++ b/src/yolo_v2_class.hpp @@ -15,17 +15,17 @@ #endif struct bbox_t { - unsigned int x, y, w, h; - float prob; - unsigned int obj_id; + 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] }; -typedef struct { - int h; - int w; - int c; - float *data; -} image_t; +struct image_t { + int h; // height + int w; // width + int c; // number of chanels (3 - for RGB) + float *data; // pointer to the image data +}; class Detector { @@ -37,11 +37,15 @@ public: YOLODLL_API std::vector detect(std::string image_filename, float thresh = 0.2); YOLODLL_API std::vector detect(image_t img, float thresh = 0.2); + static YOLODLL_API image_t load_image(std::string image_filename); + static YOLODLL_API void free_image(image_t m); #ifdef OPENCV std::vector detect(cv::Mat mat, float thresh = 0.2) { - std::shared_ptr image_ptr(new image_t, [](image_t *img) { free_image(*img); } ); + if(mat.data == NULL) + throw std::runtime_error("file not found"); + std::shared_ptr image_ptr(new image_t, [](image_t *img) { free_image(*img); delete img; }); *image_ptr = mat_to_image(mat); return detect(*image_ptr, thresh); } @@ -102,12 +106,6 @@ private: } } - static void free_image(image_t m) - { - if (m.data) { - free(m.data); - } - } #endif // OPENCV };