diff --git a/build/darknet/yolo_console_dll.sln b/build/darknet/yolo_console_dll.sln new file mode 100644 index 00000000..e06e5a26 --- /dev/null +++ b/build/darknet/yolo_console_dll.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yolo_console_dll", "yolo_console_dll.vcxproj", "{4CFC8DC0-92A2-4311-B54B-2264E56A3B58}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Debug|x64.ActiveCfg = Debug|x64 + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Debug|x64.Build.0 = Debug|x64 + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Debug|x86.ActiveCfg = Debug|Win32 + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Debug|x86.Build.0 = Debug|Win32 + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Release|x64.ActiveCfg = Release|x64 + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Release|x64.Build.0 = Release|x64 + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Release|x86.ActiveCfg = Release|Win32 + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/build/darknet/yolo_console_dll.vcxproj b/build/darknet/yolo_console_dll.vcxproj new file mode 100644 index 00000000..4faf7a02 --- /dev/null +++ b/build/darknet/yolo_console_dll.vcxproj @@ -0,0 +1,133 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {4CFC8DC0-92A2-4311-B54B-2264E56A3B58} + yolo_console_dll + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Platform)\ + $(Platform)\$(Configuration)\ + + + $(SolutionDir)$(Platform)\ + + + + Level3 + Disabled + true + + + + + Level3 + Disabled + true + C:\opencv_2.4.9\opencv\build\include + + + C:\opencv_2.4.9\opencv\build\x64\vc12\lib + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + C:\opencv_2.4.9\opencv\build\include + + + true + true + C:\opencv_2.4.9\opencv\build\x64\vc12\lib + + + + + + + + + + + + \ No newline at end of file diff --git a/build/darknet/yolo_cpp_dll.sln b/build/darknet/yolo_cpp_dll.sln new file mode 100644 index 00000000..4d457760 --- /dev/null +++ b/build/darknet/yolo_cpp_dll.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yolo_cpp_dll", "yolo_cpp_dll.vcxproj", "{4CF5694F-12A5-4012-8D94-9A0915E9FEB5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Debug|x64.ActiveCfg = Debug|x64 + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Debug|x64.Build.0 = Debug|x64 + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Debug|x86.ActiveCfg = Debug|Win32 + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Debug|x86.Build.0 = Debug|Win32 + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Release|x64.ActiveCfg = Release|x64 + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Release|x64.Build.0 = Release|x64 + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Release|x86.ActiveCfg = Release|Win32 + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/build/darknet/yolo_cpp_dll.vcxproj b/build/darknet/yolo_cpp_dll.vcxproj new file mode 100644 index 00000000..497c5dfe --- /dev/null +++ b/build/darknet/yolo_cpp_dll.vcxproj @@ -0,0 +1,286 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {4CF5694F-12A5-4012-8D94-9A0915E9FEB5} + darknet + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Platform)\ + + + $(SolutionDir)$(Platform)\ + + + + Level3 + Disabled + true + + + true + + + + + Level3 + Disabled + true + ..\..\3rdparty\include;%(AdditionalIncludeDirectories);$(CudaToolkitIncludeDir);$(cudnn)\include + _MBCS;YOLODLL_EXPORTS;_TIMESPEC_DEFINED;_CRT_SECURE_NO_WARNINGS;GPU;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + CUDNN + true + + + true + $(CUDA_PATH)lib\$(PlatformName);$(cudnn)\lib\x64;%(AdditionalLibraryDirectories) + $(OutDir)\$(TargetName)$(TargetExt) + ..\..\3rdparty\lib\x64\pthreadVC2.lib;cublas.lib;curand.lib;cudart.lib;%(AdditionalDependencies) + true + + + compute_30,sm_30;compute_52,sm_52 + 64 + + + + + Level3 + MaxSpeed + true + true + true + C:\opencv_2.4.9\opencv\build\include;..\..\3rdparty\include;%(AdditionalIncludeDirectories);$(CudaToolkitIncludeDir);$(cudnn)\include + YOLODLL_EXPORTS;_TIMESPEC_DEFINED;_CRT_SECURE_NO_WARNINGS;GPU;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + true + true + true + C:\opencv_2.4.9\opencv\build\x86\vc14\lib;C:\opencv_2.4.9\opencv\build\x86\vc12\lib;$(CUDA_PATH)lib\$(PlatformName);$(cudnn)\lib\x64;%(AdditionalLibraryDirectories) + ..\..\3rdparty\lib\x86\pthreadVC2.lib;cudart.lib;cublas.lib;curand.lib;%(AdditionalDependencies) + + + + + Level3 + MaxSpeed + true + true + true + ..\..\3rdparty\include;%(AdditionalIncludeDirectories);$(CudaToolkitIncludeDir);$(cudnn)\include + YOLODLL_EXPORTS;_TIMESPEC_DEFINED;_CRT_SECURE_NO_WARNINGS;GPU;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + c11 + c++1y + CompileAsCpp + Default + + + true + + + true + true + true + $(CUDA_PATH)lib\$(PlatformName);$(cudnn)\lib\x64;%(AdditionalLibraryDirectories) + ..\..\3rdparty\lib\x64\pthreadVC2.lib;cublas.lib;curand.lib;cudart.lib;%(AdditionalDependencies) + $(OutDir)\$(TargetName)$(TargetExt) + + + 64 + compute_30,sm_30;compute_52,sm_52 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/network.h b/src/network.h index e48cbc28..bb65eac7 100644 --- a/src/network.h +++ b/src/network.h @@ -2,8 +2,13 @@ #ifndef NETWORK_H #define NETWORK_H -#include "image.h" #include "layer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "image.h" #include "data.h" #include "tree.h" @@ -125,5 +130,9 @@ float get_network_cost(network net); int get_network_nuisance(network net); int get_network_background(network net); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/yolo.c b/src/yolo.c index 206e4683..2a9cde3f 100644 --- a/src/yolo.c +++ b/src/yolo.c @@ -6,6 +6,7 @@ #include "box.h" #include "demo.h" +#ifdef OPENCV #pragma comment(lib, "opencv_core249.lib") #pragma comment(lib, "opencv_imgproc249.lib") #pragma comment(lib, "opencv_highgui249.lib") @@ -13,7 +14,6 @@ //#pragma comment(lib, "opencv_photo249.lib") //#pragma comment(lib, "opencv_video249.lib") -#ifdef OPENCV #include "opencv2/highgui/highgui_c.h" #endif diff --git a/src/yolo_console_dll.cpp b/src/yolo_console_dll.cpp new file mode 100644 index 00000000..00eca16f --- /dev/null +++ b/src/yolo_console_dll.cpp @@ -0,0 +1,57 @@ +#include +#include +#include + +//#define OPENCV + +#include "yolo_v2_class.hpp" // imported functions from DLL + + +#ifdef OPENCV +#include // C++ +#pragma comment(lib, "opencv_core249.lib") +#pragma comment(lib, "opencv_imgproc249.lib") +#pragma comment(lib, "opencv_highgui249.lib") +void draw_boxes(cv::Mat mat_img, std::vector result_vec) { + for (auto &i : result_vec) { + cv::rectangle(mat_img, cv::Rect(i.x, i.y, i.w, i.h), cv::Scalar(50, 200, 50), 3); + } + cv::imshow("window name", mat_img); + cv::waitKey(0); +} +#endif // OPENCV + + +void show_result(std::vector result_vec) { + for (auto &i : result_vec) { + std::cout << "obj_id = " << i.obj_id << " - x = " << i.x << ", y = " << i.y + << ", w = " << i.w << ", h = " << i.h + << ", prob = " << i.prob << std::endl; + } +} + + + +int main() +{ + Detector detector("yolo-voc.cfg", "yolo-voc.weights"); + + while (true) + { + std::string filename; + std::cout << "input image filename: "; + std::cin >> filename; + if (filename.size() == 0) break; + +#ifdef OPENCV + 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); +#endif + show_result(result_vec); + } + + return 0; +} \ No newline at end of file diff --git a/src/yolo_v2_class.cpp b/src/yolo_v2_class.cpp new file mode 100644 index 00000000..69cd5fc7 --- /dev/null +++ b/src/yolo_v2_class.cpp @@ -0,0 +1,165 @@ +#include "yolo_v2_class.hpp" + + +#include "network.h" + +extern "C" { +#include "detection_layer.h" +#include "region_layer.h" +#include "cost_layer.h" +#include "utils.h" +#include "parser.h" +#include "box.h" +#include "image.h" +#include "demo.h" + +#include "option_list.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); + network &net = detector_gpu.net; + net.gpu_index = gpu_id; + //gpu_index = i; + + char *cfgfile = const_cast(cfg_filename.data()); + char *weightfile = const_cast(weight_filename.data()); + + net = parse_network_cfg(cfgfile); + if (weightfile) { + load_weights(&net, weightfile); + } + set_batch_network(&net, 1); + net.gpu_index = gpu_id; + + layer l = net.layers[net.n - 1]; + int j; + + detector_gpu.avg = (float *)calloc(l.outputs, sizeof(float)); + for (j = 0; j < FRAMES; ++j) detector_gpu.predictions[j] = (float *)calloc(l.outputs, sizeof(float)); + for (j = 0; j < FRAMES; ++j) detector_gpu.images[j] = make_image(1, 1, 3); + + detector_gpu.boxes = (box *)calloc(l.w*l.h*l.n, sizeof(box)); + detector_gpu.probs = (float **)calloc(l.w*l.h*l.n, sizeof(float *)); + for (j = 0; j < l.w*l.h*l.n; ++j) detector_gpu.probs[j] = (float *)calloc(l.classes, sizeof(float)); + + 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]); + free(detector_gpu.probs); +} + + +YOLODLL_API std::vector Detector::detect(std::string image_filename, float thresh) +{ + char *input = const_cast(image_filename.data()); + image im = load_image_color(input, 0, 0); + + image_t img; + img.c = im.c; + img.data = im.data; + img.h = im.h; + img.w = im.w; + + return detect(img, thresh); +} + + +YOLODLL_API std::vector Detector::detect(image_t img, float thresh) +{ + + detector_gpu_t &detector_gpu = *reinterpret_cast(detector_gpu_ptr.get()); + network &net = detector_gpu.net; + int old_gpu_index; + cudaGetDevice(&old_gpu_index); + cudaSetDevice(net.gpu_index); + //std::cout << "net.gpu_index = " << net.gpu_index << std::endl; + + float nms = .4; + + image im; + im.c = img.c; + im.data = img.data; + im.h = img.h; + im.w = img.w; + + 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); + + get_region_boxes(l, 1, 1, thresh, detector_gpu.probs, detector_gpu.boxes, 0, 0); + if (nms) do_nms_sort(detector_gpu.boxes, detector_gpu.probs, l.w*l.h*l.n, l.classes, nms); + //draw_detections(im, l.w*l.h*l.n, thresh, boxes, probs, names, alphabet, l.classes); + + std::vector bbox_vec; + + for (size_t i = 0; i < (l.w*l.h*l.n); ++i) { + box b = detector_gpu.boxes[i]; + int const obj_id = max_index(detector_gpu.probs[i], l.classes); + float const prob = detector_gpu.probs[i][obj_id]; + + if (prob > thresh) + { + bbox_t bbox; + bbox.x = (b.x - b.w / 2.)*im.w; + bbox.y = (b.y - b.h / 2.)*im.h; + bbox.w = b.w*im.w; + bbox.h = b.h*im.h; + bbox.obj_id = obj_id; + bbox.prob = prob; + + bbox_vec.push_back(bbox); + } + } + + cudaSetDevice(old_gpu_index); + + return bbox_vec; +} \ No newline at end of file diff --git a/src/yolo_v2_class.hpp b/src/yolo_v2_class.hpp new file mode 100644 index 00000000..0116cce4 --- /dev/null +++ b/src/yolo_v2_class.hpp @@ -0,0 +1,120 @@ +#pragma once +#include +#include + +#ifdef OPENCV +#include // C++ +#include "opencv2/highgui/highgui_c.h" // C +#include "opencv2/imgproc/imgproc_c.h" // C +#endif // OPENCV + +//extern "C" { +//#include "image.h" +//} + +#ifdef YOLODLL_EXPORTS +#define YOLODLL_API __declspec(dllexport) +#else +#define YOLODLL_API __declspec(dllimport) +#endif + +struct bbox_t { + float x, y, w, h; + float prob; + unsigned int obj_id; +}; + +typedef struct { + int h; + int w; + int c; + float *data; +} image_t; + + +class Detector { + std::shared_ptr detector_gpu_ptr; +public: + + YOLODLL_API Detector(std::string cfg_filename, std::string weight_filename, int gpu_id = 0); + YOLODLL_API ~Detector(); + + YOLODLL_API std::vector Detector::detect(std::string image_filename, float thresh = 0.2); + + YOLODLL_API std::vector detect(image_t img, float thresh = 0.2); + + +#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); } ); + *image_ptr = mat_to_image(mat); + return detect(*image_ptr, thresh); + } + +private: + static image_t mat_to_image(cv::Mat img) + { + std::shared_ptr ipl_small = std::make_shared(img); + image_t im_small = ipl_to_image(ipl_small.get()); + rgbgr_image(im_small); + return im_small; + } + + 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 i, j, k, count = 0;; + + for (k = 0; k < c; ++k) { + for (i = 0; i < h; ++i) { + for (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; + } + + static void rgbgr_image(image_t im) + { + int i; + for (i = 0; i < im.w*im.h; ++i) { + float swap = im.data[i]; + im.data[i] = im.data[i + im.w*im.h * 2]; + im.data[i + im.w*im.h * 2] = swap; + } + } + + static void free_image(image_t m) + { + if (m.data) { + free(m.data); + } + } +#endif // OPENCV +}; + + +