diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5fc7350 --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ + +*.weights + +[Bb]uild/ +[Oo]bj/ +*.o +**/[Dd]ebug*/ +**/[Rr]elease*/ +**/gcc-debug/ +**/gcc-release/ +*.mode* +*.app/ +*.pyc +.svn/ +*.log +*.cpp.eep +*.cpp.elf +*.cpp.hex + +**/bin/*.dll +**/bin/*.exe +**/bin/*.ilk +**/bin/*.exp +**/bin/*.pdb +**/bin/*.lib +**/data/sounds + +# XCode +*.pbxuser +*.perspective +*.perspectivev3 +*.mode1v3 +*.mode2v3 +# XCode 4 +xcuserdata +*.xcworkspace + +# Code::Blocks +*.depend +*.layout + +# Visual Studio +*.sdf +*.opensdf +*.suo +*.pdb +*.ilk +*.aps +ipch/ + + +# OSX +.DS_Store +*.swp +*~.nib +# Thumbnails +._* + +# Windows +# Windows image file caches +Thumbs.db +# Folder config file +Desktop.ini diff --git a/addons.make b/addons.make new file mode 100644 index 0000000..f47512d --- /dev/null +++ b/addons.make @@ -0,0 +1 @@ +ofxGui diff --git a/bin/data/voc.names b/bin/data/voc.names new file mode 100644 index 0000000..8420ab3 --- /dev/null +++ b/bin/data/voc.names @@ -0,0 +1,20 @@ +aeroplane +bicycle +bird +boat +bottle +bus +car +cat +chair +cow +diningtable +dog +horse +motorbike +person +pottedplant +sheep +sofa +train +tvmonitor diff --git a/bin/data/yolo-voc.cfg b/bin/data/yolo-voc.cfg new file mode 100644 index 0000000..5650b4c --- /dev/null +++ b/bin/data/yolo-voc.cfg @@ -0,0 +1,259 @@ +[net] +# Testing +batch=1 +subdivisions=1 +# Training +# batch=64 +# subdivisions=8 +height=416 +width=416 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=.1 + +learning_rate=0.001 +burn_in=1000 +max_batches = 80200 +policy=steps +steps=40000,60000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + + +####### + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[route] +layers=-9 + +[convolutional] +batch_normalize=1 +size=1 +stride=1 +pad=1 +filters=64 +activation=leaky + +[reorg] +stride=2 + +[route] +layers=-1,-4 + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=125 +activation=linear + + +[region] +anchors = 1.3221, 1.73145, 3.19275, 4.00944, 5.05587, 8.09892, 9.47112, 4.84053, 11.2364, 10.0071 +bias_match=1 +classes=20 +coords=4 +num=5 +softmax=1 +jitter=.3 +rescore=1 + +object_scale=5 +noobject_scale=1 +class_scale=1 +coord_scale=1 + +absolute=1 +thresh = .6 +random=1 + diff --git a/dll/yolo_cpp_dll.dll b/dll/yolo_cpp_dll.dll new file mode 100644 index 0000000..902a77d Binary files /dev/null and b/dll/yolo_cpp_dll.dll differ diff --git a/dll/yolo_cpp_dll.lib b/dll/yolo_cpp_dll.lib new file mode 100644 index 0000000..91dd555 Binary files /dev/null and b/dll/yolo_cpp_dll.lib differ diff --git a/icon.rc b/icon.rc new file mode 100644 index 0000000..7e26eb3 --- /dev/null +++ b/icon.rc @@ -0,0 +1,8 @@ +// Icon Resource Definition +#define MAIN_ICON 102 + +#if defined(_DEBUG) +MAIN_ICON ICON "icon_debug.ico" +#else +MAIN_ICON ICON "icon.ico" +#endif diff --git a/include/yolo_v2_class.hpp b/include/yolo_v2_class.hpp new file mode 100644 index 0000000..34e220a --- /dev/null +++ b/include/yolo_v2_class.hpp @@ -0,0 +1,121 @@ +#pragma once +#include +#include +#include +#include + +#ifdef OPENCV +#include // C++ +#include "opencv2/highgui/highgui_c.h" // C +#include "opencv2/imgproc/imgproc_c.h" // C +#endif // OPENCV + +#ifdef YOLODLL_EXPORTS +#define YOLODLL_API __declspec(dllexport) +#else +#define YOLODLL_API __declspec(dllimport) +#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) +}; + +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 { + std::shared_ptr detector_gpu_ptr; +public: + float nms = .4; + + YOLODLL_API Detector(std::string cfg_filename, std::string weight_filename, int gpu_id = 0); + YOLODLL_API ~Detector(); + + 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); + + YOLODLL_API std::vector tracking(std::vector cur_bbox_vec, int const frames_story = 4); + +#ifdef OPENCV + std::vector detect(cv::Mat mat, float thresh = 0.2) + { + 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); + } + +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; + } + } + +#endif // OPENCV + + std::deque> prev_bbox_vec_deque; +}; + + + diff --git a/ofxYolo2.VC.VC.opendb b/ofxYolo2.VC.VC.opendb new file mode 100644 index 0000000..85c2558 Binary files /dev/null and b/ofxYolo2.VC.VC.opendb differ diff --git a/ofxYolo2.VC.db b/ofxYolo2.VC.db new file mode 100644 index 0000000..4fd5c27 Binary files /dev/null and b/ofxYolo2.VC.db differ diff --git a/ofxYolo2.sln b/ofxYolo2.sln new file mode 100644 index 0000000..96da0d5 --- /dev/null +++ b/ofxYolo2.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ofxYolo2", "ofxYolo2.vcxproj", "{7FD42DF7-442E-479A-BA76-D0022F99702A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openframeworksLib", "..\..\libs\openFrameworksCompiled\project\vs\openframeworksLib.vcxproj", "{5837595D-ACA9-485C-8E76-729040CE4B0B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.ActiveCfg = Debug|Win32 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.Build.0 = Debug|Win32 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.ActiveCfg = Debug|x64 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.Build.0 = Debug|x64 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|Win32.ActiveCfg = Release|Win32 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|Win32.Build.0 = Release|Win32 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|x64.ActiveCfg = Release|x64 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|x64.Build.0 = Release|x64 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.ActiveCfg = Debug|Win32 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.Build.0 = Debug|Win32 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.ActiveCfg = Debug|x64 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.Build.0 = Debug|x64 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|Win32.ActiveCfg = Release|Win32 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|Win32.Build.0 = Release|Win32 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|x64.ActiveCfg = Release|x64 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ofxYolo2.vcxproj b/ofxYolo2.vcxproj new file mode 100644 index 0000000..7aac8f8 --- /dev/null +++ b/ofxYolo2.vcxproj @@ -0,0 +1,206 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {7FD42DF7-442E-479A-BA76-D0022F99702A} + Win32Proj + ofxYolo2 + + + + Application + Unicode + v140 + + + Application + Unicode + v140 + + + Application + Unicode + true + v140 + + + Application + Unicode + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + bin\ + obj\$(Configuration)\ + $(ProjectName)_debug + true + true + + + bin\ + obj\$(Configuration)\ + $(ProjectName)_debug + true + true + + + bin\ + obj\$(Configuration)\ + false + + + bin\ + obj\$(Configuration)\ + false + + + + Disabled + EnableFastChecks + %(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + %(AdditionalIncludeDirectories);..\..\addons\ofxGui\src + CompileAsCpp + + + true + Console + false + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + + Disabled + EnableFastChecks + %(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + include;%(AdditionalIncludeDirectories);..\..\addons\ofxGui\src + Default + true + + + true + Console + false + yolo_cpp_dll.lib;%(AdditionalDependencies) + dll;%(AdditionalLibraryDirectories) + + + + + + false + %(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + %(AdditionalIncludeDirectories);..\..\addons\ofxGui\src + CompileAsCpp + true + + + false + false + Console + true + true + false + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + + false + %(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + include;%(AdditionalIncludeDirectories);..\..\addons\ofxGui\src + Default + + + false + false + Console + true + true + false + yolo_cpp_dll.lib;%(AdditionalDependencies) + dll;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + {5837595d-aca9-485c-8e76-729040ce4b0b} + + + + + /D_DEBUG %(AdditionalOptions) + /D_DEBUG %(AdditionalOptions) + $(OF_ROOT)\libs\openFrameworksCompiled\project\vs + + + + + + + + + + + + \ No newline at end of file diff --git a/ofxYolo2.vcxproj.filters b/ofxYolo2.vcxproj.filters new file mode 100644 index 0000000..d68b2f3 --- /dev/null +++ b/ofxYolo2.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + src + + + src + + + src + + + + + {d8376475-7454-4a24-b08a-aac121d3ad6f} + + + {71834F65-F3A9-211E-73B8-DC85} + + + + + src + + + src + + + + + + \ No newline at end of file diff --git a/ofxYolo2.vcxproj.user b/ofxYolo2.vcxproj.user new file mode 100644 index 0000000..988b987 --- /dev/null +++ b/ofxYolo2.vcxproj.user @@ -0,0 +1,19 @@ + + + + $(ProjectDir)/bin + WindowsLocalDebugger + + + $(ProjectDir)/bin + WindowsLocalDebugger + + + $(ProjectDir)/bin + WindowsLocalDebugger + + + $(ProjectDir)/bin + WindowsLocalDebugger + + \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..e57370b --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,13 @@ +#include "ofMain.h" +#include "ofApp.h" + +//======================================================================== +int main( ){ + ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp(new ofApp()); + +} diff --git a/src/ofApp.cpp b/src/ofApp.cpp new file mode 100644 index 0000000..2044c49 --- /dev/null +++ b/src/ofApp.cpp @@ -0,0 +1,90 @@ +#include "ofApp.h" + + +//-------------------------------------------------------------- +void ofApp::setup(){ + + yolo.setup(); + grabber.initGrabber(640, 480); + +} + +//-------------------------------------------------------------- +void ofApp::update(){ + + + grabber.update(); + if (grabber.isFrameNew()) { + lastResults = yolo.detect(grabber.getPixels()); + } + +} + +//-------------------------------------------------------------- +void ofApp::draw(){ + grabber.draw(ofVec2f(0, 0)); + + ofNoFill(); + + for (auto& r : lastResults) { + ofDrawRectangle(r.x, r.y, r.w, r.h); + ofDrawBitmapString(yolo.getName(r.obj_id) + " - " + ofToString(r.prob) ,r.x,r.y); + } + + +} + +//-------------------------------------------------------------- +void ofApp::keyPressed(int key){ + +} + +//-------------------------------------------------------------- +void ofApp::keyReleased(int key){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseMoved(int x, int y ){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseDragged(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void ofApp::mousePressed(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseReleased(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseEntered(int x, int y){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseExited(int x, int y){ + +} + +//-------------------------------------------------------------- +void ofApp::windowResized(int w, int h){ + +} + +//-------------------------------------------------------------- +void ofApp::gotMessage(ofMessage msg){ + +} + +//-------------------------------------------------------------- +void ofApp::dragEvent(ofDragInfo dragInfo){ + +} diff --git a/src/ofApp.h b/src/ofApp.h new file mode 100644 index 0000000..131e976 --- /dev/null +++ b/src/ofApp.h @@ -0,0 +1,32 @@ +#pragma once + + + +#include "ofMain.h" +#include "ofxYolo2.h" + +class ofApp : public ofBaseApp{ + + ofxYolo2 yolo; + ofVideoGrabber grabber; + + std::vector lastResults; + + public: + void setup(); + void update(); + void draw(); + + void keyPressed(int key); + void keyReleased(int key); + void mouseMoved(int x, int y ); + void mouseDragged(int x, int y, int button); + void mousePressed(int x, int y, int button); + void mouseReleased(int x, int y, int button); + void mouseEntered(int x, int y); + void mouseExited(int x, int y); + void windowResized(int w, int h); + void dragEvent(ofDragInfo dragInfo); + void gotMessage(ofMessage msg); + +}; diff --git a/src/ofxYolo2.cpp b/src/ofxYolo2.cpp new file mode 100644 index 0000000..b81ffe5 --- /dev/null +++ b/src/ofxYolo2.cpp @@ -0,0 +1,87 @@ +#include "ofxYolo2.h" + + + + +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; +} + + + +std::vector ofxYolo2::detect(ofPixels& pixels) { + + image_t convertedImage = convert(pixels); + std::vector results = detector->detect(convertedImage); + + free(convertedImage.data); + return results; +} + +void ofxYolo2::setup() { + + string config = ofToDataPath("yolo-voc.cfg"); + string weights = ofToDataPath("yolo-voc.weights"); + string names = ofToDataPath("voc.names"); + + detector = new Detector(config, weights); + objectNames = objects_names_from_file(names); +} + + +std::string ofxYolo2::getName(int index) { + if(index >= objectNames.size()) return ""; + return objectNames[index]; +} + + +image_t ofxYolo2::convert(ofPixels & pix) +{ + unsigned char *data = (unsigned char *)pix.getData(); + int h = pix.getHeight(); + int w = pix.getWidth(); + int c = pix.getNumChannels(); + int step = w * c; + image_t im;// = make_image_custom(w, h, c); + int i, j, k, count = 0;; + + im.data = (float *)calloc(h*w*c, sizeof(float)); + im.c = c; + im.h = h; + im.w = w; + + for (k = 0; k < c; ++k) { + for (i = 0; i < h; ++i) { + for (j = 0; j < w; ++j) { + im.data[count++] = data[i*step + j*c + k] / 255.; + } + } + } + + return im; +} + + + +// +//ofPixels ofxYolo2::convert(image_t & im) +//{ +// unsigned char *data = (unsigned char*)calloc(im.w*im.h*im.c, sizeof(char)); +// int i, k; +// for (k = 0; k < im.c; ++k) { +// for (i = 0; i < im.w*im.h; ++i) { +// data[i*im.c + k] = (unsigned char)(255 * im.data[i + k*im.w*im.h]); +// } +// } +// +// ofPixels pix; +// pix.setFromPixels(data, im.w, im.h, im.c); +// return pix; +//} + + diff --git a/src/ofxYolo2.h b/src/ofxYolo2.h new file mode 100644 index 0000000..a8da2f0 --- /dev/null +++ b/src/ofxYolo2.h @@ -0,0 +1,24 @@ +#pragma once + + +#include "yolo_v2_class.hpp" +#include "ofMain.h" + + + +class ofxYolo2 { + + Detector* detector; + std::vector objectNames; + +public: + + void setup(); + + std::string getName(int index); + image_t convert(ofPixels & pix); + + std::vector ofxYolo2::detect(ofPixels& pixels); + + +}; \ No newline at end of file