├── .gitignore ├── README.md ├── beifen ├── haar-frontface.xml ├── main.cpp ├── serial.cpp ├── serial.h └── template.h ├── cascade_TM ├── CMakeLists.txt ├── build │ └── fuck └── src │ ├── main.cpp │ └── template.h ├── cascade_staple ├── CMakeLists.txt ├── build │ └── fuck └── src │ ├── fhog.cpp │ ├── fhog.h │ ├── main.cpp │ ├── sse.hpp │ ├── staple_tracker.cpp │ └── staple_tracker.hpp ├── color_detect ├── CMakeLists.txt ├── ColorDetect.h ├── fuck └── main.cpp ├── serial_linux ├── CMakeLists.txt ├── build │ └── fuck └── src │ ├── main.cpp │ ├── serial.cpp │ └── serial.h ├── serial_windows ├── CMakeLists.txt └── src │ ├── main.cpp │ ├── serial.cpp │ └── serial.h ├── track_TM ├── CMakeLists.txt ├── build │ └── TM_track ├── main.cpp └── template.h ├── track_opencv ├── CMakeLists.txt ├── build │ └── tracker └── src │ └── tracker.cpp ├── track_staple ├── CMakeLists.txt ├── build │ └── stapleCC └── src │ ├── fhog.cpp │ ├── fhog.h │ ├── main.cpp │ ├── sse.hpp │ ├── staple_tracker.cpp │ └── staple_tracker.hpp ├── yolo_KCF ├── CMakeLists.txt ├── build │ ├── cfg │ │ ├── yolov3-head.cfg │ │ └── yolov3-tiny.cfg │ └── detect └── src │ ├── main.cpp │ ├── utils.h │ └── yolo_v2_class.hpp └── yolo_TM ├── CMakeLists.txt ├── build ├── cfg │ ├── yolov3-head.cfg │ └── yolov3-tiny.cfg └── detect └── src ├── main.cpp ├── template.h ├── utils.h └── yolo_v2_class.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Cmake files 2 | CMakeCache.txt 3 | CMakeFiles 4 | Makefile 5 | cmake_install.cmake 6 | 7 | # VS Code 8 | .vscode 9 | 10 | # windows backup 11 | beifen 12 | 13 | # Video 14 | *.avi 15 | *.mp4 16 | 17 | # Cascade 18 | *.xml 19 | 20 | # YOLO 21 | *.weights -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Detect-Track 2 | Four tracking algorithms organized with cascade classifier or YOLOv3 for object detection. 3 | - **Video Show** 4 | - http://v.youku.com/v_show/id_XMzYxODcyNjEzMg==.html 5 | - http://v.youku.com/v_show/id_XMzYxODcxODY2OA==.html 6 | - https://youtu.be/zZZoJIJmQd8 7 | - https://youtu.be/rImqJhreMy4 8 | 9 | ! Requires: OpenCV > 3.1.0 10 | 11 | ## [cascade_staple](cascade_staple) 12 | - 检测器:级联分类器 13 | - 跟踪器:staple 14 | 15 | ## [cascade_TM](cascade_TM) 16 | - 检测器:级联分类器 17 | - 跟踪器:Template tracker 18 | 19 | ## [yolo_TM](yolo_TM) 20 | - Requires: 自行编译[darknet](https://github.com/AlexeyAB/darknet),将生成的darknet.so复制到/usr/lib/目录下 21 | - 检测器:YOLOv3 22 | - 跟踪器:Template tracker 23 | 24 | ## [yolo_KCF](yolo_KCF) 25 | - Requires: Compiled with OpenCV_contrib 26 | - Requires: 自行编译[darknet](https://github.com/AlexeyAB/darknet),将生成的darknet.so复制到/usr/lib/目录下 27 | - 检测器:YOLOv3 28 | - 跟踪器:KCF 29 | 30 | ## [track_TM](track_TM) 31 | - 跟踪器:Template tracker 32 | 33 | ## [track_staple](track_staple) 34 | - 跟踪器:staple 35 | 36 | ## [track_opencv](track_opencv) 37 | - Requires: Compiled with OpenCV_contrib 38 | - 跟踪器:"BOOSTING", "MIL", "KCF", "TLD","MEDIANFLOW", "GOTURN", "CSRT" 39 | 40 | ## [color_detect](color_detect) 41 | - 颜色检测器 42 | 43 | ## [serial_linux](serial_linux) 44 | - linux串口通信封装 45 | 46 | ## [serial_windows](serial_windows) 47 | - windows串口通信封装 48 | -------------------------------------------------------------------------------- /beifen/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/beifen/main.cpp -------------------------------------------------------------------------------- /beifen/serial.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/beifen/serial.cpp -------------------------------------------------------------------------------- /beifen/serial.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/beifen/serial.h -------------------------------------------------------------------------------- /beifen/template.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | using namespace cv; 5 | 6 | class Template{ 7 | public: 8 | Template(); 9 | void initTracking(Mat frame, Rect box, int scale = 5); 10 | Rect track(Mat frame); 11 | Rect getLocation(); 12 | private: 13 | Mat model; 14 | Rect location; 15 | int scale; 16 | }; 17 | 18 | Template::Template() 19 | { 20 | this->scale = 5; 21 | } 22 | 23 | void Template::initTracking(Mat frame, Rect box, int scale) 24 | { 25 | this->location = box; 26 | this->scale = scale; 27 | 28 | if(frame.empty()) 29 | { 30 | cout << "ERROR: frame is empty." << endl; 31 | exit(0); 32 | } 33 | if(frame.channels() != 1) 34 | { 35 | cvtColor(frame, frame, CV_RGB2GRAY); 36 | } 37 | this->model = frame(box); 38 | } 39 | 40 | Rect Template::track(Mat frame) 41 | { 42 | if(frame.empty()) 43 | { 44 | cout << "ERROR: frame is empty." << endl; 45 | exit(0); 46 | } 47 | Mat gray; 48 | if(frame.channels() != 1) 49 | { 50 | cvtColor(frame, gray, CV_RGB2GRAY); 51 | } 52 | 53 | Rect searchWindow; 54 | searchWindow.width = this->location.width * scale; 55 | searchWindow.height = this->location.height * scale; 56 | searchWindow.x = this->location.x + this->location.width * 0.5 57 | - searchWindow.width * 0.5; 58 | searchWindow.y = this->location.y + this->location.height * 0.5 59 | - searchWindow.height * 0.5; 60 | searchWindow &= Rect(0, 0, frame.cols, frame.rows); 61 | 62 | Mat similarity; 63 | matchTemplate(gray(searchWindow), this->model, similarity, CV_TM_CCOEFF_NORMED); 64 | double mag_r; 65 | Point point; 66 | minMaxLoc(similarity, 0, &mag_r, 0, &point); 67 | this->location.x = point.x + searchWindow.x; 68 | this->location.y = point.y + searchWindow.y; 69 | 70 | this->model = gray(location); 71 | return this->location; 72 | } 73 | 74 | Rect Template::getLocation() 75 | { 76 | return this->location; 77 | } -------------------------------------------------------------------------------- /cascade_TM/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(fuck) 4 | 5 | SET(CMAKE_C_COMPILER g++) 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | add_compile_options(-std=c++11) 8 | message(STATUS "optional:-std=c++11") 9 | endif(CMAKE_COMPILER_IS_GNUCXX) 10 | 11 | find_package(OpenCV REQUIRED) 12 | 13 | message(STATUS "OpenCV library status:") 14 | message(STATUS " version: ${OpenCV_VERSION}") 15 | message(STATUS " libraries: ${OpenCV_LIBS}") 16 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 17 | 18 | if(CMAKE_VERSION VERSION_LESS "2.8.11") 19 | include_directories(${OpenCV_INCLUDE_DIRS}) 20 | endif() 21 | 22 | 23 | file(GLOB SRCS ./src/*.cpp) 24 | file(GLOB HDRS ./src/*.h*) 25 | 26 | set(traincascade_files ${SRCS} ${HDRS}) 27 | 28 | add_executable(fuck ${traincascade_files}) 29 | 30 | target_link_libraries(fuck ${OpenCV_LIBS}) 31 | -------------------------------------------------------------------------------- /cascade_TM/build/fuck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/cascade_TM/build/fuck -------------------------------------------------------------------------------- /cascade_TM/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "template.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | using namespace cv; 14 | 15 | void limitRect(cv::Rect &location, cv::Size sz) 16 | { 17 | cv::Rect window(cv::Point(0, 0), sz); 18 | location = location & window; 19 | } 20 | 21 | int main(int argc, char * argv[]) 22 | { 23 | //VideoWriter output_dst("newtracker.avi", CV_FOURCC('M', 'J', 'P', 'G'), 60, Size(640, 480), 1); 24 | Template tracker; 25 | cv::VideoCapture capture; 26 | capture.open("new.avi"); 27 | if(!capture.isOpened()) 28 | { 29 | std::cout << "fail to open" << std::endl; 30 | exit(0); 31 | } 32 | cv::String cascade_name = "cascade.xml";; 33 | cv::CascadeClassifier detector; 34 | if( !detector.load( cascade_name ) ) 35 | { 36 | printf("--(!)Error loading face cascade\n"); 37 | return -1; 38 | }; 39 | 40 | 41 | int64 tic, toc; 42 | double time = 0; 43 | bool show_visualization = true; 44 | int status = 0; //0:没有目标,1:找到目标进行跟踪 45 | cv::Mat frame; 46 | int frame_num = 0; 47 | Rect location; 48 | std::vector> result_rects; 49 | while ( capture.read(frame) ) 50 | { 51 | if( frame.empty() ) 52 | { 53 | printf(" --(!) No captured frame -- Break!"); 54 | break; 55 | } 56 | frame_num++; 57 | tic = cv::getTickCount(); 58 | if(status == 0) 59 | { 60 | //cout << "[debug] " << frame_num << ":" << " 没有目标" << endl; 61 | std::vector boards; 62 | cv::Mat frame_gray; 63 | cv::cvtColor( frame, frame_gray, COLOR_BGR2GRAY ); 64 | detector.detectMultiScale( frame_gray, boards, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(50, 50) ,Size(130, 130)); 65 | if(boards.size() > 0) 66 | { 67 | cout << "[debug] " << frame_num << ":" << " cascade找到" << boards.size() << "个目标" << endl; 68 | for(int i = 0; i < boards.size(); i++) 69 | { 70 | rectangle( frame, cvPoint(cvRound(boards[i].x), cvRound(boards[i].y)), 71 | cvPoint(cvRound((boards[i].x + boards[i].width-1)), cvRound((boards[i].y + boards[i].height-1))), 72 | Scalar( 20, 20, 20 ), 3, 8, 0); 73 | } 74 | cv::imshow("detectracker", frame); 75 | //waitKey(0); 76 | if(boards.size() == 1) 77 | location = boards[0]; 78 | else 79 | { 80 | int max_area = boards[0].width * boards[0].height; 81 | int max_index = 0; 82 | for(int i = 1; i < boards.size(); i++) 83 | { 84 | int area = boards[i].width * boards[i].height; 85 | if(area > max_index) 86 | { 87 | max_area = area; 88 | max_index = i; 89 | } 90 | } 91 | location = boards[max_index]; 92 | } 93 | tracker.initTracking(frame, location); 94 | status = 1; 95 | cout << "[debug] " << frame_num << ":" << " 开始跟踪" << endl; 96 | } 97 | } 98 | else if(status == 1) 99 | { 100 | location = tracker.track(frame); 101 | limitRect(location, frame.size()); 102 | if(location.empty()) 103 | { 104 | status = 0; 105 | continue; 106 | } 107 | // if(frame_num % 3 == 0) 108 | // { 109 | // Mat roi = frame(location); 110 | // imwrite("../data/" + to_string(frame_num) + ".jpg", roi); 111 | // } 112 | result_rects.push_back(location); 113 | if(frame_num % 10 == 0) 114 | { 115 | //在图片周围进行寻找 116 | int factor = 2; 117 | int newx = location.x + (1 - factor) * location.width / 2; 118 | int newy = location.y + (1 - factor) * location.height / 2; 119 | Rect loc = Rect(newx, newy, location.width * factor, location.height * factor); 120 | limitRect(loc, frame.size()); 121 | Mat roi = frame(loc); 122 | std::vector boards; 123 | detector.detectMultiScale( roi, boards, 1.1, 2, 124 | 0|CASCADE_SCALE_IMAGE, roi.size(), roi.size()); 125 | cout << "[debug] boards: " << boards.size() << endl; 126 | if(boards.size() <= 0) 127 | { 128 | status = 0; 129 | } 130 | else 131 | { 132 | //location = boards[0]; 133 | location = Rect(boards[0].x + loc.x, boards[0].y + loc.y, boards[0].width, boards[0].height); 134 | tracker.initTracking(frame,location); 135 | } 136 | } 137 | } 138 | toc = cv::getTickCount() - tic; 139 | time += toc; 140 | 141 | if (show_visualization) { 142 | cv::putText(frame, std::to_string(frame_num), cv::Point(20, 40), 6, 1, 143 | cv::Scalar(0, 255, 255), 2); 144 | if(status == 1) 145 | cv::rectangle(frame, location, cv::Scalar(0, 128, 255), 2); 146 | cv::imshow("detectracker", frame); 147 | //output_dst << frame; 148 | 149 | char key = cv::waitKey(10); 150 | if (key == 27 || key == 'q' || key == 'Q') 151 | break; 152 | } 153 | } 154 | 155 | time = time / double(cv::getTickFrequency()); 156 | double fps = double(frame_num) / time; 157 | std::cout << "fps:" << fps << std::endl; 158 | cv::destroyAllWindows(); 159 | 160 | return 0; 161 | } 162 | 163 | -------------------------------------------------------------------------------- /cascade_TM/src/template.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | using namespace cv; 5 | 6 | class Template{ 7 | public: 8 | Template(); 9 | void initTracking(Mat frame, Rect box, int scale = 5); 10 | Rect track(Mat frame); 11 | Rect getLocation(); 12 | private: 13 | Mat model; 14 | Rect location; 15 | int scale; 16 | }; 17 | 18 | Template::Template() 19 | { 20 | this->scale = 5; 21 | } 22 | 23 | void Template::initTracking(Mat frame, Rect box, int scale) 24 | { 25 | this->location = box; 26 | this->scale = scale; 27 | 28 | if(frame.empty()) 29 | { 30 | cout << "ERROR: frame is empty." << endl; 31 | exit(0); 32 | } 33 | if(frame.channels() != 1) 34 | { 35 | cvtColor(frame, frame, CV_RGB2GRAY); 36 | } 37 | this->model = frame(box); 38 | } 39 | 40 | Rect Template::track(Mat frame) 41 | { 42 | if(frame.empty()) 43 | { 44 | cout << "ERROR: frame is empty." << endl; 45 | exit(0); 46 | } 47 | Mat gray; 48 | if(frame.channels() != 1) 49 | { 50 | cvtColor(frame, gray, CV_RGB2GRAY); 51 | } 52 | 53 | Rect searchWindow; 54 | searchWindow.width = this->location.width * scale; 55 | searchWindow.height = this->location.height * scale; 56 | searchWindow.x = this->location.x + this->location.width * 0.5 57 | - searchWindow.width * 0.5; 58 | searchWindow.y = this->location.y + this->location.height * 0.5 59 | - searchWindow.height * 0.5; 60 | searchWindow &= Rect(0, 0, frame.cols, frame.rows); 61 | 62 | Mat similarity; 63 | matchTemplate(gray(searchWindow), this->model, similarity, CV_TM_CCOEFF_NORMED); 64 | double mag_r; 65 | Point point; 66 | minMaxLoc(similarity, 0, &mag_r, 0, &point); 67 | this->location.x = point.x + searchWindow.x; 68 | this->location.y = point.y + searchWindow.y; 69 | 70 | this->model = gray(location); 71 | return this->location; 72 | } 73 | 74 | Rect Template::getLocation() 75 | { 76 | return this->location; 77 | } -------------------------------------------------------------------------------- /cascade_staple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(fuck) 4 | 5 | SET(CMAKE_C_COMPILER g++) 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | add_compile_options(-std=c++11) 8 | message(STATUS "optional:-std=c++11") 9 | endif(CMAKE_COMPILER_IS_GNUCXX) 10 | 11 | find_package(OpenCV REQUIRED) 12 | 13 | message(STATUS "OpenCV library status:") 14 | message(STATUS " version: ${OpenCV_VERSION}") 15 | message(STATUS " libraries: ${OpenCV_LIBS}") 16 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 17 | 18 | if(CMAKE_VERSION VERSION_LESS "2.8.11") 19 | include_directories(${OpenCV_INCLUDE_DIRS}) 20 | endif() 21 | 22 | 23 | file(GLOB SRCS ./src/*.cpp) 24 | file(GLOB HDRS ./src/*.h*) 25 | 26 | set(traincascade_files ${SRCS} ${HDRS}) 27 | 28 | add_executable(fuck ${traincascade_files}) 29 | 30 | target_link_libraries(fuck ${OpenCV_LIBS}) 31 | -------------------------------------------------------------------------------- /cascade_staple/build/fuck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/cascade_staple/build/fuck -------------------------------------------------------------------------------- /cascade_staple/src/fhog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | #include "fhog.h" 7 | #undef MIN 8 | 9 | // platform independent aligned memory allocation (see also alFree) 10 | void* alMalloc( size_t size, int alignment ) { 11 | const size_t pSize = sizeof(void*), a = alignment-1; 12 | void *raw = wrMalloc(size + a + pSize); 13 | void *aligned = (void*) (((size_t) raw + pSize + a) & ~a); 14 | *(void**) ((size_t) aligned-pSize) = raw; 15 | return aligned; 16 | } 17 | 18 | // platform independent alignned memory de-allocation (see also alMalloc) 19 | void alFree(void* aligned) { 20 | void* raw = *(void**)((char*)aligned-sizeof(void*)); 21 | wrFree(raw); 22 | } 23 | 24 | /******************************************************************************* 25 | * Piotr's Computer Vision Matlab Toolbox Version 3.30 26 | * Copyright 2014 Piotr Dollar & Ron Appel. [pdollar-at-gmail.com] 27 | * Licensed under the Simplified BSD License [see external/bsd.txt] 28 | *******************************************************************************/ 29 | // #include "wrappers.hpp" 30 | 31 | #define PI 3.14159265f 32 | 33 | // compute x and y gradients for just one column (uses sse) 34 | void grad1( float *I, float *Gx, float *Gy, int h, int w, int x ) { 35 | int y, y1; float *Ip, *In, r; __m128 *_Ip, *_In, *_G, _r; 36 | // compute column of Gx 37 | Ip=I-h; In=I+h; r=.5f; 38 | if(x==0) { r=1; Ip+=h; } else if(x==w-1) { r=1; In-=h; } 39 | if( h<4 || h%4>0 || (size_t(I)&15) || (size_t(Gx)&15) ) { 40 | for( y=0; yh-1) y1=h-1; 50 | GRADY(1); Ip--; for(y=1; y PI-1e-6f ) a1[i]=PI-1e-6f; 74 | init=true; return a1; 75 | } 76 | 77 | // compute gradient magnitude and orientation at each location (uses sse) 78 | void gradMag( float *I, float *M, float *O, int h, int w, int d, bool full ) { 79 | int x, y, y1, c, h4, s; float *Gx, *Gy, *M2; __m128 *_Gx, *_Gy, *_M2, _m; 80 | float *acost = acosTable(), acMult=10000.0f; 81 | // allocate memory for storing one column of output (padded so h4%4==0) 82 | h4=(h%4==0) ? h : h-(h%4)+4; s=d*h4*sizeof(float); 83 | M2=(float*) alMalloc(s,16); _M2=(__m128*) M2; 84 | Gx=(float*) alMalloc(s,16); _Gx=(__m128*) Gx; 85 | Gy=(float*) alMalloc(s,16); _Gy=(__m128*) Gy; 86 | // compute gradient magnitude and orientation for each column 87 | for( x=0; x=oMax) o0=0; O0[i]=o0; 157 | o1=o0+nb; if(o1==oMax) o1=0; O1[i]=o1; 158 | m=M[i]*norm; M1[i]=od*m; M0[i]=m-M1[i]; 159 | } else for(; i=oMax) o0=0; O0[i]=o0; 162 | M0[i]=M[i]*norm; M1[i]=0; O1[i]=0; 163 | } 164 | } 165 | 166 | // compute nOrients gradient histograms per bin x bin block of pixels 167 | void gradHist( float *M, float *O, float *H, int h, int w, 168 | int bin, int nOrients, int softBin, bool full ) 169 | { 170 | const int hb=h/bin, wb=w/bin, h0=hb*bin, w0=wb*bin, nb=wb*hb; 171 | const float s=(float)bin, sInv=1/s, sInv2=1/s/s; 172 | float *H0, *H1, *M0, *M1; int x, y; int *O0, *O1; float xb, init; 173 | O0=(int*)alMalloc(h*sizeof(int),16); M0=(float*) alMalloc(h*sizeof(float),16); 174 | O1=(int*)alMalloc(h*sizeof(int),16); M1=(float*) alMalloc(h*sizeof(float),16); 175 | // main loop 176 | for( x=0; x=0); 179 | 180 | if( softBin<0 && softBin%2==0 ) { 181 | // no interpolation w.r.t. either orienation or spatial bin 182 | H1=H+(x/bin)*hb; 183 | #define GH H1[O0[y]]+=M0[y]; y++; 184 | if( bin==1 ) for(y=0; y=0; xb0 = hasLf?(int)xb:-1; hasRt = xb0 < wb-1; 208 | xd=xb-xb0; xb+=sInv; yb=init; y=0; 209 | // macros for code conciseness 210 | #define GHinit yd=yb-yb0; yb+=sInv; H0=H+xb0*hb+yb0; xyd=xd*yd; \ 211 | ms[0]=1-xd-yd+xyd; ms[1]=yd-xyd; ms[2]=xd-xyd; ms[3]=xyd; 212 | #define GH(H,ma,mb) H1=H; sse::STRu(*H1,sse::ADD(sse::LDu(*H1),sse::MUL(ma,mb))); 213 | // leading rows, no top bin 214 | for( ; y=hb-1) break; GHinit; _m0=sse::SET(M0[y]); 222 | if(hasLf) { _m=sse::SET(0,0,ms[1],ms[0]); GH(H0+O0[y],_m,_m0); } 223 | if(hasRt) { _m=sse::SET(0,0,ms[3],ms[2]); GH(H0+O0[y]+hb,_m,_m0); } 224 | } else for( ; ; y++ ) { 225 | yb0 = (int) yb; if(yb0>=hb-1) break; GHinit; 226 | _m0=sse::SET(M0[y]); _m1=sse::SET(M1[y]); 227 | if(hasLf) { _m=sse::SET(0,0,ms[1],ms[0]); 228 | GH(H0+O0[y],_m,_m0); GH(H0+O1[y],_m,_m1); } 229 | if(hasRt) { _m=sse::SET(0,0,ms[3],ms[2]); 230 | GH(H0+O0[y]+hb,_m,_m0); GH(H0+O1[y]+hb,_m,_m1); } 231 | } 232 | // final rows, no bottom bin 233 | for( ; yclip) t=clip; c++; 279 | const float r=.2357f; int o, x, y, c; float t; 280 | const int nb=wb*hb, nbo=nOrients*nb, hb1=hb+1; 281 | for( o=0; onl1 ) mexErrMsgTxt("Incorrect number of outputs."); 359 | if( nrnr1 ) mexErrMsgTxt("Incorrect number of inputs."); 360 | nDims = mxGetNumberOfDimensions(pr[0]); dims = mxGetDimensions(pr[0]); 361 | *h=dims[0]; *w=dims[1]; *d=(nDims==2) ? 1 : dims[2]; *I = mxGetPr(pr[0]); 362 | if( nDims!=2 && nDims!=3 ) mexErrMsgTxt("I must be a 2D or 3D array."); 363 | if( mxGetClassID(pr[0])!=id ) mexErrMsgTxt("I has incorrect type."); 364 | } 365 | 366 | // [Gx,Gy] = grad2(I) - see gradient2.m 367 | void mGrad2( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 368 | int h, w, d; float *I, *Gx, *Gy; 369 | checkArgs(nl,pl,nr,pr,1,2,1,1,&h,&w,&d,mxSINGLE_CLASS,(void**)&I); 370 | if(h<2 || w<2) mexErrMsgTxt("I must be at least 2x2."); 371 | pl[0]= mxCreateMatrix3( h, w, d, mxSINGLE_CLASS, 0, (void**) &Gx ); 372 | pl[1]= mxCreateMatrix3( h, w, d, mxSINGLE_CLASS, 0, (void**) &Gy ); 373 | grad2( I, Gx, Gy, h, w, d ); 374 | } 375 | 376 | // [M,O] = gradMag( I, channel, full ) - see gradientMag.m 377 | void mGradMag( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 378 | int h, w, d, c, full; float *I, *M, *O=0; 379 | checkArgs(nl,pl,nr,pr,1,2,3,3,&h,&w,&d,mxSINGLE_CLASS,(void**)&I); 380 | if(h<2 || w<2) mexErrMsgTxt("I must be at least 2x2."); 381 | c = (int) mxGetScalar(pr[1]); full = (int) mxGetScalar(pr[2]); 382 | if( c>0 && c<=d ) { I += h*w*(c-1); d=1; } 383 | pl[0] = mxCreateMatrix3(h,w,1,mxSINGLE_CLASS,0,(void**)&M); 384 | if(nl>=2) pl[1] = mxCreateMatrix3(h,w,1,mxSINGLE_CLASS,0,(void**)&O); 385 | gradMag(I, M, O, h, w, d, full>0 ); 386 | } 387 | 388 | // gradMagNorm( M, S, norm ) - operates on M - see gradientMag.m 389 | void mGradMagNorm( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 390 | int h, w, d; float *M, *S, norm; 391 | checkArgs(nl,pl,nr,pr,0,0,3,3,&h,&w,&d,mxSINGLE_CLASS,(void**)&M); 392 | if( mxGetM(pr[1])!=h || mxGetN(pr[1])!=w || d!=1 || 393 | mxGetClassID(pr[1])!=mxSINGLE_CLASS ) mexErrMsgTxt("M or S is bad."); 394 | S = (float*) mxGetPr(pr[1]); norm = (float) mxGetScalar(pr[2]); 395 | gradMagNorm(M,S,h,w,norm); 396 | } 397 | 398 | // H=gradHist(M,O,[...]) - see gradientHist.m 399 | void mGradHist( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 400 | int h, w, d, hb, wb, nChns, binSize, nOrients, softBin, useHog; 401 | bool full; float *M, *O, *H, clipHog; 402 | checkArgs(nl,pl,nr,pr,1,3,2,8,&h,&w,&d,mxSINGLE_CLASS,(void**)&M); 403 | O = (float*) mxGetPr(pr[1]); 404 | if( mxGetM(pr[1])!=h || mxGetN(pr[1])!=w || d!=1 || 405 | mxGetClassID(pr[1])!=mxSINGLE_CLASS ) mexErrMsgTxt("M or O is bad."); 406 | binSize = (nr>=3) ? (int) mxGetScalar(pr[2]) : 8; 407 | nOrients = (nr>=4) ? (int) mxGetScalar(pr[3]) : 9; 408 | softBin = (nr>=5) ? (int) mxGetScalar(pr[4]) : 1; 409 | useHog = (nr>=6) ? (int) mxGetScalar(pr[5]) : 0; 410 | clipHog = (nr>=7) ? (float) mxGetScalar(pr[6]) : 0.2f; 411 | full = (nr>=8) ? (bool) (mxGetScalar(pr[7])>0) : false; 412 | hb = h/binSize; wb = w/binSize; 413 | nChns = useHog== 0 ? nOrients : (useHog==1 ? nOrients*4 : nOrients*3+5); 414 | pl[0] = mxCreateMatrix3(hb,wb,nChns,mxSINGLE_CLASS,1,(void**)&H); 415 | if( nOrients==0 ) return; 416 | if( useHog==0 ) { 417 | gradHist( M, O, H, h, w, binSize, nOrients, softBin, full ); 418 | } else if(useHog==1) { 419 | hog( M, O, H, h, w, binSize, nOrients, softBin, full, clipHog ); 420 | } else { 421 | fhog( M, O, H, h, w, binSize, nOrients, softBin, clipHog ); 422 | } 423 | } 424 | 425 | // inteface to various gradient functions (see corresponding Matlab functions) 426 | void mexFunction( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 427 | int f; char action[1024]; f=mxGetString(pr[0],action,1024); nr--; pr++; 428 | if(f) mexErrMsgTxt("Failed to get action."); 429 | else if(!strcmp(action,"gradient2")) mGrad2(nl,pl,nr,pr); 430 | else if(!strcmp(action,"gradientMag")) mGradMag(nl,pl,nr,pr); 431 | else if(!strcmp(action,"gradientMagNorm")) mGradMagNorm(nl,pl,nr,pr); 432 | else if(!strcmp(action,"gradientHist")) mGradHist(nl,pl,nr,pr); 433 | else mexErrMsgTxt("Invalid action."); 434 | } 435 | #endif 436 | 437 | 438 | float* crop_H(float *H,int* h_height,int* h_width,int depth,int dh,int dw) { 439 | int crop_h = *h_height-dh-1; 440 | int crop_w = *h_width-dw-1; 441 | float* crop_H = new float[crop_h*crop_w*depth]; 442 | 443 | for(int i = 1;i < *h_height-dh;i ++) 444 | for(int j = 1;j < *h_width-dw;j ++) 445 | for(int k = 0;k < depth;k ++) 446 | crop_H[i-1 + (j-1)*(crop_h) + k*(crop_h*crop_w)] = H[k*(*h_width * *h_height) + j*(*h_height) + i]; 447 | delete H; 448 | *h_height = crop_h;*h_width = crop_w; 449 | return crop_H; 450 | } 451 | 452 | float* fhog(float *M,float* O,int height,int width,int channel,int *h,int *w,int *d,int binSize, int nOrients, float clip, bool crop) { 453 | *h = height/binSize; 454 | *w = width/binSize; 455 | *d = nOrients*3+5; 456 | 457 | float* H = new float[(*h)*(*w)*(*d)]; 458 | memset(H,0.0f,(*h)*(*w)*(*d)*sizeof(float)); 459 | 460 | fhog( M, O, H, height, width, binSize, nOrients, -1, clip ); 461 | 462 | if(!crop) 463 | return H; 464 | return crop_H(H,h,w,*d,height%binSize < binSize/2,width%binSize < binSize/2); 465 | } 466 | 467 | void fhog(cv::MatND &fhog_feature, const cv::Mat& input, int binSize, int nOrients, float clip, bool crop) { 468 | int HEIGHT = input.rows; 469 | int WIDTH = input.cols; 470 | int DEPTH = input.channels(); 471 | 472 | float *II = new float[HEIGHT*WIDTH*DEPTH]; 473 | int count=0; 474 | 475 | // MatLab:: RGB, OpenCV: BGR 476 | 477 | for (int i = 0; i < WIDTH; i++) { 478 | for (int j = 0; j < HEIGHT; j++) { 479 | cv::Vec3b p = input.at(j,i); 480 | II[count+2] = p[0]; // B->R 481 | II[count+1] = p[1]; // G->G 482 | II[count+0] = p[2]; // R->B 483 | count += 3; 484 | } 485 | } 486 | 487 | float *I = new float[HEIGHT*WIDTH*DEPTH]; 488 | 489 | // channel x width x height 490 | for (int i = 0; i < WIDTH; i++) { 491 | for (int j = 0; j < HEIGHT; j++) { 492 | for (int k = 0; k < DEPTH; k++) { 493 | I[k*WIDTH*HEIGHT+i*HEIGHT+j] = II[i*HEIGHT*DEPTH+j*DEPTH+k]; 494 | } 495 | } 496 | } 497 | 498 | float *M = new float[HEIGHT*WIDTH], *O = new float[HEIGHT*WIDTH]; 499 | gradMag(I, M, O, HEIGHT, WIDTH, DEPTH, true); 500 | 501 | int h,w,d; 502 | float* HH = fhog(M,O,HEIGHT,WIDTH,DEPTH,&h,&w,&d,binSize,nOrients,clip,crop); 503 | float* H = new float[w*h*d]; 504 | 505 | for(int i = 0;i < w; i++) 506 | for(int j = 0;j < h; j++) 507 | for(int k = 0;k < d; k++) 508 | //H[i*h*d+j*d+k] = HH[k*w*h+i*h+j]; // ->hwd 509 | H[j*w*d+i*d+k] = HH[k*w*h+i*h+j]; // ->whd 510 | 511 | fhog_feature = cv::MatND(h,w,CV_32FC(32),H).clone(); 512 | 513 | delete[] H; 514 | 515 | delete[] M; delete[] O; 516 | delete[] II;delete[] I;delete[] HH; 517 | } 518 | 519 | void fhog28(cv::MatND &fhog_feature, const cv::Mat& input, int binSize, int nOrients, float clip, bool crop) { 520 | int HEIGHT = input.rows; 521 | int WIDTH = input.cols; 522 | int DEPTH = input.channels(); 523 | 524 | float *II = new float[WIDTH*HEIGHT*DEPTH]; 525 | int count=0; 526 | 527 | // MatLab:: RGB, OpenCV: BGR 528 | 529 | for (int i = 0; i < WIDTH; i++) { 530 | for (int j = 0; j < HEIGHT; j++) { 531 | cv::Vec3b p = input.at(j,i); 532 | II[count+2] = p[0]; // B->R 533 | II[count+1] = p[1]; // G->G 534 | II[count+0] = p[2]; // R->B 535 | count += 3; 536 | } 537 | } 538 | 539 | float *I = new float[HEIGHT*WIDTH*DEPTH]; 540 | 541 | // channel x width x height 542 | for (int i = 0; i < WIDTH; i++) { 543 | for (int j = 0; j < HEIGHT; j++) { 544 | for (int k = 0; k < DEPTH; k++) { 545 | I[k*WIDTH*HEIGHT+i*HEIGHT+j] = II[i*HEIGHT*DEPTH+j*DEPTH+k]; 546 | } 547 | } 548 | } 549 | 550 | float *M = new float[HEIGHT*WIDTH], *O = new float[HEIGHT*WIDTH]; 551 | gradMag(I, M, O, HEIGHT, WIDTH, DEPTH, true); 552 | 553 | int h,w,d; 554 | float* HH = fhog(M,O,HEIGHT,WIDTH,DEPTH,&h,&w,&d,binSize,nOrients,clip,crop); 555 | 556 | #undef CHANNELS 557 | #define CHANNELS 28 558 | 559 | assert(d >= CHANNELS); 560 | 561 | // out = zeros(h, w, 28, 'single'); 562 | // out(:,:,2:28) = temp(:,:,1:27); 563 | 564 | float* H = new float[w*h*CHANNELS]; 565 | 566 | for(int i = 0;i < w; i++) 567 | for(int j = 0;j < h; j++) { 568 | //H[i*h*CHANNELS+j*CHANNELS+0] = 0.0; 569 | H[j*w*CHANNELS+i*CHANNELS+0] = 0.0; 570 | for(int k = 0;k < CHANNELS-1;k++) { 571 | //H[i*h*CHANNELS+j*CHANNELS+k+1] = HH[k*w*h+i*h+j]; // ->hwd 572 | H[j*w*CHANNELS+i*CHANNELS+k+1] = HH[k*w*h+i*h+j]; // ->whd 573 | } 574 | } 575 | 576 | fhog_feature = cv::MatND(h,w,CV_32FC(CHANNELS),H).clone(); 577 | 578 | delete[] H; 579 | 580 | delete[] M; delete[] O; 581 | delete[] II;delete[] I;delete[] HH; 582 | } 583 | 584 | void fhog31(cv::MatND &fhog_feature, const cv::Mat& input, int binSize, int nOrients, float clip, bool crop) { 585 | int HEIGHT = input.rows; 586 | int WIDTH = input.cols; 587 | int DEPTH = input.channels(); 588 | 589 | float *II = new float[WIDTH*HEIGHT*DEPTH]; 590 | int count=0; 591 | 592 | // MatLab:: RGB, OpenCV: BGR 593 | 594 | for (int i = 0; i < WIDTH; i++) { 595 | for (int j = 0; j < HEIGHT; j++) { 596 | cv::Vec3b p = input.at(j,i); 597 | II[count+2] = p[0]; // B->R 598 | II[count+1] = p[1]; // G->G 599 | II[count+0] = p[2]; // R->B 600 | count += 3; 601 | } 602 | } 603 | 604 | float *I = new float[HEIGHT*WIDTH*DEPTH]; 605 | 606 | // channel x width x height 607 | for (int i = 0; i < WIDTH; i++) { 608 | for (int j = 0; j < HEIGHT; j++) { 609 | for (int k = 0; k < DEPTH; k++) { 610 | I[k*WIDTH*HEIGHT+i*HEIGHT+j] = II[i*HEIGHT*DEPTH+j*DEPTH+k]; 611 | } 612 | } 613 | } 614 | 615 | float *M = new float[HEIGHT*WIDTH], *O = new float[HEIGHT*WIDTH]; 616 | gradMag(I, M, O, HEIGHT, WIDTH, DEPTH, true); 617 | 618 | int h,w,d; 619 | float* HH = fhog(M,O,HEIGHT,WIDTH,DEPTH,&h,&w,&d,binSize,nOrients,clip,crop); 620 | 621 | #undef CHANNELS 622 | #define CHANNELS 31 623 | 624 | assert(d >= CHANNELS); 625 | 626 | // out = zeros(h, w, 31, 'single'); 627 | // out(:,:,1:31) = temp(:,:,1:31); 628 | 629 | float* H = new float[w*h*CHANNELS]; 630 | 631 | for(int i = 0;i < w; i++) 632 | for(int j = 0;j < h; j++) { 633 | for(int k = 0;k < CHANNELS;k++) { 634 | //H[i*h*CHANNELS+j*CHANNELS+k+1] = HH[k*w*h+i*h+j]; // ->hwd 635 | H[j*w*CHANNELS+i*CHANNELS+k] = HH[k*w*h+i*h+j]; // ->whd 636 | } 637 | } 638 | 639 | fhog_feature = cv::MatND(h,w,CV_32FC(CHANNELS),H).clone(); 640 | 641 | delete[] H; 642 | 643 | delete[] M; delete[] O; 644 | delete[] II;delete[] I;delete[] HH; 645 | } 646 | -------------------------------------------------------------------------------- /cascade_staple/src/fhog.h: -------------------------------------------------------------------------------- 1 | #ifndef FHOG_H 2 | #define FHOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "sse.hpp" 8 | 9 | #include 10 | 11 | /** 12 | Inputs: 13 | float* I - a gray or color image matrix with shape = channel x width x height 14 | int *h, *w, *d - return the size of the returned hog features 15 | int binSize -[8] spatial bin size 16 | int nOrients -[9] number of orientation bins 17 | float clip -[.2] value at which to clip histogram bins 18 | bool crop -[false] if true crop boundaries 19 | 20 | Return: 21 | float* H - computed hog features with shape: (nOrients*3+5) x (w/binSize) x (h/binSize), if not crop 22 | 23 | Author: 24 | Sophia 25 | Date: 26 | 2015-01-15 27 | **/ 28 | 29 | float* fhog(float* I,int height,int width,int channel,int *h,int *w,int *d,int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 30 | void fhog(cv::MatND &fhog_feature, const cv::Mat& input, int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 31 | void fhog28(cv::MatND &fhog_feature, const cv::Mat& input, int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 32 | void fhog31(cv::MatND &fhog_feature, const cv::Mat& input, int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 33 | 34 | // wrapper functions if compiling from C/C++ 35 | inline void wrError(const char *errormsg) { throw errormsg; } 36 | inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size); } 37 | inline void* wrMalloc( size_t size ) { return malloc(size); } 38 | inline void wrFree( void * ptr ) { free(ptr); } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /cascade_staple/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "staple_tracker.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | using namespace cv; 14 | 15 | void limitRect(cv::Rect &location, cv::Size sz) 16 | { 17 | cv::Rect window(cv::Point(0, 0), sz); 18 | location = location & window; 19 | } 20 | 21 | int main(int argc, char * argv[]) 22 | { 23 | //VideoWriter output_dst("detectracker.avi", CV_FOURCC('M', 'J', 'P', 'G'), 23, Size(640, 480), 1); 24 | STAPLE_TRACKER staple; 25 | cv::VideoCapture capture; 26 | capture.open("new.avi"); 27 | if(!capture.isOpened()) 28 | { 29 | std::cout << "fail to open" << std::endl; 30 | exit(0); 31 | } 32 | cv::String cascade_name = "cascade.xml";; 33 | cv::CascadeClassifier detector; 34 | if( !detector.load( cascade_name ) ) 35 | { 36 | printf("--(!)Error loading face cascade\n"); 37 | return -1; 38 | }; 39 | 40 | 41 | int64 tic, toc; 42 | double time = 0; 43 | bool show_visualization = true; 44 | int status = 0; //0:没有目标,1:找到目标进行跟踪 45 | cv::Mat frame; 46 | int frame_num = 0; 47 | Rect location; 48 | std::vector> result_rects; 49 | while ( capture.read(frame) ) 50 | { 51 | if( frame.empty() ) 52 | { 53 | printf(" --(!) No captured frame -- Break!"); 54 | break; 55 | } 56 | frame_num++; 57 | tic = cv::getTickCount(); 58 | if(status == 0) 59 | { 60 | //cout << "[debug] " << frame_num << ":" << " 没有目标" << endl; 61 | std::vector boards; 62 | cv::Mat frame_gray; 63 | cv::cvtColor( frame, frame_gray, COLOR_BGR2GRAY ); 64 | detector.detectMultiScale( frame_gray, boards, 1.1, 2, 0|CASCADE_SCALE_IMAGE, Size(60, 60) ,Size(100, 100)); 65 | if(boards.size() > 0) 66 | { 67 | cout << "[debug] " << frame_num << ":" << " cascade找到" << boards.size() << "个目标" << endl; 68 | for(int i = 0; i < boards.size(); i++) 69 | { 70 | rectangle( frame, cvPoint(cvRound(boards[i].x), cvRound(boards[i].y)), 71 | cvPoint(cvRound((boards[i].x + boards[i].width-1)), cvRound((boards[i].y + boards[i].height-1))), 72 | Scalar( 20, 20, 20 ), 3, 8, 0); 73 | } 74 | cv::imshow("detectracker", frame); 75 | //waitKey(0); 76 | if(boards.size() == 1) 77 | location = boards[0]; 78 | else 79 | { 80 | int max_area = boards[0].width * boards[0].height; 81 | int max_index = 0; 82 | for(int i = 1; i < boards.size(); i++) 83 | { 84 | int area = boards[i].width * boards[i].height; 85 | if(area > max_index) 86 | { 87 | max_area = area; 88 | max_index = i; 89 | } 90 | } 91 | location = boards[max_index]; 92 | } 93 | staple.tracker_staple_initialize(frame, location); 94 | staple.tracker_staple_train(frame, true); 95 | status = 1; 96 | cout << "[debug] " << frame_num << ":" << " 开始跟踪" << endl; 97 | } 98 | } 99 | else if(status == 1) 100 | { 101 | location = staple.tracker_staple_update(frame); 102 | limitRect(location, frame.size()); 103 | if(location.empty()) 104 | { 105 | status = 0; 106 | continue; 107 | } 108 | // if(frame_num % 3 == 0) 109 | // { 110 | // Mat roi = frame(location); 111 | // imwrite("../data/" + to_string(frame_num) + ".jpg", roi); 112 | // } 113 | 114 | staple.tracker_staple_train(frame, false); 115 | result_rects.push_back(location); 116 | if(frame_num % 10 == 0) 117 | { 118 | Mat roi = frame(location); 119 | std::vector boards; 120 | detector.detectMultiScale( roi, boards, 1.1, 2, 121 | 0|CASCADE_SCALE_IMAGE, roi.size(), roi.size()); 122 | cout << "[debug] boards: " << boards.size() << endl; 123 | if(boards.size() <= 0) 124 | { 125 | status = 0; 126 | } 127 | } 128 | } 129 | toc = cv::getTickCount() - tic; 130 | time += toc; 131 | 132 | if (show_visualization) { 133 | cv::putText(frame, std::to_string(frame_num), cv::Point(20, 40), 6, 1, 134 | cv::Scalar(0, 255, 255), 2); 135 | if(status == 1) 136 | cv::rectangle(frame, location, cv::Scalar(0, 128, 255), 2); 137 | cv::imshow("detectracker", frame); 138 | //output_dst << frame; 139 | 140 | char key = cv::waitKey(10); 141 | if (key == 27 || key == 'q' || key == 'Q') 142 | break; 143 | } 144 | } 145 | 146 | time = time / double(cv::getTickFrequency()); 147 | double fps = double(frame_num) / time; 148 | std::cout << "fps:" << fps << std::endl; 149 | cv::destroyAllWindows(); 150 | 151 | return 0; 152 | } 153 | 154 | -------------------------------------------------------------------------------- /cascade_staple/src/sse.hpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Piotr's Computer Vision Matlab Toolbox Version 3.23 3 | * Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] 4 | * Licensed under the Simplified BSD License [see external/bsd.txt] 5 | *******************************************************************************/ 6 | #ifndef _SSE_HPP_ 7 | #define _SSE_HPP_ 8 | #include // SSE2:, SSE3:, SSE4: 9 | 10 | namespace sse{ 11 | 12 | #define RETf inline __m128 13 | #define RETi inline __m128i 14 | 15 | // set, load and store values 16 | RETf SET( const float &x ) { return _mm_set1_ps(x); } 17 | RETf SET( float x, float y, float z, float w ) { return _mm_set_ps(x,y,z,w); } 18 | RETi SET( const int &x ) { return _mm_set1_epi32(x); } 19 | RETf LD( const float &x ) { return _mm_load_ps(&x); } 20 | RETf LDu( const float &x ) { return _mm_loadu_ps(&x); } 21 | RETf STR( float &x, const __m128 y ) { _mm_store_ps(&x,y); return y; } 22 | RETf STR1( float &x, const __m128 y ) { _mm_store_ss(&x,y); return y; } 23 | RETf STRu( float &x, const __m128 y ) { _mm_storeu_ps(&x,y); return y; } 24 | RETf STR( float &x, const float y ) { return STR(x,SET(y)); } 25 | 26 | // arithmetic operators 27 | RETi ADD( const __m128i x, const __m128i y ) { return _mm_add_epi32(x,y); } 28 | RETf ADD( const __m128 x, const __m128 y ) { return _mm_add_ps(x,y); } 29 | RETf ADD( const __m128 x, const __m128 y, const __m128 z ) { 30 | return ADD(ADD(x,y),z); } 31 | RETf ADD( const __m128 a, const __m128 b, const __m128 c, const __m128 &d ) { 32 | return ADD(ADD(ADD(a,b),c),d); } 33 | RETf SUB( const __m128 x, const __m128 y ) { return _mm_sub_ps(x,y); } 34 | RETf MUL( const __m128 x, const __m128 y ) { return _mm_mul_ps(x,y); } 35 | RETf MUL( const __m128 x, const float y ) { return MUL(x,SET(y)); } 36 | RETf MUL( const float x, const __m128 y ) { return MUL(SET(x),y); } 37 | RETf INC( __m128 &x, const __m128 y ) { return x = ADD(x,y); } 38 | RETf INC( float &x, const __m128 y ) { __m128 t=ADD(LD(x),y); return STR(x,t); } 39 | RETf DEC( __m128 &x, const __m128 y ) { return x = SUB(x,y); } 40 | RETf DEC( float &x, const __m128 y ) { __m128 t=SUB(LD(x),y); return STR(x,t); } 41 | RETf MIN( const __m128 x, const __m128 y ) { return _mm_min_ps(x,y); } 42 | RETf RCP( const __m128 x ) { return _mm_rcp_ps(x); } 43 | RETf RCPSQRT( const __m128 x ) { return _mm_rsqrt_ps(x); } 44 | 45 | // logical operators 46 | RETf AND( const __m128 x, const __m128 y ) { return _mm_and_ps(x,y); } 47 | RETi AND( const __m128i x, const __m128i y ) { return _mm_and_si128(x,y); } 48 | RETf ANDNOT( const __m128 x, const __m128 y ) { return _mm_andnot_ps(x,y); } 49 | RETf OR( const __m128 x, const __m128 y ) { return _mm_or_ps(x,y); } 50 | RETf XOR( const __m128 x, const __m128 y ) { return _mm_xor_ps(x,y); } 51 | 52 | // comparison operators 53 | RETf CMPGT( const __m128 x, const __m128 y ) { return _mm_cmpgt_ps(x,y); } 54 | RETf CMPLT( const __m128 x, const __m128 y ) { return _mm_cmplt_ps(x,y); } 55 | RETi CMPGT( const __m128i x, const __m128i y ) { return _mm_cmpgt_epi32(x,y); } 56 | RETi CMPLT( const __m128i x, const __m128i y ) { return _mm_cmplt_epi32(x,y); } 57 | 58 | // conversion operators 59 | RETf CVT( const __m128i x ) { return _mm_cvtepi32_ps(x); } 60 | RETi CVT( const __m128 x ) { return _mm_cvttps_epi32(x); } 61 | 62 | #undef RETf 63 | #undef RETi 64 | 65 | } 66 | #endif 67 | -------------------------------------------------------------------------------- /cascade_staple/src/staple_tracker.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STAPLE_TRACKER_HPP 2 | #define STAPLE_TRACKER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define _PI 3.141592653589793 16 | #define _2PI 6.283185307179586 17 | 18 | struct staple_cfg 19 | { 20 | bool grayscale_sequence = false; // suppose that sequence is colour 21 | int hog_cell_size = 4; 22 | int fixed_area = 150*150; // standard area to which we resize the target 23 | int n_bins = 2*2*2*2*2; // number of bins for the color histograms (bg and fg models) 24 | double learning_rate_pwp = 0.04; // bg and fg color models learning rate 25 | const char * feature_type = "fhog"; // "fhog", ""gray"" 26 | double inner_padding = 0.2; // defines inner area used to sample colors from the foreground 27 | double output_sigma_factor = 1/16.0; // standard deviation for the desired translation filter output 28 | double lambda = 1e-3; // egularization weight 29 | double learning_rate_cf = 0.01; // HOG model learning rate 30 | double merge_factor = 0.3; // fixed interpolation factor - how to linearly combine the two responses 31 | const char * merge_method = "const_factor"; 32 | bool den_per_channel = false; 33 | 34 | // scale related 35 | bool scale_adaptation = true; 36 | int hog_scale_cell_size = 4; // Default DSST=4 37 | double learning_rate_scale = 0.025; 38 | double scale_sigma_factor = 1/4.0; 39 | int num_scales = 33; 40 | double scale_model_factor = 1.0; 41 | double scale_step = 1.02; 42 | double scale_model_max_area = 32*16; 43 | 44 | // debugging stuff 45 | int visualization = 0; // show output bbox on frame 46 | int visualization_dbg = 0; // show also per-pixel scores, desired response and filter output 47 | 48 | cv::Point_ init_pos; 49 | cv::Size target_sz; 50 | }; 51 | 52 | class STAPLE_TRACKER 53 | { 54 | public: 55 | STAPLE_TRACKER(){ cfg = default_parameters_staple(cfg); frameno = 0; }; 56 | ~STAPLE_TRACKER(){} 57 | 58 | void mexResize(const cv::Mat &im, cv::Mat &output, cv::Size newsz, const char *method); 59 | void tracker_staple_train(const cv::Mat &im, bool first); 60 | void tracker_staple_initialize(const cv::Mat &im, cv::Rect_ region); 61 | cv::Rect tracker_staple_update(const cv::Mat &im); 62 | 63 | protected: 64 | staple_cfg default_parameters_staple(staple_cfg cfg); 65 | void initializeAllAreas(const cv::Mat &im); 66 | 67 | void getSubwindow(const cv::Mat &im, cv::Point_ centerCoor, cv::Size model_sz, cv::Size scaled_sz, cv::Mat &output); 68 | void getSubwindowFloor(const cv::Mat &im, cv::Point_ centerCoor, cv::Size model_sz, cv::Size scaled_sz, cv::Mat &output); 69 | void updateHistModel(bool new_model, cv::Mat &patch, double learning_rate_pwp=0.0); 70 | void CalculateHann(cv::Size sz, cv::Mat &output); 71 | void gaussianResponse(cv::Size rect_size, double sigma, cv::Mat &output); 72 | void getFeatureMap(cv::Mat &im_patch, const char *feature_type, cv::MatND &output); 73 | void cropFilterResponse(const cv::Mat &response_cf, cv::Size response_size, cv::Mat& output); 74 | void getColourMap(const cv::Mat &patch, cv::Mat& output); 75 | void getCenterLikelihood(const cv::Mat &object_likelihood, cv::Size m, cv::Mat& center_likelihood); 76 | void mergeResponses(const cv::Mat &response_cf, const cv::Mat &response_pwp, cv::Mat &response); 77 | void getScaleSubwindow(const cv::Mat &im, cv::Point_ centerCoor, cv::Mat &output); 78 | 79 | private: 80 | staple_cfg cfg; 81 | 82 | cv::Point_ pos; 83 | cv::Size target_sz; 84 | 85 | cv::Size bg_area; 86 | cv::Size fg_area; 87 | double area_resize_factor; 88 | cv::Size cf_response_size; 89 | 90 | cv::Size norm_bg_area; 91 | cv::Size norm_target_sz; 92 | cv::Size norm_delta_area; 93 | cv::Size norm_pwp_search_area; 94 | 95 | cv::Mat im_patch_pwp; 96 | 97 | cv::MatND bg_hist; 98 | cv::MatND fg_hist; 99 | 100 | cv::Mat hann_window; 101 | cv::Mat yf; 102 | 103 | std::vector hf_den; 104 | std::vector hf_num; 105 | 106 | cv::Rect rect_position; 107 | 108 | float scale_factor; 109 | cv::Mat scale_window; 110 | cv::Mat scale_factors; 111 | cv::Size scale_model_sz; 112 | float min_scale_factor; 113 | float max_scale_factor; 114 | cv::Size base_target_sz; 115 | 116 | cv::Mat ysf; 117 | cv::Mat sf_den; 118 | cv::Mat sf_num; 119 | 120 | int frameno; 121 | }; 122 | 123 | #endif -------------------------------------------------------------------------------- /color_detect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(fuck) 4 | 5 | SET(CMAKE_C_COMPILER g++) 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | add_compile_options(-std=c++11) 8 | message(STATUS "optional:-std=c++11") 9 | endif(CMAKE_COMPILER_IS_GNUCXX) 10 | 11 | find_package(OpenCV REQUIRED) 12 | 13 | message(STATUS "OpenCV library status:") 14 | message(STATUS " version: ${OpenCV_VERSION}") 15 | message(STATUS " libraries: ${OpenCV_LIBS}") 16 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 17 | 18 | if(CMAKE_VERSION VERSION_LESS "2.8.11") 19 | include_directories(${OpenCV_INCLUDE_DIRS}) 20 | endif() 21 | 22 | 23 | file(GLOB SRCS ./*.cpp) 24 | file(GLOB HDRS ./*.h*) 25 | 26 | set(traincascade_files ${SRCS} ${HDRS}) 27 | 28 | add_executable(fuck ${traincascade_files}) 29 | 30 | target_link_libraries(fuck ${OpenCV_LIBS}) 31 | -------------------------------------------------------------------------------- /color_detect/ColorDetect.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/color_detect/ColorDetect.h -------------------------------------------------------------------------------- /color_detect/fuck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/color_detect/fuck -------------------------------------------------------------------------------- /color_detect/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/color_detect/main.cpp -------------------------------------------------------------------------------- /serial_linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(fuck) 4 | 5 | SET(CMAKE_C_COMPILER g++) 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | add_compile_options(-std=c++11) 8 | message(STATUS "optional:-std=c++11") 9 | endif(CMAKE_COMPILER_IS_GNUCXX) 10 | 11 | find_package(OpenCV REQUIRED) 12 | 13 | message(STATUS "OpenCV library status:") 14 | message(STATUS " version: ${OpenCV_VERSION}") 15 | message(STATUS " libraries: ${OpenCV_LIBS}") 16 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 17 | 18 | if(CMAKE_VERSION VERSION_LESS "2.8.11") 19 | include_directories(${OpenCV_INCLUDE_DIRS}) 20 | endif() 21 | 22 | 23 | file(GLOB SRCS ./src/*.cpp) 24 | file(GLOB HDRS ./src/*.h*) 25 | 26 | set(traincascade_files ${SRCS} ${HDRS}) 27 | 28 | add_executable(fuck ${traincascade_files}) 29 | 30 | target_link_libraries(fuck ${OpenCV_LIBS}) 31 | -------------------------------------------------------------------------------- /serial_linux/build/fuck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/serial_linux/build/fuck -------------------------------------------------------------------------------- /serial_linux/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "serial.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | 7 | int main(int argc, char * argv[]) 8 | { 9 | string dev = "/dev/ttyUSB0"; 10 | Serial sel((char *)dev.data()); 11 | sel.setPara(); 12 | 13 | string buff = "Hello!"; 14 | sel.writeData(buff.data(), buff.length()); 15 | 16 | char buff2[64]; 17 | sel.readData(buff2); 18 | 19 | return 0; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /serial_linux/src/serial.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by michael on 17-12-15. 3 | // 4 | 5 | #include "serial.h" 6 | 7 | /** 8 | * @brief 构造函数,初始化文件句柄 9 | * @param dev 类型 char* 串口号 10 | */ 11 | Serial::Serial(char *dev) 12 | { 13 | fd = open( dev, O_RDWR | O_NOCTTY ); //| O_NOCTTY | O_NDELAY 14 | if (-1 == fd) 15 | { 16 | perror("Can't Open Serial Port"); 17 | exit(0); 18 | } 19 | } 20 | 21 | Serial::~Serial() 22 | { 23 | close(fd); 24 | } 25 | 26 | /** 27 | * @brief 延迟 28 | * @param sec 类型 int 延迟秒数 29 | * @return void 30 | */ 31 | void Serial::delay(int sec) 32 | { 33 | time_t start_time, cur_time; 34 | time(&start_time); 35 | do{ 36 | time(&cur_time); 37 | }while((cur_time - start_time) < sec); 38 | } 39 | 40 | /** 41 | * @brief 设置串口通信速率,数据位,停止位和效验位 42 | * @param speed 类型 int 串口速度 43 | * @param databits 类型 int 数据位 取值为 7 或者8 44 | * @oaran stopbits 类型 int 停止位 取值为 1 或者2 45 | * @param parity 类型 int 效验类型 取值为N,E,O,S 46 | * @return bool 47 | */ 48 | bool Serial::setPara(int speed, int databits, int stopbits, int parity) 49 | { 50 | int i; 51 | int status; 52 | struct termios Opt; 53 | tcgetattr(fd, &Opt); 54 | for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) 55 | { 56 | if (speed == name_arr[i]) 57 | { 58 | tcflush(fd, TCIOFLUSH); 59 | cfsetispeed(&Opt, speed_arr[i]); 60 | cfsetospeed(&Opt, speed_arr[i]); 61 | status = tcsetattr(fd, TCSANOW, &Opt); 62 | if (status != 0) 63 | { 64 | perror("tcsetattr fd1"); 65 | return false; 66 | } 67 | tcflush(fd,TCIOFLUSH); 68 | } 69 | } 70 | 71 | struct termios options; 72 | options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ 73 | options.c_oflag &= ~OPOST; /*Output*/ 74 | if ( tcgetattr( fd,&options) != 0) 75 | { 76 | perror("SetupSerial 1"); 77 | return false; 78 | } 79 | options.c_cflag &= ~CSIZE; 80 | switch (databits) /*设置数据位数*/ 81 | { 82 | case 7: 83 | options.c_cflag |= CS7; 84 | break; 85 | case 8: 86 | options.c_cflag |= CS8; 87 | break; 88 | default: 89 | fprintf(stderr,"Unsupported data size/n"); return false; 90 | } 91 | switch (parity) 92 | { 93 | case 'n': 94 | case 'N': 95 | options.c_cflag &= ~PARENB; /* Clear parity enable */ 96 | options.c_iflag &= ~INPCK; /* Enable parity checking */ 97 | break; 98 | case 'o': 99 | case 'O': 100 | options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ 101 | options.c_iflag |= INPCK; /* Disnable parity checking */ 102 | break; 103 | case 'e': 104 | case 'E': 105 | options.c_cflag |= PARENB; /* Enable parity */ 106 | options.c_cflag &= ~PARODD; /* 转换为偶效验*/ 107 | options.c_iflag |= INPCK; /* Disnable parity checking */ 108 | break; 109 | case 'S': 110 | case 's': /*as no parity*/ 111 | options.c_cflag &= ~PARENB; 112 | options.c_cflag &= ~CSTOPB;break; 113 | default: 114 | fprintf(stderr,"Unsupported parity/n"); 115 | return false; 116 | } 117 | /* 设置停止位*/ 118 | switch (stopbits) 119 | { 120 | case 1: 121 | options.c_cflag &= ~CSTOPB; 122 | break; 123 | case 2: 124 | options.c_cflag |= CSTOPB; 125 | break; 126 | default: 127 | fprintf(stderr,"Unsupported stop bits/n"); 128 | return false; 129 | } 130 | /* Set input parity option */ 131 | if (parity != 'n') 132 | options.c_iflag |= INPCK; 133 | tcflush(fd,TCIFLUSH); 134 | options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/ 135 | options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ 136 | if (tcsetattr(fd,TCSANOW,&options) != 0) 137 | { 138 | perror("SetupSerial 3"); 139 | return false; 140 | } 141 | return true; 142 | } 143 | 144 | /** 145 | * @brief 设置串口通信速率/波特率 146 | * @param speed 类型 int 串口速度/波特率 147 | * @return bool 148 | */ 149 | bool Serial::setBaudRate(int speed) 150 | { 151 | int i; 152 | int status; 153 | struct termios Opt; 154 | tcgetattr(fd, &Opt); 155 | for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) 156 | { 157 | if (speed == name_arr[i]) 158 | { 159 | tcflush(fd, TCIOFLUSH); 160 | cfsetispeed(&Opt, speed_arr[i]); 161 | cfsetospeed(&Opt, speed_arr[i]); 162 | status = tcsetattr(fd, TCSANOW, &Opt); 163 | if (status != 0) 164 | { 165 | perror("tcsetattr fd1"); 166 | return false; 167 | } 168 | tcflush(fd,TCIOFLUSH); 169 | } 170 | } 171 | return true; 172 | } 173 | 174 | /** 175 | * @brief 写数据 176 | * @param data 类型 const char * 字符串 177 | * @param datalength 类型 int 字符串长度 178 | * @return int 写入字符串的长度 179 | */ 180 | int Serial::writeData(const char *data, int datalength) 181 | { 182 | int nwrite; 183 | nwrite = write(fd, data, datalength); 184 | return nwrite; 185 | } 186 | 187 | /** 188 | * @brief 读数据 189 | * @param data 类型 char * 字符串 190 | * @param datalength 类型 int 字符串长度 191 | * @return int 读出字符串的长度 192 | */ 193 | int Serial::readData(char *data, int datalength) 194 | { 195 | int nread; 196 | nread = read(fd, data, 5); 197 | data[nread] = '\0'; 198 | return nread; 199 | } -------------------------------------------------------------------------------- /serial_linux/src/serial.h: -------------------------------------------------------------------------------- 1 | #ifndef SERIAL_H 2 | #define SERIAL_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | class Serial 17 | { 18 | public: 19 | Serial(char *dev); 20 | ~Serial(); 21 | void delay(int sec); 22 | bool setPara(int speed = 9600, int databits = 8, int stopbits = 1, int parity = 'N'); 23 | bool setBaudRate(int speed); 24 | int writeData(const char *data, int datalength); 25 | int readData(char *data, int datalength = 64); 26 | 27 | private: 28 | int fd; 29 | int speed_arr[14] = { B115200, B19200, B9600, B4800, B2400, B1200, B300, 30 | B115200, B19200, B9600, B4800, B2400, B1200, B300, }; 31 | int name_arr[14] = {115200, 19200, 9600, 4800, 2400, 1200, 300, 115200, 32 | 19200, 9600, 4800, 2400, 1200, 300, }; 33 | }; 34 | 35 | #endif -------------------------------------------------------------------------------- /serial_windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(fuck) 4 | 5 | SET(CMAKE_C_COMPILER g++) 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | add_compile_options(-std=c++11) 8 | message(STATUS "optional:-std=c++11") 9 | endif(CMAKE_COMPILER_IS_GNUCXX) 10 | 11 | find_package(OpenCV REQUIRED) 12 | 13 | message(STATUS "OpenCV library status:") 14 | message(STATUS " version: ${OpenCV_VERSION}") 15 | message(STATUS " libraries: ${OpenCV_LIBS}") 16 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 17 | 18 | if(CMAKE_VERSION VERSION_LESS "2.8.11") 19 | include_directories(${OpenCV_INCLUDE_DIRS}) 20 | endif() 21 | 22 | 23 | file(GLOB SRCS ./src/*.cpp) 24 | file(GLOB HDRS ./src/*.h*) 25 | 26 | set(traincascade_files ${SRCS} ${HDRS}) 27 | 28 | add_executable(fuck ${traincascade_files}) 29 | 30 | target_link_libraries(fuck ${OpenCV_LIBS}) 31 | -------------------------------------------------------------------------------- /serial_windows/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "serial.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | 7 | int main(int argc, char * argv[]) 8 | { 9 | string dev = "/dev/ttyUSB0"; 10 | CSerial serial; 11 | serial.OpenSerialPort(_T("COM6"),115200,8,1); 12 | 13 | string buff = "Hello!"; 14 | serial.SendData(buff.data(), buff.length()); 15 | 16 | 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /serial_windows/src/serial.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/serial_windows/src/serial.cpp -------------------------------------------------------------------------------- /serial_windows/src/serial.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/serial_windows/src/serial.h -------------------------------------------------------------------------------- /track_TM/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(TM_track) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | set(SOURCE_FILES main.cpp template.h) 7 | 8 | find_package(OpenCV REQUIRED) 9 | add_executable(TM_track ${SOURCE_FILES}) 10 | target_link_libraries(TM_track ${OpenCV_LIBS}) 11 | -------------------------------------------------------------------------------- /track_TM/build/TM_track: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/track_TM/build/TM_track -------------------------------------------------------------------------------- /track_TM/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "template.h" 3 | #include 4 | using namespace std; 5 | using namespace cv; 6 | 7 | Rect box; 8 | bool drawingBox = false; 9 | bool gotBB = false; 10 | 11 | void onMouse(int event, int x, int y, int flags, void *param) 12 | { 13 | switch(event) 14 | { 15 | case CV_EVENT_MOUSEMOVE: 16 | if (drawingBox) 17 | { 18 | box.width = x - box.x; 19 | box.height = y - box.y; 20 | } 21 | break; 22 | case CV_EVENT_LBUTTONDOWN: 23 | drawingBox = true; 24 | box = Rect(x, y, 0, 0); 25 | break; 26 | case CV_EVENT_LBUTTONUP: 27 | drawingBox = false; 28 | if(box.width < 0) 29 | { 30 | box.x +=box.width; 31 | box.width *= -1; 32 | } 33 | if(box.height < 0) 34 | { 35 | box.y += box.height; 36 | box.height *= -1; 37 | } 38 | gotBB = true; 39 | break; 40 | } 41 | } 42 | 43 | int main(int argc, char * argv[]) 44 | { 45 | Template tracker; 46 | //cout << "C++11 : " << to_string(2333) << endl; 47 | VideoCapture capture; 48 | capture.open(0); 49 | 50 | if(!capture.isOpened()) 51 | { 52 | cout << "capture device failed to open!" << endl; 53 | return -1; 54 | } 55 | cvNamedWindow("Tracker", CV_WINDOW_AUTOSIZE); 56 | cvSetMouseCallback("Tracker", onMouse, NULL); 57 | 58 | Mat frame; 59 | capture >> frame; 60 | while (!gotBB) 61 | { 62 | capture >> frame; 63 | 64 | imshow("Tracker", frame); 65 | if (cvWaitKey(300) == 'q') 66 | return 1; 67 | } 68 | cvSetMouseCallback("Tracker", NULL, NULL); 69 | 70 | tracker.initTracking(frame, box, 10); 71 | 72 | TickMeter t; 73 | int frameCount = 0; 74 | 75 | while (1) 76 | { 77 | capture >> frame; 78 | if (frame.empty()) 79 | return -1; 80 | frameCount++; 81 | 82 | t.start(); 83 | // tracking 84 | box = tracker.track(frame); 85 | 86 | // show 87 | stringstream buf; 88 | buf << frameCount; 89 | string num = buf.str(); 90 | putText(frame, num, Point(20, 20), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 255), 3); 91 | rectangle(frame, box, Scalar(0, 0, 255), 3); 92 | 93 | t.stop(); 94 | imshow("Tracker", frame); 95 | char c = waitKey(10); 96 | if (c == 27) 97 | break; 98 | } 99 | 100 | double fps = t.getCounter() / t.getTimeSec(); 101 | cout << "Average fps: " << fps << endl; 102 | 103 | return 0; 104 | } -------------------------------------------------------------------------------- /track_TM/template.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | using namespace cv; 5 | 6 | class Template{ 7 | public: 8 | Template(); 9 | void initTracking(Mat frame, Rect box, int scale = 5); 10 | Rect track(Mat frame); 11 | Rect getLocation(); 12 | private: 13 | Mat model; 14 | Rect location; 15 | int scale; 16 | }; 17 | 18 | Template::Template() 19 | { 20 | this->scale = 5; 21 | } 22 | 23 | void Template::initTracking(Mat frame, Rect box, int scale) 24 | { 25 | this->location = box; 26 | this->scale = scale; 27 | 28 | if(frame.empty()) 29 | { 30 | cout << "ERROR: frame is empty." << endl; 31 | exit(0); 32 | } 33 | if(frame.channels() != 1) 34 | { 35 | cvtColor(frame, frame, CV_RGB2GRAY); 36 | } 37 | this->model = frame(box); 38 | } 39 | 40 | Rect Template::track(Mat frame) 41 | { 42 | if(frame.empty()) 43 | { 44 | cout << "ERROR: frame is empty." << endl; 45 | exit(0); 46 | } 47 | Mat gray; 48 | if(frame.channels() != 1) 49 | { 50 | cvtColor(frame, gray, CV_RGB2GRAY); 51 | } 52 | 53 | Rect searchWindow; 54 | searchWindow.width = this->location.width * scale; 55 | searchWindow.height = this->location.height * scale; 56 | searchWindow.x = this->location.x + this->location.width * 0.5 57 | - searchWindow.width * 0.5; 58 | searchWindow.y = this->location.y + this->location.height * 0.5 59 | - searchWindow.height * 0.5; 60 | searchWindow &= Rect(0, 0, frame.cols, frame.rows); 61 | 62 | Mat similarity; 63 | matchTemplate(gray(searchWindow), this->model, similarity, CV_TM_CCOEFF_NORMED); 64 | double mag_r; 65 | Point point; 66 | minMaxLoc(similarity, 0, &mag_r, 0, &point); 67 | this->location.x = point.x + searchWindow.x; 68 | this->location.y = point.y + searchWindow.y; 69 | 70 | this->model = gray(location); 71 | return this->location; 72 | } 73 | 74 | Rect Template::getLocation() 75 | { 76 | return this->location; 77 | } -------------------------------------------------------------------------------- /track_opencv/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(tracker) 3 | aux_source_directory(./src/ SRC_LIST) 4 | add_executable(${PROJECT_NAME} ${SRC_LIST}) 5 | 6 | IF (UNIX) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3") #c++11 8 | ENDIF (UNIX) 9 | find_package(OpenCV REQUIRED) 10 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 11 | -------------------------------------------------------------------------------- /track_opencv/build/tracker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/track_opencv/build/tracker -------------------------------------------------------------------------------- /track_opencv/src/tracker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | using namespace cv; 7 | using namespace std; 8 | 9 | // Convert to string 10 | #define SSTR( x ) static_cast< std::ostringstream & >( \ 11 | ( std::ostringstream() << std::dec << x ) ).str() 12 | 13 | 14 | int main(int argc, char **argv) 15 | { 16 | // List of tracker types in OpenCV 3.2 17 | // NOTE : GOTURN implementation is buggy and does not work. 18 | string trackerTypes[7] = {"BOOSTING", "MIL", "KCF", "TLD","MEDIANFLOW", "GOTURN", "CSRT"}; 19 | // vector trackerTypes(types, std::end(types)); 20 | 21 | // Create a tracker 22 | string trackerType = trackerTypes[2]; 23 | 24 | Ptr tracker; 25 | 26 | #if (CV_MINOR_VERSION < 3) 27 | { 28 | tracker = Tracker::create(trackerType); 29 | } 30 | #else 31 | { 32 | if (trackerType == "BOOSTING") 33 | tracker = TrackerBoosting::create(); 34 | if (trackerType == "MIL") 35 | tracker = TrackerMIL::create(); 36 | if (trackerType == "KCF") 37 | tracker = TrackerKCF::create(); 38 | if (trackerType == "TLD") 39 | tracker = TrackerTLD::create(); 40 | if (trackerType == "MEDIANFLOW") 41 | tracker = TrackerMedianFlow::create(); 42 | if (trackerType == "GOTURN") 43 | tracker = TrackerGOTURN::create(); 44 | if (trackerType == "CSRT") 45 | tracker = TrackerCSRT::create(); 46 | } 47 | #endif 48 | // Read video 49 | VideoCapture video( 0 ); 50 | 51 | // Exit if video is not opened 52 | if(!video.isOpened()) 53 | { 54 | cout << "Could not read video file" << endl; 55 | return 1; 56 | 57 | } 58 | 59 | // Read first frame 60 | Mat frame; 61 | bool ok = video.read(frame); 62 | ok = video.read(frame); 63 | ok = video.read(frame); 64 | ok = video.read(frame); 65 | ok = video.read(frame); 66 | ok = video.read(frame); 67 | ok = video.read(frame); 68 | ok = video.read(frame); 69 | ok = video.read(frame); 70 | 71 | // Define initial boundibg box 72 | Rect2d bbox(287, 23, 86, 320); 73 | 74 | // Uncomment the line below to select a different bounding box 75 | bbox = selectROI(frame, false); 76 | 77 | // Display bounding box. 78 | rectangle(frame, bbox, Scalar( 255, 0, 0 ), 2, 1 ); 79 | imshow("Tracking", frame); 80 | 81 | tracker->init(frame, bbox); 82 | 83 | while(video.read(frame)) 84 | { 85 | // Start timer 86 | double timer = (double)getTickCount(); 87 | 88 | // Update the tracking result 89 | bool ok = tracker->update(frame, bbox); 90 | 91 | // Calculate Frames per second (FPS) 92 | float fps = getTickFrequency() / ((double)getTickCount() - timer); 93 | 94 | 95 | if (ok) 96 | { 97 | // Tracking success : Draw the tracked object 98 | rectangle(frame, bbox, Scalar( 255, 0, 0 ), 2, 1 ); 99 | } 100 | else 101 | { 102 | // Tracking failure detected. 103 | putText(frame, "Tracking failure detected", Point(100,80), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,255),2); 104 | } 105 | 106 | // Display tracker type on frame 107 | putText(frame, trackerType + " Tracker", Point(100,20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(50,170,50),2); 108 | 109 | // Display FPS on frame 110 | putText(frame, "FPS : " + SSTR(int(fps)), Point(100,50), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(50,170,50), 2); 111 | 112 | // Display frame. 113 | imshow("Tracking", frame); 114 | 115 | // Exit if ESC pressed. 116 | int k = waitKey(1); 117 | if(k == 27) 118 | { 119 | break; 120 | } 121 | 122 | } 123 | 124 | 125 | 126 | } -------------------------------------------------------------------------------- /track_staple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(stapleCC) 3 | aux_source_directory(./src/ SRC_LIST) 4 | add_executable(${PROJECT_NAME} ${SRC_LIST}) 5 | 6 | IF (UNIX) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3") #c++11 8 | ENDIF (UNIX) 9 | find_package(OpenCV REQUIRED) 10 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 11 | -------------------------------------------------------------------------------- /track_staple/build/stapleCC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/track_staple/build/stapleCC -------------------------------------------------------------------------------- /track_staple/src/fhog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | #include "fhog.h" 7 | #undef MIN 8 | 9 | // platform independent aligned memory allocation (see also alFree) 10 | void* alMalloc( size_t size, int alignment ) { 11 | const size_t pSize = sizeof(void*), a = alignment-1; 12 | void *raw = wrMalloc(size + a + pSize); 13 | void *aligned = (void*) (((size_t) raw + pSize + a) & ~a); 14 | *(void**) ((size_t) aligned-pSize) = raw; 15 | return aligned; 16 | } 17 | 18 | // platform independent alignned memory de-allocation (see also alMalloc) 19 | void alFree(void* aligned) { 20 | void* raw = *(void**)((char*)aligned-sizeof(void*)); 21 | wrFree(raw); 22 | } 23 | 24 | /******************************************************************************* 25 | * Piotr's Computer Vision Matlab Toolbox Version 3.30 26 | * Copyright 2014 Piotr Dollar & Ron Appel. [pdollar-at-gmail.com] 27 | * Licensed under the Simplified BSD License [see external/bsd.txt] 28 | *******************************************************************************/ 29 | // #include "wrappers.hpp" 30 | 31 | #define PI 3.14159265f 32 | 33 | // compute x and y gradients for just one column (uses sse) 34 | void grad1( float *I, float *Gx, float *Gy, int h, int w, int x ) { 35 | int y, y1; float *Ip, *In, r; __m128 *_Ip, *_In, *_G, _r; 36 | // compute column of Gx 37 | Ip=I-h; In=I+h; r=.5f; 38 | if(x==0) { r=1; Ip+=h; } else if(x==w-1) { r=1; In-=h; } 39 | if( h<4 || h%4>0 || (size_t(I)&15) || (size_t(Gx)&15) ) { 40 | for( y=0; yh-1) y1=h-1; 50 | GRADY(1); Ip--; for(y=1; y PI-1e-6f ) a1[i]=PI-1e-6f; 74 | init=true; return a1; 75 | } 76 | 77 | // compute gradient magnitude and orientation at each location (uses sse) 78 | void gradMag( float *I, float *M, float *O, int h, int w, int d, bool full ) { 79 | int x, y, y1, c, h4, s; float *Gx, *Gy, *M2; __m128 *_Gx, *_Gy, *_M2, _m; 80 | float *acost = acosTable(), acMult=10000.0f; 81 | // allocate memory for storing one column of output (padded so h4%4==0) 82 | h4=(h%4==0) ? h : h-(h%4)+4; s=d*h4*sizeof(float); 83 | M2=(float*) alMalloc(s,16); _M2=(__m128*) M2; 84 | Gx=(float*) alMalloc(s,16); _Gx=(__m128*) Gx; 85 | Gy=(float*) alMalloc(s,16); _Gy=(__m128*) Gy; 86 | // compute gradient magnitude and orientation for each column 87 | for( x=0; x=oMax) o0=0; O0[i]=o0; 157 | o1=o0+nb; if(o1==oMax) o1=0; O1[i]=o1; 158 | m=M[i]*norm; M1[i]=od*m; M0[i]=m-M1[i]; 159 | } else for(; i=oMax) o0=0; O0[i]=o0; 162 | M0[i]=M[i]*norm; M1[i]=0; O1[i]=0; 163 | } 164 | } 165 | 166 | // compute nOrients gradient histograms per bin x bin block of pixels 167 | void gradHist( float *M, float *O, float *H, int h, int w, 168 | int bin, int nOrients, int softBin, bool full ) 169 | { 170 | const int hb=h/bin, wb=w/bin, h0=hb*bin, w0=wb*bin, nb=wb*hb; 171 | const float s=(float)bin, sInv=1/s, sInv2=1/s/s; 172 | float *H0, *H1, *M0, *M1; int x, y; int *O0, *O1; float xb, init; 173 | O0=(int*)alMalloc(h*sizeof(int),16); M0=(float*) alMalloc(h*sizeof(float),16); 174 | O1=(int*)alMalloc(h*sizeof(int),16); M1=(float*) alMalloc(h*sizeof(float),16); 175 | // main loop 176 | for( x=0; x=0); 179 | 180 | if( softBin<0 && softBin%2==0 ) { 181 | // no interpolation w.r.t. either orienation or spatial bin 182 | H1=H+(x/bin)*hb; 183 | #define GH H1[O0[y]]+=M0[y]; y++; 184 | if( bin==1 ) for(y=0; y=0; xb0 = hasLf?(int)xb:-1; hasRt = xb0 < wb-1; 208 | xd=xb-xb0; xb+=sInv; yb=init; y=0; 209 | // macros for code conciseness 210 | #define GHinit yd=yb-yb0; yb+=sInv; H0=H+xb0*hb+yb0; xyd=xd*yd; \ 211 | ms[0]=1-xd-yd+xyd; ms[1]=yd-xyd; ms[2]=xd-xyd; ms[3]=xyd; 212 | #define GH(H,ma,mb) H1=H; sse::STRu(*H1,sse::ADD(sse::LDu(*H1),sse::MUL(ma,mb))); 213 | // leading rows, no top bin 214 | for( ; y=hb-1) break; GHinit; _m0=sse::SET(M0[y]); 222 | if(hasLf) { _m=sse::SET(0,0,ms[1],ms[0]); GH(H0+O0[y],_m,_m0); } 223 | if(hasRt) { _m=sse::SET(0,0,ms[3],ms[2]); GH(H0+O0[y]+hb,_m,_m0); } 224 | } else for( ; ; y++ ) { 225 | yb0 = (int) yb; if(yb0>=hb-1) break; GHinit; 226 | _m0=sse::SET(M0[y]); _m1=sse::SET(M1[y]); 227 | if(hasLf) { _m=sse::SET(0,0,ms[1],ms[0]); 228 | GH(H0+O0[y],_m,_m0); GH(H0+O1[y],_m,_m1); } 229 | if(hasRt) { _m=sse::SET(0,0,ms[3],ms[2]); 230 | GH(H0+O0[y]+hb,_m,_m0); GH(H0+O1[y]+hb,_m,_m1); } 231 | } 232 | // final rows, no bottom bin 233 | for( ; yclip) t=clip; c++; 279 | const float r=.2357f; int o, x, y, c; float t; 280 | const int nb=wb*hb, nbo=nOrients*nb, hb1=hb+1; 281 | for( o=0; onl1 ) mexErrMsgTxt("Incorrect number of outputs."); 359 | if( nrnr1 ) mexErrMsgTxt("Incorrect number of inputs."); 360 | nDims = mxGetNumberOfDimensions(pr[0]); dims = mxGetDimensions(pr[0]); 361 | *h=dims[0]; *w=dims[1]; *d=(nDims==2) ? 1 : dims[2]; *I = mxGetPr(pr[0]); 362 | if( nDims!=2 && nDims!=3 ) mexErrMsgTxt("I must be a 2D or 3D array."); 363 | if( mxGetClassID(pr[0])!=id ) mexErrMsgTxt("I has incorrect type."); 364 | } 365 | 366 | // [Gx,Gy] = grad2(I) - see gradient2.m 367 | void mGrad2( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 368 | int h, w, d; float *I, *Gx, *Gy; 369 | checkArgs(nl,pl,nr,pr,1,2,1,1,&h,&w,&d,mxSINGLE_CLASS,(void**)&I); 370 | if(h<2 || w<2) mexErrMsgTxt("I must be at least 2x2."); 371 | pl[0]= mxCreateMatrix3( h, w, d, mxSINGLE_CLASS, 0, (void**) &Gx ); 372 | pl[1]= mxCreateMatrix3( h, w, d, mxSINGLE_CLASS, 0, (void**) &Gy ); 373 | grad2( I, Gx, Gy, h, w, d ); 374 | } 375 | 376 | // [M,O] = gradMag( I, channel, full ) - see gradientMag.m 377 | void mGradMag( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 378 | int h, w, d, c, full; float *I, *M, *O=0; 379 | checkArgs(nl,pl,nr,pr,1,2,3,3,&h,&w,&d,mxSINGLE_CLASS,(void**)&I); 380 | if(h<2 || w<2) mexErrMsgTxt("I must be at least 2x2."); 381 | c = (int) mxGetScalar(pr[1]); full = (int) mxGetScalar(pr[2]); 382 | if( c>0 && c<=d ) { I += h*w*(c-1); d=1; } 383 | pl[0] = mxCreateMatrix3(h,w,1,mxSINGLE_CLASS,0,(void**)&M); 384 | if(nl>=2) pl[1] = mxCreateMatrix3(h,w,1,mxSINGLE_CLASS,0,(void**)&O); 385 | gradMag(I, M, O, h, w, d, full>0 ); 386 | } 387 | 388 | // gradMagNorm( M, S, norm ) - operates on M - see gradientMag.m 389 | void mGradMagNorm( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 390 | int h, w, d; float *M, *S, norm; 391 | checkArgs(nl,pl,nr,pr,0,0,3,3,&h,&w,&d,mxSINGLE_CLASS,(void**)&M); 392 | if( mxGetM(pr[1])!=h || mxGetN(pr[1])!=w || d!=1 || 393 | mxGetClassID(pr[1])!=mxSINGLE_CLASS ) mexErrMsgTxt("M or S is bad."); 394 | S = (float*) mxGetPr(pr[1]); norm = (float) mxGetScalar(pr[2]); 395 | gradMagNorm(M,S,h,w,norm); 396 | } 397 | 398 | // H=gradHist(M,O,[...]) - see gradientHist.m 399 | void mGradHist( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 400 | int h, w, d, hb, wb, nChns, binSize, nOrients, softBin, useHog; 401 | bool full; float *M, *O, *H, clipHog; 402 | checkArgs(nl,pl,nr,pr,1,3,2,8,&h,&w,&d,mxSINGLE_CLASS,(void**)&M); 403 | O = (float*) mxGetPr(pr[1]); 404 | if( mxGetM(pr[1])!=h || mxGetN(pr[1])!=w || d!=1 || 405 | mxGetClassID(pr[1])!=mxSINGLE_CLASS ) mexErrMsgTxt("M or O is bad."); 406 | binSize = (nr>=3) ? (int) mxGetScalar(pr[2]) : 8; 407 | nOrients = (nr>=4) ? (int) mxGetScalar(pr[3]) : 9; 408 | softBin = (nr>=5) ? (int) mxGetScalar(pr[4]) : 1; 409 | useHog = (nr>=6) ? (int) mxGetScalar(pr[5]) : 0; 410 | clipHog = (nr>=7) ? (float) mxGetScalar(pr[6]) : 0.2f; 411 | full = (nr>=8) ? (bool) (mxGetScalar(pr[7])>0) : false; 412 | hb = h/binSize; wb = w/binSize; 413 | nChns = useHog== 0 ? nOrients : (useHog==1 ? nOrients*4 : nOrients*3+5); 414 | pl[0] = mxCreateMatrix3(hb,wb,nChns,mxSINGLE_CLASS,1,(void**)&H); 415 | if( nOrients==0 ) return; 416 | if( useHog==0 ) { 417 | gradHist( M, O, H, h, w, binSize, nOrients, softBin, full ); 418 | } else if(useHog==1) { 419 | hog( M, O, H, h, w, binSize, nOrients, softBin, full, clipHog ); 420 | } else { 421 | fhog( M, O, H, h, w, binSize, nOrients, softBin, clipHog ); 422 | } 423 | } 424 | 425 | // inteface to various gradient functions (see corresponding Matlab functions) 426 | void mexFunction( int nl, mxArray *pl[], int nr, const mxArray *pr[] ) { 427 | int f; char action[1024]; f=mxGetString(pr[0],action,1024); nr--; pr++; 428 | if(f) mexErrMsgTxt("Failed to get action."); 429 | else if(!strcmp(action,"gradient2")) mGrad2(nl,pl,nr,pr); 430 | else if(!strcmp(action,"gradientMag")) mGradMag(nl,pl,nr,pr); 431 | else if(!strcmp(action,"gradientMagNorm")) mGradMagNorm(nl,pl,nr,pr); 432 | else if(!strcmp(action,"gradientHist")) mGradHist(nl,pl,nr,pr); 433 | else mexErrMsgTxt("Invalid action."); 434 | } 435 | #endif 436 | 437 | 438 | float* crop_H(float *H,int* h_height,int* h_width,int depth,int dh,int dw) { 439 | int crop_h = *h_height-dh-1; 440 | int crop_w = *h_width-dw-1; 441 | float* crop_H = new float[crop_h*crop_w*depth]; 442 | 443 | for(int i = 1;i < *h_height-dh;i ++) 444 | for(int j = 1;j < *h_width-dw;j ++) 445 | for(int k = 0;k < depth;k ++) 446 | crop_H[i-1 + (j-1)*(crop_h) + k*(crop_h*crop_w)] = H[k*(*h_width * *h_height) + j*(*h_height) + i]; 447 | delete H; 448 | *h_height = crop_h;*h_width = crop_w; 449 | return crop_H; 450 | } 451 | 452 | float* fhog(float *M,float* O,int height,int width,int channel,int *h,int *w,int *d,int binSize, int nOrients, float clip, bool crop) { 453 | *h = height/binSize; 454 | *w = width/binSize; 455 | *d = nOrients*3+5; 456 | 457 | float* H = new float[(*h)*(*w)*(*d)]; 458 | memset(H,0.0f,(*h)*(*w)*(*d)*sizeof(float)); 459 | 460 | fhog( M, O, H, height, width, binSize, nOrients, -1, clip ); 461 | 462 | if(!crop) 463 | return H; 464 | return crop_H(H,h,w,*d,height%binSize < binSize/2,width%binSize < binSize/2); 465 | } 466 | 467 | void fhog(cv::MatND &fhog_feature, const cv::Mat& input, int binSize, int nOrients, float clip, bool crop) { 468 | int HEIGHT = input.rows; 469 | int WIDTH = input.cols; 470 | int DEPTH = input.channels(); 471 | 472 | float *II = new float[HEIGHT*WIDTH*DEPTH]; 473 | int count=0; 474 | 475 | // MatLab:: RGB, OpenCV: BGR 476 | 477 | for (int i = 0; i < WIDTH; i++) { 478 | for (int j = 0; j < HEIGHT; j++) { 479 | cv::Vec3b p = input.at(j,i); 480 | II[count+2] = p[0]; // B->R 481 | II[count+1] = p[1]; // G->G 482 | II[count+0] = p[2]; // R->B 483 | count += 3; 484 | } 485 | } 486 | 487 | float *I = new float[HEIGHT*WIDTH*DEPTH]; 488 | 489 | // channel x width x height 490 | for (int i = 0; i < WIDTH; i++) { 491 | for (int j = 0; j < HEIGHT; j++) { 492 | for (int k = 0; k < DEPTH; k++) { 493 | I[k*WIDTH*HEIGHT+i*HEIGHT+j] = II[i*HEIGHT*DEPTH+j*DEPTH+k]; 494 | } 495 | } 496 | } 497 | 498 | float *M = new float[HEIGHT*WIDTH], *O = new float[HEIGHT*WIDTH]; 499 | gradMag(I, M, O, HEIGHT, WIDTH, DEPTH, true); 500 | 501 | int h,w,d; 502 | float* HH = fhog(M,O,HEIGHT,WIDTH,DEPTH,&h,&w,&d,binSize,nOrients,clip,crop); 503 | float* H = new float[w*h*d]; 504 | 505 | for(int i = 0;i < w; i++) 506 | for(int j = 0;j < h; j++) 507 | for(int k = 0;k < d; k++) 508 | //H[i*h*d+j*d+k] = HH[k*w*h+i*h+j]; // ->hwd 509 | H[j*w*d+i*d+k] = HH[k*w*h+i*h+j]; // ->whd 510 | 511 | fhog_feature = cv::MatND(h,w,CV_32FC(32),H).clone(); 512 | 513 | delete[] H; 514 | 515 | delete[] M; delete[] O; 516 | delete[] II;delete[] I;delete[] HH; 517 | } 518 | 519 | void fhog28(cv::MatND &fhog_feature, const cv::Mat& input, int binSize, int nOrients, float clip, bool crop) { 520 | int HEIGHT = input.rows; 521 | int WIDTH = input.cols; 522 | int DEPTH = input.channels(); 523 | 524 | float *II = new float[WIDTH*HEIGHT*DEPTH]; 525 | int count=0; 526 | 527 | // MatLab:: RGB, OpenCV: BGR 528 | 529 | for (int i = 0; i < WIDTH; i++) { 530 | for (int j = 0; j < HEIGHT; j++) { 531 | cv::Vec3b p = input.at(j,i); 532 | II[count+2] = p[0]; // B->R 533 | II[count+1] = p[1]; // G->G 534 | II[count+0] = p[2]; // R->B 535 | count += 3; 536 | } 537 | } 538 | 539 | float *I = new float[HEIGHT*WIDTH*DEPTH]; 540 | 541 | // channel x width x height 542 | for (int i = 0; i < WIDTH; i++) { 543 | for (int j = 0; j < HEIGHT; j++) { 544 | for (int k = 0; k < DEPTH; k++) { 545 | I[k*WIDTH*HEIGHT+i*HEIGHT+j] = II[i*HEIGHT*DEPTH+j*DEPTH+k]; 546 | } 547 | } 548 | } 549 | 550 | float *M = new float[HEIGHT*WIDTH], *O = new float[HEIGHT*WIDTH]; 551 | gradMag(I, M, O, HEIGHT, WIDTH, DEPTH, true); 552 | 553 | int h,w,d; 554 | float* HH = fhog(M,O,HEIGHT,WIDTH,DEPTH,&h,&w,&d,binSize,nOrients,clip,crop); 555 | 556 | #undef CHANNELS 557 | #define CHANNELS 28 558 | 559 | assert(d >= CHANNELS); 560 | 561 | // out = zeros(h, w, 28, 'single'); 562 | // out(:,:,2:28) = temp(:,:,1:27); 563 | 564 | float* H = new float[w*h*CHANNELS]; 565 | 566 | for(int i = 0;i < w; i++) 567 | for(int j = 0;j < h; j++) { 568 | //H[i*h*CHANNELS+j*CHANNELS+0] = 0.0; 569 | H[j*w*CHANNELS+i*CHANNELS+0] = 0.0; 570 | for(int k = 0;k < CHANNELS-1;k++) { 571 | //H[i*h*CHANNELS+j*CHANNELS+k+1] = HH[k*w*h+i*h+j]; // ->hwd 572 | H[j*w*CHANNELS+i*CHANNELS+k+1] = HH[k*w*h+i*h+j]; // ->whd 573 | } 574 | } 575 | 576 | fhog_feature = cv::MatND(h,w,CV_32FC(CHANNELS),H).clone(); 577 | 578 | delete[] H; 579 | 580 | delete[] M; delete[] O; 581 | delete[] II;delete[] I;delete[] HH; 582 | } 583 | 584 | void fhog31(cv::MatND &fhog_feature, const cv::Mat& input, int binSize, int nOrients, float clip, bool crop) { 585 | int HEIGHT = input.rows; 586 | int WIDTH = input.cols; 587 | int DEPTH = input.channels(); 588 | 589 | float *II = new float[WIDTH*HEIGHT*DEPTH]; 590 | int count=0; 591 | 592 | // MatLab:: RGB, OpenCV: BGR 593 | 594 | for (int i = 0; i < WIDTH; i++) { 595 | for (int j = 0; j < HEIGHT; j++) { 596 | cv::Vec3b p = input.at(j,i); 597 | II[count+2] = p[0]; // B->R 598 | II[count+1] = p[1]; // G->G 599 | II[count+0] = p[2]; // R->B 600 | count += 3; 601 | } 602 | } 603 | 604 | float *I = new float[HEIGHT*WIDTH*DEPTH]; 605 | 606 | // channel x width x height 607 | for (int i = 0; i < WIDTH; i++) { 608 | for (int j = 0; j < HEIGHT; j++) { 609 | for (int k = 0; k < DEPTH; k++) { 610 | I[k*WIDTH*HEIGHT+i*HEIGHT+j] = II[i*HEIGHT*DEPTH+j*DEPTH+k]; 611 | } 612 | } 613 | } 614 | 615 | float *M = new float[HEIGHT*WIDTH], *O = new float[HEIGHT*WIDTH]; 616 | gradMag(I, M, O, HEIGHT, WIDTH, DEPTH, true); 617 | 618 | int h,w,d; 619 | float* HH = fhog(M,O,HEIGHT,WIDTH,DEPTH,&h,&w,&d,binSize,nOrients,clip,crop); 620 | 621 | #undef CHANNELS 622 | #define CHANNELS 31 623 | 624 | assert(d >= CHANNELS); 625 | 626 | // out = zeros(h, w, 31, 'single'); 627 | // out(:,:,1:31) = temp(:,:,1:31); 628 | 629 | float* H = new float[w*h*CHANNELS]; 630 | 631 | for(int i = 0;i < w; i++) 632 | for(int j = 0;j < h; j++) { 633 | for(int k = 0;k < CHANNELS;k++) { 634 | //H[i*h*CHANNELS+j*CHANNELS+k+1] = HH[k*w*h+i*h+j]; // ->hwd 635 | H[j*w*CHANNELS+i*CHANNELS+k] = HH[k*w*h+i*h+j]; // ->whd 636 | } 637 | } 638 | 639 | fhog_feature = cv::MatND(h,w,CV_32FC(CHANNELS),H).clone(); 640 | 641 | delete[] H; 642 | 643 | delete[] M; delete[] O; 644 | delete[] II;delete[] I;delete[] HH; 645 | } 646 | -------------------------------------------------------------------------------- /track_staple/src/fhog.h: -------------------------------------------------------------------------------- 1 | #ifndef FHOG_H 2 | #define FHOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "sse.hpp" 8 | 9 | #include 10 | 11 | /** 12 | Inputs: 13 | float* I - a gray or color image matrix with shape = channel x width x height 14 | int *h, *w, *d - return the size of the returned hog features 15 | int binSize -[8] spatial bin size 16 | int nOrients -[9] number of orientation bins 17 | float clip -[.2] value at which to clip histogram bins 18 | bool crop -[false] if true crop boundaries 19 | 20 | Return: 21 | float* H - computed hog features with shape: (nOrients*3+5) x (w/binSize) x (h/binSize), if not crop 22 | 23 | Author: 24 | Sophia 25 | Date: 26 | 2015-01-15 27 | **/ 28 | 29 | float* fhog(float* I,int height,int width,int channel,int *h,int *w,int *d,int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 30 | void fhog(cv::MatND &fhog_feature, const cv::Mat& input, int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 31 | void fhog28(cv::MatND &fhog_feature, const cv::Mat& input, int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 32 | void fhog31(cv::MatND &fhog_feature, const cv::Mat& input, int binSize = 4,int nOrients = 9,float clip=0.2f,bool crop = false); 33 | 34 | // wrapper functions if compiling from C/C++ 35 | inline void wrError(const char *errormsg) { throw errormsg; } 36 | inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size); } 37 | inline void* wrMalloc( size_t size ) { return malloc(size); } 38 | inline void wrFree( void * ptr ) { free(ptr); } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /track_staple/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "staple_tracker.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | using namespace cv; 15 | 16 | bool gotBB = false; 17 | Rect box; 18 | bool drawingBox = true; 19 | 20 | void onMouse(int event, int x, int y, int flags, void *param) 21 | { 22 | switch(event) 23 | { 24 | case CV_EVENT_MOUSEMOVE: 25 | if (drawingBox) 26 | { 27 | box.width = x - box.x; 28 | box.height = y - box.y; 29 | } 30 | break; 31 | case CV_EVENT_LBUTTONDOWN: 32 | drawingBox = true; 33 | box = Rect(x, y, 0, 0); 34 | break; 35 | case CV_EVENT_LBUTTONUP: 36 | drawingBox = false; 37 | if(box.width < 0) 38 | { 39 | box.x +=box.width; 40 | box.width *= -1; 41 | } 42 | if(box.height < 0) 43 | { 44 | box.y += box.height; 45 | box.height *= -1; 46 | } 47 | gotBB = true; 48 | break; 49 | } 50 | } 51 | 52 | int main(int argc, char * argv[]) 53 | { 54 | cv::VideoCapture capture; 55 | capture.open( 0 ); 56 | if(!capture.isOpened()) 57 | { 58 | std::cout << "fail to open" << std::endl; 59 | exit(0); 60 | } 61 | //int frame_number = capture.get(CV_CAP_PROP_FRAME_COUNT); 62 | 63 | cvNamedWindow("Tracker", CV_WINDOW_AUTOSIZE); 64 | cvSetMouseCallback("Tracker", onMouse, NULL); 65 | 66 | Mat image; 67 | capture >> image; 68 | while (!gotBB) 69 | { 70 | capture >> image; 71 | 72 | imshow("Tracker", image); 73 | if (cvWaitKey(10) == 'q') 74 | return 1; 75 | } 76 | cvSetMouseCallback("Tracker", NULL, NULL); 77 | 78 | 79 | STAPLE_TRACKER staple; 80 | 81 | cv::Rect_ location; 82 | location = box; 83 | staple.tracker_staple_initialize(image, location); 84 | staple.tracker_staple_train(image, true); 85 | 86 | std::vector> result_rects; 87 | int64 tic, toc; 88 | double time = 0; 89 | bool show_visualization = true; 90 | 91 | int frame = 0; 92 | while(true) 93 | { 94 | if(!capture.read(image)) 95 | break; 96 | 97 | tic = cv::getTickCount(); 98 | location = staple.tracker_staple_update(image); 99 | staple.tracker_staple_train(image, false); 100 | toc = cv::getTickCount() - tic; 101 | time += toc; 102 | result_rects.push_back(location); 103 | 104 | if (show_visualization) { 105 | cv::putText(image, std::to_string(frame++ + 1), cv::Point(20, 40), 6, 1, 106 | cv::Scalar(0, 255, 255), 2); 107 | cv::rectangle(image, location, cv::Scalar(0, 128, 255), 2); 108 | cv::imshow("STAPLE", image); 109 | 110 | char key = cv::waitKey(10); 111 | if (key == 27 || key == 'q' || key == 'Q') 112 | break; 113 | } 114 | } 115 | 116 | time = time / double(cv::getTickFrequency()); 117 | double fps = double(result_rects.size()) / time; 118 | std::cout << "fps:" << fps << std::endl; 119 | cv::destroyAllWindows(); 120 | 121 | return 0; 122 | } 123 | 124 | -------------------------------------------------------------------------------- /track_staple/src/sse.hpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Piotr's Computer Vision Matlab Toolbox Version 3.23 3 | * Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] 4 | * Licensed under the Simplified BSD License [see external/bsd.txt] 5 | *******************************************************************************/ 6 | #ifndef _SSE_HPP_ 7 | #define _SSE_HPP_ 8 | #include // SSE2:, SSE3:, SSE4: 9 | 10 | namespace sse{ 11 | 12 | #define RETf inline __m128 13 | #define RETi inline __m128i 14 | 15 | // set, load and store values 16 | RETf SET( const float &x ) { return _mm_set1_ps(x); } 17 | RETf SET( float x, float y, float z, float w ) { return _mm_set_ps(x,y,z,w); } 18 | RETi SET( const int &x ) { return _mm_set1_epi32(x); } 19 | RETf LD( const float &x ) { return _mm_load_ps(&x); } 20 | RETf LDu( const float &x ) { return _mm_loadu_ps(&x); } 21 | RETf STR( float &x, const __m128 y ) { _mm_store_ps(&x,y); return y; } 22 | RETf STR1( float &x, const __m128 y ) { _mm_store_ss(&x,y); return y; } 23 | RETf STRu( float &x, const __m128 y ) { _mm_storeu_ps(&x,y); return y; } 24 | RETf STR( float &x, const float y ) { return STR(x,SET(y)); } 25 | 26 | // arithmetic operators 27 | RETi ADD( const __m128i x, const __m128i y ) { return _mm_add_epi32(x,y); } 28 | RETf ADD( const __m128 x, const __m128 y ) { return _mm_add_ps(x,y); } 29 | RETf ADD( const __m128 x, const __m128 y, const __m128 z ) { 30 | return ADD(ADD(x,y),z); } 31 | RETf ADD( const __m128 a, const __m128 b, const __m128 c, const __m128 &d ) { 32 | return ADD(ADD(ADD(a,b),c),d); } 33 | RETf SUB( const __m128 x, const __m128 y ) { return _mm_sub_ps(x,y); } 34 | RETf MUL( const __m128 x, const __m128 y ) { return _mm_mul_ps(x,y); } 35 | RETf MUL( const __m128 x, const float y ) { return MUL(x,SET(y)); } 36 | RETf MUL( const float x, const __m128 y ) { return MUL(SET(x),y); } 37 | RETf INC( __m128 &x, const __m128 y ) { return x = ADD(x,y); } 38 | RETf INC( float &x, const __m128 y ) { __m128 t=ADD(LD(x),y); return STR(x,t); } 39 | RETf DEC( __m128 &x, const __m128 y ) { return x = SUB(x,y); } 40 | RETf DEC( float &x, const __m128 y ) { __m128 t=SUB(LD(x),y); return STR(x,t); } 41 | RETf MIN( const __m128 x, const __m128 y ) { return _mm_min_ps(x,y); } 42 | RETf RCP( const __m128 x ) { return _mm_rcp_ps(x); } 43 | RETf RCPSQRT( const __m128 x ) { return _mm_rsqrt_ps(x); } 44 | 45 | // logical operators 46 | RETf AND( const __m128 x, const __m128 y ) { return _mm_and_ps(x,y); } 47 | RETi AND( const __m128i x, const __m128i y ) { return _mm_and_si128(x,y); } 48 | RETf ANDNOT( const __m128 x, const __m128 y ) { return _mm_andnot_ps(x,y); } 49 | RETf OR( const __m128 x, const __m128 y ) { return _mm_or_ps(x,y); } 50 | RETf XOR( const __m128 x, const __m128 y ) { return _mm_xor_ps(x,y); } 51 | 52 | // comparison operators 53 | RETf CMPGT( const __m128 x, const __m128 y ) { return _mm_cmpgt_ps(x,y); } 54 | RETf CMPLT( const __m128 x, const __m128 y ) { return _mm_cmplt_ps(x,y); } 55 | RETi CMPGT( const __m128i x, const __m128i y ) { return _mm_cmpgt_epi32(x,y); } 56 | RETi CMPLT( const __m128i x, const __m128i y ) { return _mm_cmplt_epi32(x,y); } 57 | 58 | // conversion operators 59 | RETf CVT( const __m128i x ) { return _mm_cvtepi32_ps(x); } 60 | RETi CVT( const __m128 x ) { return _mm_cvttps_epi32(x); } 61 | 62 | #undef RETf 63 | #undef RETi 64 | 65 | } 66 | #endif 67 | -------------------------------------------------------------------------------- /track_staple/src/staple_tracker.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STAPLE_TRACKER_HPP 2 | #define STAPLE_TRACKER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define _PI 3.141592653589793 16 | #define _2PI 6.283185307179586 17 | 18 | struct staple_cfg 19 | { 20 | bool grayscale_sequence = false; // suppose that sequence is colour 21 | int hog_cell_size = 4; 22 | int fixed_area = 150*150; // standard area to which we resize the target 23 | int n_bins = 2*2*2*2*2; // number of bins for the color histograms (bg and fg models) 24 | double learning_rate_pwp = 0.04; // bg and fg color models learning rate 25 | const char * feature_type = "fhog"; // "fhog", ""gray"" 26 | double inner_padding = 0.2; // defines inner area used to sample colors from the foreground 27 | double output_sigma_factor = 1/16.0; // standard deviation for the desired translation filter output 28 | double lambda = 1e-3; // egularization weight 29 | double learning_rate_cf = 0.01; // HOG model learning rate 30 | double merge_factor = 0.3; // fixed interpolation factor - how to linearly combine the two responses 31 | const char * merge_method = "const_factor"; 32 | bool den_per_channel = false; 33 | 34 | // scale related 35 | bool scale_adaptation = true; 36 | int hog_scale_cell_size = 4; // Default DSST=4 37 | double learning_rate_scale = 0.025; 38 | double scale_sigma_factor = 1/4.0; 39 | int num_scales = 33; 40 | double scale_model_factor = 1.0; 41 | double scale_step = 1.02; 42 | double scale_model_max_area = 32*16; 43 | 44 | // debugging stuff 45 | int visualization = 0; // show output bbox on frame 46 | int visualization_dbg = 0; // show also per-pixel scores, desired response and filter output 47 | 48 | cv::Point_ init_pos; 49 | cv::Size target_sz; 50 | }; 51 | 52 | class STAPLE_TRACKER 53 | { 54 | public: 55 | STAPLE_TRACKER(){ cfg = default_parameters_staple(cfg); frameno = 0; }; 56 | ~STAPLE_TRACKER(){} 57 | 58 | void mexResize(const cv::Mat &im, cv::Mat &output, cv::Size newsz, const char *method); 59 | void tracker_staple_train(const cv::Mat &im, bool first); 60 | void tracker_staple_initialize(const cv::Mat &im, cv::Rect_ region); 61 | cv::Rect tracker_staple_update(const cv::Mat &im); 62 | 63 | protected: 64 | staple_cfg default_parameters_staple(staple_cfg cfg); 65 | void initializeAllAreas(const cv::Mat &im); 66 | 67 | void getSubwindow(const cv::Mat &im, cv::Point_ centerCoor, cv::Size model_sz, cv::Size scaled_sz, cv::Mat &output); 68 | void getSubwindowFloor(const cv::Mat &im, cv::Point_ centerCoor, cv::Size model_sz, cv::Size scaled_sz, cv::Mat &output); 69 | void updateHistModel(bool new_model, cv::Mat &patch, double learning_rate_pwp=0.0); 70 | void CalculateHann(cv::Size sz, cv::Mat &output); 71 | void gaussianResponse(cv::Size rect_size, double sigma, cv::Mat &output); 72 | void getFeatureMap(cv::Mat &im_patch, const char *feature_type, cv::MatND &output); 73 | void cropFilterResponse(const cv::Mat &response_cf, cv::Size response_size, cv::Mat& output); 74 | void getColourMap(const cv::Mat &patch, cv::Mat& output); 75 | void getCenterLikelihood(const cv::Mat &object_likelihood, cv::Size m, cv::Mat& center_likelihood); 76 | void mergeResponses(const cv::Mat &response_cf, const cv::Mat &response_pwp, cv::Mat &response); 77 | void getScaleSubwindow(const cv::Mat &im, cv::Point_ centerCoor, cv::Mat &output); 78 | 79 | private: 80 | staple_cfg cfg; 81 | 82 | cv::Point_ pos; 83 | cv::Size target_sz; 84 | 85 | cv::Size bg_area; 86 | cv::Size fg_area; 87 | double area_resize_factor; 88 | cv::Size cf_response_size; 89 | 90 | cv::Size norm_bg_area; 91 | cv::Size norm_target_sz; 92 | cv::Size norm_delta_area; 93 | cv::Size norm_pwp_search_area; 94 | 95 | cv::Mat im_patch_pwp; 96 | 97 | cv::MatND bg_hist; 98 | cv::MatND fg_hist; 99 | 100 | cv::Mat hann_window; 101 | cv::Mat yf; 102 | 103 | std::vector hf_den; 104 | std::vector hf_num; 105 | 106 | cv::Rect rect_position; 107 | 108 | float scale_factor; 109 | cv::Mat scale_window; 110 | cv::Mat scale_factors; 111 | cv::Size scale_model_sz; 112 | float min_scale_factor; 113 | float max_scale_factor; 114 | cv::Size base_target_sz; 115 | 116 | cv::Mat ysf; 117 | cv::Mat sf_den; 118 | cv::Mat sf_num; 119 | 120 | int frameno; 121 | }; 122 | 123 | #endif -------------------------------------------------------------------------------- /yolo_KCF/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(detect) 4 | 5 | SET(CMAKE_C_COMPILER g++) 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | add_compile_options(-std=c++11) 8 | message(STATUS "optional:-std=c++11") 9 | endif(CMAKE_COMPILER_IS_GNUCXX) 10 | 11 | find_package(OpenCV REQUIRED) 12 | 13 | message(STATUS "OpenCV library status:") 14 | message(STATUS " version: ${OpenCV_VERSION}") 15 | message(STATUS " libraries: ${OpenCV_LIBS}") 16 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 17 | 18 | if(CMAKE_VERSION VERSION_LESS "2.8.11") 19 | include_directories(${OpenCV_INCLUDE_DIRS}) 20 | endif() 21 | 22 | 23 | file(GLOB SRCS ./src/*.cpp) 24 | file(GLOB HDRS ./src/*.h*) 25 | 26 | set(traincascade_files ${SRCS} ${HDRS}) 27 | 28 | add_executable(detect ${traincascade_files}) 29 | 30 | # include_directories(./src) 31 | 32 | target_link_libraries(detect ${OpenCV_LIBS} libdarknet.so) 33 | -------------------------------------------------------------------------------- /yolo_KCF/build/cfg/yolov3-head.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | # batch=1 4 | # subdivisions=1 5 | # Training 6 | batch=64 7 | subdivisions=8 8 | width=192 9 | height=192 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.001 19 | burn_in=1000 20 | max_batches = 650200 21 | policy=steps 22 | steps=550000,600000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=32 28 | size=3 29 | stride=1 30 | pad=1 31 | activation=leaky 32 | 33 | # Downsample 34 | 35 | [convolutional] 36 | batch_normalize=1 37 | filters=64 38 | size=3 39 | stride=2 40 | pad=1 41 | activation=leaky 42 | 43 | [convolutional] 44 | batch_normalize=1 45 | filters=32 46 | size=1 47 | stride=1 48 | pad=1 49 | activation=leaky 50 | 51 | [convolutional] 52 | batch_normalize=1 53 | filters=64 54 | size=3 55 | stride=1 56 | pad=1 57 | activation=leaky 58 | 59 | [shortcut] 60 | from=-3 61 | activation=linear 62 | 63 | # Downsample 64 | 65 | [convolutional] 66 | batch_normalize=1 67 | filters=128 68 | size=3 69 | stride=2 70 | pad=1 71 | activation=leaky 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=64 76 | size=1 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [convolutional] 82 | batch_normalize=1 83 | filters=128 84 | size=3 85 | stride=1 86 | pad=1 87 | activation=leaky 88 | 89 | [shortcut] 90 | from=-3 91 | activation=linear 92 | 93 | [convolutional] 94 | batch_normalize=1 95 | filters=64 96 | size=1 97 | stride=1 98 | pad=1 99 | activation=leaky 100 | 101 | [convolutional] 102 | batch_normalize=1 103 | filters=128 104 | size=3 105 | stride=1 106 | pad=1 107 | activation=leaky 108 | 109 | [shortcut] 110 | from=-3 111 | activation=linear 112 | 113 | # Downsample 114 | 115 | [convolutional] 116 | batch_normalize=1 117 | filters=256 118 | size=3 119 | stride=2 120 | pad=1 121 | activation=leaky 122 | 123 | [convolutional] 124 | batch_normalize=1 125 | filters=128 126 | size=1 127 | stride=1 128 | pad=1 129 | activation=leaky 130 | 131 | [convolutional] 132 | batch_normalize=1 133 | filters=256 134 | size=3 135 | stride=1 136 | pad=1 137 | activation=leaky 138 | 139 | [shortcut] 140 | from=-3 141 | activation=linear 142 | 143 | [convolutional] 144 | batch_normalize=1 145 | filters=128 146 | size=1 147 | stride=1 148 | pad=1 149 | activation=leaky 150 | 151 | [convolutional] 152 | batch_normalize=1 153 | filters=256 154 | size=3 155 | stride=1 156 | pad=1 157 | activation=leaky 158 | 159 | [shortcut] 160 | from=-3 161 | activation=linear 162 | 163 | [convolutional] 164 | batch_normalize=1 165 | filters=128 166 | size=1 167 | stride=1 168 | pad=1 169 | activation=leaky 170 | 171 | [convolutional] 172 | batch_normalize=1 173 | filters=256 174 | size=3 175 | stride=1 176 | pad=1 177 | activation=leaky 178 | 179 | [shortcut] 180 | from=-3 181 | activation=linear 182 | 183 | [convolutional] 184 | batch_normalize=1 185 | filters=128 186 | size=1 187 | stride=1 188 | pad=1 189 | activation=leaky 190 | 191 | [convolutional] 192 | batch_normalize=1 193 | filters=256 194 | size=3 195 | stride=1 196 | pad=1 197 | activation=leaky 198 | 199 | [shortcut] 200 | from=-3 201 | activation=linear 202 | 203 | 204 | [convolutional] 205 | batch_normalize=1 206 | filters=128 207 | size=1 208 | stride=1 209 | pad=1 210 | activation=leaky 211 | 212 | [convolutional] 213 | batch_normalize=1 214 | filters=256 215 | size=3 216 | stride=1 217 | pad=1 218 | activation=leaky 219 | 220 | [shortcut] 221 | from=-3 222 | activation=linear 223 | 224 | [convolutional] 225 | batch_normalize=1 226 | filters=128 227 | size=1 228 | stride=1 229 | pad=1 230 | activation=leaky 231 | 232 | [convolutional] 233 | batch_normalize=1 234 | filters=256 235 | size=3 236 | stride=1 237 | pad=1 238 | activation=leaky 239 | 240 | [shortcut] 241 | from=-3 242 | activation=linear 243 | 244 | [convolutional] 245 | batch_normalize=1 246 | filters=128 247 | size=1 248 | stride=1 249 | pad=1 250 | activation=leaky 251 | 252 | [convolutional] 253 | batch_normalize=1 254 | filters=256 255 | size=3 256 | stride=1 257 | pad=1 258 | activation=leaky 259 | 260 | [shortcut] 261 | from=-3 262 | activation=linear 263 | 264 | [convolutional] 265 | batch_normalize=1 266 | filters=128 267 | size=1 268 | stride=1 269 | pad=1 270 | activation=leaky 271 | 272 | [convolutional] 273 | batch_normalize=1 274 | filters=256 275 | size=3 276 | stride=1 277 | pad=1 278 | activation=leaky 279 | 280 | [shortcut] 281 | from=-3 282 | activation=linear 283 | 284 | # Downsample 285 | 286 | [convolutional] 287 | batch_normalize=1 288 | filters=512 289 | size=3 290 | stride=2 291 | pad=1 292 | activation=leaky 293 | 294 | [convolutional] 295 | batch_normalize=1 296 | filters=256 297 | size=1 298 | stride=1 299 | pad=1 300 | activation=leaky 301 | 302 | [convolutional] 303 | batch_normalize=1 304 | filters=512 305 | size=3 306 | stride=1 307 | pad=1 308 | activation=leaky 309 | 310 | [shortcut] 311 | from=-3 312 | activation=linear 313 | 314 | 315 | [convolutional] 316 | batch_normalize=1 317 | filters=256 318 | size=1 319 | stride=1 320 | pad=1 321 | activation=leaky 322 | 323 | [convolutional] 324 | batch_normalize=1 325 | filters=512 326 | size=3 327 | stride=1 328 | pad=1 329 | activation=leaky 330 | 331 | [shortcut] 332 | from=-3 333 | activation=linear 334 | 335 | 336 | [convolutional] 337 | batch_normalize=1 338 | filters=256 339 | size=1 340 | stride=1 341 | pad=1 342 | activation=leaky 343 | 344 | [convolutional] 345 | batch_normalize=1 346 | filters=512 347 | size=3 348 | stride=1 349 | pad=1 350 | activation=leaky 351 | 352 | [shortcut] 353 | from=-3 354 | activation=linear 355 | 356 | 357 | [convolutional] 358 | batch_normalize=1 359 | filters=256 360 | size=1 361 | stride=1 362 | pad=1 363 | activation=leaky 364 | 365 | [convolutional] 366 | batch_normalize=1 367 | filters=512 368 | size=3 369 | stride=1 370 | pad=1 371 | activation=leaky 372 | 373 | [shortcut] 374 | from=-3 375 | activation=linear 376 | 377 | [convolutional] 378 | batch_normalize=1 379 | filters=256 380 | size=1 381 | stride=1 382 | pad=1 383 | activation=leaky 384 | 385 | [convolutional] 386 | batch_normalize=1 387 | filters=512 388 | size=3 389 | stride=1 390 | pad=1 391 | activation=leaky 392 | 393 | [shortcut] 394 | from=-3 395 | activation=linear 396 | 397 | 398 | [convolutional] 399 | batch_normalize=1 400 | filters=256 401 | size=1 402 | stride=1 403 | pad=1 404 | activation=leaky 405 | 406 | [convolutional] 407 | batch_normalize=1 408 | filters=512 409 | size=3 410 | stride=1 411 | pad=1 412 | activation=leaky 413 | 414 | [shortcut] 415 | from=-3 416 | activation=linear 417 | 418 | 419 | [convolutional] 420 | batch_normalize=1 421 | filters=256 422 | size=1 423 | stride=1 424 | pad=1 425 | activation=leaky 426 | 427 | [convolutional] 428 | batch_normalize=1 429 | filters=512 430 | size=3 431 | stride=1 432 | pad=1 433 | activation=leaky 434 | 435 | [shortcut] 436 | from=-3 437 | activation=linear 438 | 439 | [convolutional] 440 | batch_normalize=1 441 | filters=256 442 | size=1 443 | stride=1 444 | pad=1 445 | activation=leaky 446 | 447 | [convolutional] 448 | batch_normalize=1 449 | filters=512 450 | size=3 451 | stride=1 452 | pad=1 453 | activation=leaky 454 | 455 | [shortcut] 456 | from=-3 457 | activation=linear 458 | 459 | # Downsample 460 | 461 | [convolutional] 462 | batch_normalize=1 463 | filters=1024 464 | size=3 465 | stride=2 466 | pad=1 467 | activation=leaky 468 | 469 | [convolutional] 470 | batch_normalize=1 471 | filters=512 472 | size=1 473 | stride=1 474 | pad=1 475 | activation=leaky 476 | 477 | [convolutional] 478 | batch_normalize=1 479 | filters=1024 480 | size=3 481 | stride=1 482 | pad=1 483 | activation=leaky 484 | 485 | [shortcut] 486 | from=-3 487 | activation=linear 488 | 489 | [convolutional] 490 | batch_normalize=1 491 | filters=512 492 | size=1 493 | stride=1 494 | pad=1 495 | activation=leaky 496 | 497 | [convolutional] 498 | batch_normalize=1 499 | filters=1024 500 | size=3 501 | stride=1 502 | pad=1 503 | activation=leaky 504 | 505 | [shortcut] 506 | from=-3 507 | activation=linear 508 | 509 | [convolutional] 510 | batch_normalize=1 511 | filters=512 512 | size=1 513 | stride=1 514 | pad=1 515 | activation=leaky 516 | 517 | [convolutional] 518 | batch_normalize=1 519 | filters=1024 520 | size=3 521 | stride=1 522 | pad=1 523 | activation=leaky 524 | 525 | [shortcut] 526 | from=-3 527 | activation=linear 528 | 529 | [convolutional] 530 | batch_normalize=1 531 | filters=512 532 | size=1 533 | stride=1 534 | pad=1 535 | activation=leaky 536 | 537 | [convolutional] 538 | batch_normalize=1 539 | filters=1024 540 | size=3 541 | stride=1 542 | pad=1 543 | activation=leaky 544 | stopbackward=1 545 | 546 | [shortcut] 547 | from=-3 548 | activation=linear 549 | 550 | ###################### 551 | 552 | [convolutional] 553 | batch_normalize=1 554 | filters=512 555 | size=1 556 | stride=1 557 | pad=1 558 | activation=leaky 559 | 560 | [convolutional] 561 | batch_normalize=1 562 | size=3 563 | stride=1 564 | pad=1 565 | filters=1024 566 | activation=leaky 567 | 568 | [convolutional] 569 | batch_normalize=1 570 | filters=512 571 | size=1 572 | stride=1 573 | pad=1 574 | activation=leaky 575 | 576 | [convolutional] 577 | batch_normalize=1 578 | size=3 579 | stride=1 580 | pad=1 581 | filters=1024 582 | activation=leaky 583 | 584 | [convolutional] 585 | batch_normalize=1 586 | filters=512 587 | size=1 588 | stride=1 589 | pad=1 590 | activation=leaky 591 | 592 | [convolutional] 593 | batch_normalize=1 594 | size=3 595 | stride=1 596 | pad=1 597 | filters=1024 598 | activation=leaky 599 | 600 | 601 | [convolutional] 602 | size=1 603 | stride=1 604 | pad=1 605 | filters=18 606 | activation=linear 607 | 608 | 609 | [yolo] 610 | mask = 6,7,8 611 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 612 | classes=1 613 | num=9 614 | jitter=.3 615 | ignore_thresh = .5 616 | truth_thresh = 1 617 | random=1 618 | 619 | 620 | [route] 621 | layers = -4 622 | 623 | [convolutional] 624 | batch_normalize=1 625 | filters=256 626 | size=1 627 | stride=1 628 | pad=1 629 | activation=leaky 630 | 631 | [upsample] 632 | stride=2 633 | 634 | [route] 635 | layers = -1, 61 636 | 637 | 638 | 639 | [convolutional] 640 | batch_normalize=1 641 | filters=256 642 | size=1 643 | stride=1 644 | pad=1 645 | activation=leaky 646 | 647 | [convolutional] 648 | batch_normalize=1 649 | size=3 650 | stride=1 651 | pad=1 652 | filters=512 653 | activation=leaky 654 | 655 | [convolutional] 656 | batch_normalize=1 657 | filters=256 658 | size=1 659 | stride=1 660 | pad=1 661 | activation=leaky 662 | 663 | [convolutional] 664 | batch_normalize=1 665 | size=3 666 | stride=1 667 | pad=1 668 | filters=512 669 | activation=leaky 670 | 671 | [convolutional] 672 | batch_normalize=1 673 | filters=256 674 | size=1 675 | stride=1 676 | pad=1 677 | activation=leaky 678 | 679 | [convolutional] 680 | batch_normalize=1 681 | size=3 682 | stride=1 683 | pad=1 684 | filters=512 685 | activation=leaky 686 | 687 | [convolutional] 688 | size=1 689 | stride=1 690 | pad=1 691 | filters=18 692 | activation=linear 693 | 694 | 695 | [yolo] 696 | mask = 3,4,5 697 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 698 | classes=1 699 | num=9 700 | jitter=.3 701 | ignore_thresh = .5 702 | truth_thresh = 1 703 | random=1 704 | 705 | 706 | 707 | [route] 708 | layers = -4 709 | 710 | [convolutional] 711 | batch_normalize=1 712 | filters=128 713 | size=1 714 | stride=1 715 | pad=1 716 | activation=leaky 717 | 718 | [upsample] 719 | stride=2 720 | 721 | [route] 722 | layers = -1, 36 723 | 724 | 725 | 726 | [convolutional] 727 | batch_normalize=1 728 | filters=128 729 | size=1 730 | stride=1 731 | pad=1 732 | activation=leaky 733 | 734 | [convolutional] 735 | batch_normalize=1 736 | size=3 737 | stride=1 738 | pad=1 739 | filters=256 740 | activation=leaky 741 | 742 | [convolutional] 743 | batch_normalize=1 744 | filters=128 745 | size=1 746 | stride=1 747 | pad=1 748 | activation=leaky 749 | 750 | [convolutional] 751 | batch_normalize=1 752 | size=3 753 | stride=1 754 | pad=1 755 | filters=256 756 | activation=leaky 757 | 758 | [convolutional] 759 | batch_normalize=1 760 | filters=128 761 | size=1 762 | stride=1 763 | pad=1 764 | activation=leaky 765 | 766 | [convolutional] 767 | batch_normalize=1 768 | size=3 769 | stride=1 770 | pad=1 771 | filters=256 772 | activation=leaky 773 | 774 | [convolutional] 775 | size=1 776 | stride=1 777 | pad=1 778 | filters=18 779 | activation=linear 780 | 781 | 782 | [yolo] 783 | mask = 0,1,2 784 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 785 | classes=1 786 | num=9 787 | jitter=.3 788 | ignore_thresh = .5 789 | truth_thresh = 1 790 | random=1 791 | 792 | -------------------------------------------------------------------------------- /yolo_KCF/build/cfg/yolov3-tiny.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | batch=1 4 | subdivisions=1 5 | # Training 6 | # batch=64 7 | # subdivisions=2 8 | width=416 9 | height=416 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.001 19 | burn_in=1000 20 | max_batches = 500200 21 | policy=steps 22 | steps=400000,450000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=16 28 | size=3 29 | stride=1 30 | pad=1 31 | activation=leaky 32 | 33 | [maxpool] 34 | size=2 35 | stride=2 36 | 37 | [convolutional] 38 | batch_normalize=1 39 | filters=32 40 | size=3 41 | stride=1 42 | pad=1 43 | activation=leaky 44 | 45 | [maxpool] 46 | size=2 47 | stride=2 48 | 49 | [convolutional] 50 | batch_normalize=1 51 | filters=64 52 | size=3 53 | stride=1 54 | pad=1 55 | activation=leaky 56 | 57 | [maxpool] 58 | size=2 59 | stride=2 60 | 61 | [convolutional] 62 | batch_normalize=1 63 | filters=128 64 | size=3 65 | stride=1 66 | pad=1 67 | activation=leaky 68 | 69 | [maxpool] 70 | size=2 71 | stride=2 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=256 76 | size=3 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [maxpool] 82 | size=2 83 | stride=2 84 | 85 | [convolutional] 86 | batch_normalize=1 87 | filters=512 88 | size=3 89 | stride=1 90 | pad=1 91 | activation=leaky 92 | 93 | [maxpool] 94 | size=2 95 | stride=1 96 | 97 | [convolutional] 98 | batch_normalize=1 99 | filters=1024 100 | size=3 101 | stride=1 102 | pad=1 103 | activation=leaky 104 | 105 | ########### 106 | 107 | [convolutional] 108 | batch_normalize=1 109 | filters=256 110 | size=1 111 | stride=1 112 | pad=1 113 | activation=leaky 114 | 115 | [convolutional] 116 | batch_normalize=1 117 | filters=512 118 | size=3 119 | stride=1 120 | pad=1 121 | activation=leaky 122 | 123 | [convolutional] 124 | size=1 125 | stride=1 126 | pad=1 127 | filters=255 128 | activation=linear 129 | 130 | 131 | 132 | [yolo] 133 | mask = 3,4,5 134 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 135 | classes=80 136 | num=6 137 | jitter=.3 138 | ignore_thresh = .7 139 | truth_thresh = 1 140 | random=1 141 | 142 | [route] 143 | layers = -4 144 | 145 | [convolutional] 146 | batch_normalize=1 147 | filters=128 148 | size=1 149 | stride=1 150 | pad=1 151 | activation=leaky 152 | 153 | [upsample] 154 | stride=2 155 | 156 | [route] 157 | layers = -1, 8 158 | 159 | [convolutional] 160 | batch_normalize=1 161 | filters=256 162 | size=3 163 | stride=1 164 | pad=1 165 | activation=leaky 166 | 167 | [convolutional] 168 | size=1 169 | stride=1 170 | pad=1 171 | filters=255 172 | activation=linear 173 | 174 | [yolo] 175 | mask = 1,2,3 176 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 177 | classes=80 178 | num=6 179 | jitter=.3 180 | ignore_thresh = .7 181 | truth_thresh = 1 182 | random=1 183 | -------------------------------------------------------------------------------- /yolo_KCF/build/detect: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/yolo_KCF/build/detect -------------------------------------------------------------------------------- /yolo_KCF/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "utils.h" 6 | 7 | using namespace std; 8 | 9 | int main(int argc, char **argv) 10 | { 11 | // List of tracker types in OpenCV 3.2 12 | // NOTE : GOTURN implementation is buggy and does not work. 13 | string trackerTypes[7] = {"BOOSTING", "MIL", "KCF", "TLD","MEDIANFLOW", "GOTURN", "CSRT"}; 14 | // vector trackerTypes(types, std::end(types)); 15 | 16 | // Create a tracker 17 | string trackerType = trackerTypes[3]; 18 | 19 | cv::Ptr tracker; 20 | 21 | if (trackerType == "BOOSTING") 22 | tracker = cv::TrackerBoosting::create(); 23 | if (trackerType == "MIL") 24 | tracker = cv::TrackerMIL::create(); 25 | if (trackerType == "KCF") 26 | tracker = cv::TrackerKCF::create(); 27 | if (trackerType == "TLD") 28 | tracker = cv::TrackerTLD::create(); 29 | if (trackerType == "MEDIANFLOW") 30 | tracker = cv::TrackerMedianFlow::create(); 31 | if (trackerType == "GOTURN") 32 | tracker = cv::TrackerGOTURN::create(); 33 | if (trackerType == "CSRT") 34 | tracker = cv::TrackerCSRT::create(); 35 | 36 | // Create a detector 37 | string cfgDir = "cfg/yolov3-head.cfg"; 38 | string weightDir = "cfg/yolov3-head.weights"; 39 | Detector detector(cfgDir, weightDir); 40 | 41 | // Create a video stream 42 | cv::VideoCapture capture( 0 ); 43 | if(!capture.isOpened()) 44 | { 45 | cout << "Could not read camera" << endl; 46 | return 1; 47 | 48 | } 49 | 50 | cv::TickMeter meter; 51 | cv::Mat frame, frameShow; 52 | // 0:No object. 53 | // 1:Object detected and tracking. 54 | int status = 0; 55 | cv::Rect2d location; 56 | 57 | 58 | while(capture.read(frame)) 59 | { 60 | meter.start(); 61 | if(frame.empty()) 62 | { 63 | cout << "No captured frame" << endl; 64 | break; 65 | } 66 | frameShow = frame.clone(); 67 | 68 | 69 | double timer = (double)cv::getTickCount(); 70 | if(status == 0) 71 | { 72 | vector results = detector.detect(frame, 0.15); 73 | vector persons = person_filter(results); 74 | if(persons.size() > 0) 75 | { 76 | cout << "[debug] " << meter.getCounter() << ": " << "persons: " << persons.size() << endl; 77 | for(size_t i = 0; i < persons.size(); i++) 78 | rectangle( frameShow, persons[i], cv::Scalar(20, 20, 20), 1, 8, 0); 79 | location = max_filter(persons); 80 | 81 | tracker->init(frame, location); 82 | status = 1; 83 | cout << "[debug] " << meter.getCounter() << ": " << "开始跟踪" << endl; 84 | } 85 | } 86 | else if(status == 1) 87 | { 88 | bool ok = tracker->update(frame, location); 89 | if( ok == false ) 90 | { 91 | cout << "---------------------------------------Track failed" << endl; 92 | // Tracking failure detected. YOLO detecion 93 | vector results = detector.detect(frame, 0.15); 94 | vector persons = person_filter(results); 95 | if(persons.size() > 0) 96 | { 97 | // Detection success, reinit tracker. 98 | for(size_t i = 0; i < persons.size(); i++) 99 | rectangle( frameShow, persons[i], cv::Scalar(20, 20, 20), 1, 8, 0); 100 | location = max_filter(persons); 101 | tracker->init(frame, location); 102 | } 103 | else 104 | { 105 | // Detection failed. 106 | status = 0; 107 | } 108 | } 109 | } 110 | 111 | if(status == 1) 112 | { 113 | // Tracking or detection successed. 114 | cout << "[loc: " << location.x << " " << location.y << " " << location.width << " " << location.height << "]\n"; 115 | rectangle(frameShow, location, cv::Scalar(255, 0, 0), 2, 1); 116 | } 117 | else 118 | { 119 | // Tracking or detection failed. 120 | putText(frameShow, "Tracking failure detected", cv::Point(100,80), cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0,0,255),2); 121 | } 122 | 123 | // Show real-time fps. 124 | float fps = cv::getTickFrequency() / ((double)cv::getTickCount() - timer); 125 | putText(frameShow, "FPS : " + SSTR(int(fps)), cv::Point(100,50), cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(50,170,50), 2); 126 | imshow("Detection-Tracking", frameShow); 127 | 128 | int k = cv::waitKey(1); 129 | if(k == 27) 130 | { 131 | break; 132 | } 133 | 134 | meter.stop(); 135 | } 136 | 137 | // Print average fps. 138 | double fps = double(meter.getCounter()) / meter.getTimeSec(); 139 | cout << "[Average fps] " << fps << endl; 140 | 141 | return 0; 142 | } -------------------------------------------------------------------------------- /yolo_KCF/src/utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "yolo_v2_class.hpp" 11 | 12 | using namespace std; 13 | 14 | vector person_filter(vector results) 15 | { 16 | vector persons; 17 | for(size_t i = 0; i < results.size(); i++) 18 | { 19 | if( results[i].obj_id == 0 ) 20 | { 21 | cv::Rect2d box; 22 | box.x = results[i].x; 23 | box.y = results[i].y; 24 | box.width = results[i].w; 25 | box.height = results[i].h; 26 | persons.push_back(box); 27 | } 28 | } 29 | return persons; 30 | } 31 | 32 | cv::Rect2d max_filter(vector persons) 33 | { 34 | int max_aera = persons[0].area(); 35 | int max_index = 0; 36 | for(size_t i = 1; i < persons.size(); i++) 37 | { 38 | int area = persons[i].area(); 39 | if(area > max_aera) 40 | { 41 | max_aera = area; 42 | max_index = i; 43 | } 44 | } 45 | return persons[max_index]; 46 | } 47 | 48 | void limitRect(cv::Rect2d &location, cv::Size sz) 49 | { 50 | cv::Rect2d window(cv::Point(0, 0), sz); 51 | location = location & window; 52 | } 53 | 54 | // Convert to string 55 | #define SSTR( x ) static_cast< std::ostringstream & >( \ 56 | ( std::ostringstream() << std::dec << x ) ).str() 57 | 58 | string IntToString(int value) 59 | { 60 | ostringstream convert; 61 | convert << value; 62 | return convert.str(); 63 | } 64 | 65 | string GetCurrentTime() 66 | { 67 | time_t Time = time(NULL); 68 | tm* LocalTime = localtime(&Time); 69 | string Result; 70 | 71 | // add the year 72 | Result += IntToString(LocalTime->tm_year + 1900) + "-"; 73 | // add the month 74 | Result += IntToString(LocalTime->tm_mon + 1) + "-"; 75 | // add the day 76 | Result += IntToString(LocalTime->tm_mday) + "_"; 77 | // add the hour 78 | Result += IntToString(LocalTime->tm_hour) + "-"; 79 | // add the minutes 80 | Result += IntToString(LocalTime->tm_min) + "-"; 81 | // add the seconds 82 | Result += IntToString(LocalTime->tm_sec); 83 | 84 | return Result; 85 | } 86 | 87 | string GetCurrentTime2() 88 | { 89 | time_t Time = time(NULL); 90 | tm* LocalTime = localtime(&Time); 91 | string Result; 92 | 93 | // add the year 94 | Result += IntToString(LocalTime->tm_year + 1900) + "-"; 95 | // add the month 96 | Result += IntToString(LocalTime->tm_mon + 1) + "-"; 97 | // add the day 98 | Result += IntToString(LocalTime->tm_mday) + " "; 99 | // add the hour 100 | Result += IntToString(LocalTime->tm_hour) + ":"; 101 | // add the minutes 102 | Result += IntToString(LocalTime->tm_min) + ":"; 103 | // add the seconds 104 | Result += IntToString(LocalTime->tm_sec); 105 | 106 | return Result; 107 | } -------------------------------------------------------------------------------- /yolo_KCF/src/yolo_v2_class.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifdef YOLODLL_EXPORTS 3 | #if defined(_MSC_VER) 4 | #define YOLODLL_API __declspec(dllexport) 5 | #else 6 | #define YOLODLL_API __attribute__((visibility("default"))) 7 | #endif 8 | #else 9 | #if defined(_MSC_VER) 10 | #define YOLODLL_API __declspec(dllimport) 11 | #else 12 | #define YOLODLL_API 13 | #endif 14 | #endif 15 | 16 | struct bbox_t { 17 | unsigned int x, y, w, h; // (x,y) - top-left corner, (w, h) - width & height of bounded box 18 | float prob; // confidence - probability that the object was found correctly 19 | unsigned int obj_id; // class of object - from range [0, classes-1] 20 | unsigned int track_id; // tracking id for video (0 - untracked, 1 - inf - tracked object) 21 | unsigned int frames_counter;// counter of frames on which the object was detected 22 | }; 23 | 24 | struct image_t { 25 | int h; // height 26 | int w; // width 27 | int c; // number of chanels (3 - for RGB) 28 | float *data; // pointer to the image data 29 | }; 30 | 31 | #define C_SHARP_MAX_OBJECTS 1000 32 | struct bbox_t_container { 33 | bbox_t candidates[C_SHARP_MAX_OBJECTS]; 34 | }; 35 | 36 | #ifdef __cplusplus 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #define OPENCV 43 | #ifdef OPENCV 44 | #include // C++ 45 | #include "opencv2/highgui/highgui_c.h" // C 46 | #include "opencv2/imgproc/imgproc_c.h" // C 47 | #endif // OPENCV 48 | 49 | extern "C" YOLODLL_API int init(const char *configurationFilename, const char *weightsFilename, int gpu); 50 | extern "C" YOLODLL_API int detect_image(const char *filename, bbox_t_container &container); 51 | extern "C" YOLODLL_API int detect_mat(const uint8_t* data, const size_t data_length, bbox_t_container &container); 52 | extern "C" YOLODLL_API int dispose(); 53 | extern "C" YOLODLL_API int get_device_count(); 54 | extern "C" YOLODLL_API int get_device_name(int gpu, char* deviceName); 55 | 56 | class Detector { 57 | std::shared_ptr detector_gpu_ptr; 58 | std::deque> prev_bbox_vec_deque; 59 | const int cur_gpu_id; 60 | public: 61 | float nms = .4; 62 | bool wait_stream; 63 | 64 | YOLODLL_API Detector(std::string cfg_filename, std::string weight_filename, int gpu_id = 0); 65 | YOLODLL_API ~Detector(); 66 | 67 | YOLODLL_API std::vector detect(std::string image_filename, float thresh = 0.2, bool use_mean = false); 68 | YOLODLL_API std::vector detect(image_t img, float thresh = 0.2, bool use_mean = false); 69 | static YOLODLL_API image_t load_image(std::string image_filename); 70 | static YOLODLL_API void free_image(image_t m); 71 | YOLODLL_API int get_net_width() const; 72 | YOLODLL_API int get_net_height() const; 73 | YOLODLL_API int get_net_color_depth() const; 74 | 75 | YOLODLL_API std::vector tracking_id(std::vector cur_bbox_vec, bool const change_history = true, 76 | int const frames_story = 10, int const max_dist = 150); 77 | 78 | std::vector detect_resized(image_t img, int init_w, int init_h, float thresh = 0.2, bool use_mean = false) 79 | { 80 | if (img.data == NULL) 81 | throw std::runtime_error("Image is empty"); 82 | auto detection_boxes = detect(img, thresh, use_mean); 83 | float wk = (float)init_w / img.w, hk = (float)init_h / img.h; 84 | for (auto &i : detection_boxes) i.x *= wk, i.w *= wk, i.y *= hk, i.h *= hk; 85 | return detection_boxes; 86 | } 87 | 88 | #ifdef OPENCV 89 | std::vector detect(cv::Mat mat, float thresh = 0.2, bool use_mean = false) 90 | { 91 | if(mat.data == NULL) 92 | throw std::runtime_error("Image is empty"); 93 | auto image_ptr = mat_to_image_resize(mat); 94 | return detect_resized(*image_ptr, mat.cols, mat.rows, thresh, use_mean); 95 | } 96 | 97 | std::shared_ptr mat_to_image_resize(cv::Mat mat) const 98 | { 99 | if (mat.data == NULL) return std::shared_ptr(NULL); 100 | 101 | cv::Size network_size = cv::Size(get_net_width(), get_net_height()); 102 | cv::Mat det_mat; 103 | if (mat.size() != network_size) 104 | cv::resize(mat, det_mat, network_size); 105 | else 106 | det_mat = mat; // only reference is copied 107 | 108 | return mat_to_image(det_mat); 109 | } 110 | 111 | static std::shared_ptr mat_to_image(cv::Mat img_src) 112 | { 113 | cv::Mat img; 114 | cv::cvtColor(img_src, img, cv::COLOR_RGB2BGR); 115 | std::shared_ptr image_ptr(new image_t, [](image_t *img) { free_image(*img); delete img; }); 116 | std::shared_ptr ipl_small = std::make_shared(img); 117 | *image_ptr = ipl_to_image(ipl_small.get()); 118 | return image_ptr; 119 | } 120 | 121 | private: 122 | 123 | static image_t ipl_to_image(IplImage* src) 124 | { 125 | unsigned char *data = (unsigned char *)src->imageData; 126 | int h = src->height; 127 | int w = src->width; 128 | int c = src->nChannels; 129 | int step = src->widthStep; 130 | image_t out = make_image_custom(w, h, c); 131 | int count = 0; 132 | 133 | for (int k = 0; k < c; ++k) { 134 | for (int i = 0; i < h; ++i) { 135 | int i_step = i*step; 136 | for (int j = 0; j < w; ++j) { 137 | out.data[count++] = data[i_step + j*c + k] / 255.; 138 | } 139 | } 140 | } 141 | 142 | return out; 143 | } 144 | 145 | static image_t make_empty_image(int w, int h, int c) 146 | { 147 | image_t out; 148 | out.data = 0; 149 | out.h = h; 150 | out.w = w; 151 | out.c = c; 152 | return out; 153 | } 154 | 155 | static image_t make_image_custom(int w, int h, int c) 156 | { 157 | image_t out = make_empty_image(w, h, c); 158 | out.data = (float *)calloc(h*w*c, sizeof(float)); 159 | return out; 160 | } 161 | 162 | #endif // OPENCV 163 | 164 | }; 165 | 166 | 167 | 168 | #if defined(TRACK_OPTFLOW) && defined(OPENCV) && defined(GPU) 169 | 170 | #include 171 | #include 172 | #include 173 | #include 174 | 175 | class Tracker_optflow { 176 | public: 177 | const int gpu_count; 178 | const int gpu_id; 179 | const int flow_error; 180 | 181 | 182 | Tracker_optflow(int _gpu_id = 0, int win_size = 9, int max_level = 3, int iterations = 8000, int _flow_error = -1) : 183 | gpu_count(cv::cuda::getCudaEnabledDeviceCount()), gpu_id(std::min(_gpu_id, gpu_count-1)), 184 | flow_error((_flow_error > 0)? _flow_error:(win_size*4)) 185 | { 186 | int const old_gpu_id = cv::cuda::getDevice(); 187 | cv::cuda::setDevice(gpu_id); 188 | 189 | stream = cv::cuda::Stream(); 190 | 191 | sync_PyrLKOpticalFlow_gpu = cv::cuda::SparsePyrLKOpticalFlow::create(); 192 | sync_PyrLKOpticalFlow_gpu->setWinSize(cv::Size(win_size, win_size)); // 9, 15, 21, 31 193 | sync_PyrLKOpticalFlow_gpu->setMaxLevel(max_level); // +- 3 pt 194 | sync_PyrLKOpticalFlow_gpu->setNumIters(iterations); // 2000, def: 30 195 | 196 | cv::cuda::setDevice(old_gpu_id); 197 | } 198 | 199 | // just to avoid extra allocations 200 | cv::cuda::GpuMat src_mat_gpu; 201 | cv::cuda::GpuMat dst_mat_gpu, dst_grey_gpu; 202 | cv::cuda::GpuMat prev_pts_flow_gpu, cur_pts_flow_gpu; 203 | cv::cuda::GpuMat status_gpu, err_gpu; 204 | 205 | cv::cuda::GpuMat src_grey_gpu; // used in both functions 206 | cv::Ptr sync_PyrLKOpticalFlow_gpu; 207 | cv::cuda::Stream stream; 208 | 209 | std::vector cur_bbox_vec; 210 | std::vector good_bbox_vec_flags; 211 | cv::Mat prev_pts_flow_cpu; 212 | 213 | void update_cur_bbox_vec(std::vector _cur_bbox_vec) 214 | { 215 | cur_bbox_vec = _cur_bbox_vec; 216 | good_bbox_vec_flags = std::vector(cur_bbox_vec.size(), true); 217 | cv::Mat prev_pts, cur_pts_flow_cpu; 218 | 219 | for (auto &i : cur_bbox_vec) { 220 | float x_center = (i.x + i.w / 2.0F); 221 | float y_center = (i.y + i.h / 2.0F); 222 | prev_pts.push_back(cv::Point2f(x_center, y_center)); 223 | } 224 | 225 | if (prev_pts.rows == 0) 226 | prev_pts_flow_cpu = cv::Mat(); 227 | else 228 | cv::transpose(prev_pts, prev_pts_flow_cpu); 229 | 230 | if (prev_pts_flow_gpu.cols < prev_pts_flow_cpu.cols) { 231 | prev_pts_flow_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), prev_pts_flow_cpu.type()); 232 | cur_pts_flow_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), prev_pts_flow_cpu.type()); 233 | 234 | status_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), CV_8UC1); 235 | err_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), CV_32FC1); 236 | } 237 | 238 | prev_pts_flow_gpu.upload(cv::Mat(prev_pts_flow_cpu), stream); 239 | } 240 | 241 | 242 | void update_tracking_flow(cv::Mat src_mat, std::vector _cur_bbox_vec) 243 | { 244 | int const old_gpu_id = cv::cuda::getDevice(); 245 | if (old_gpu_id != gpu_id) 246 | cv::cuda::setDevice(gpu_id); 247 | 248 | if (src_mat.channels() == 3) { 249 | if (src_mat_gpu.cols == 0) { 250 | src_mat_gpu = cv::cuda::GpuMat(src_mat.size(), src_mat.type()); 251 | src_grey_gpu = cv::cuda::GpuMat(src_mat.size(), CV_8UC1); 252 | } 253 | 254 | update_cur_bbox_vec(_cur_bbox_vec); 255 | 256 | //src_grey_gpu.upload(src_mat, stream); // use BGR 257 | src_mat_gpu.upload(src_mat, stream); 258 | cv::cuda::cvtColor(src_mat_gpu, src_grey_gpu, CV_BGR2GRAY, 1, stream); 259 | } 260 | if (old_gpu_id != gpu_id) 261 | cv::cuda::setDevice(old_gpu_id); 262 | } 263 | 264 | 265 | std::vector tracking_flow(cv::Mat dst_mat, bool check_error = true) 266 | { 267 | if (sync_PyrLKOpticalFlow_gpu.empty()) { 268 | std::cout << "sync_PyrLKOpticalFlow_gpu isn't initialized \n"; 269 | return cur_bbox_vec; 270 | } 271 | 272 | int const old_gpu_id = cv::cuda::getDevice(); 273 | if(old_gpu_id != gpu_id) 274 | cv::cuda::setDevice(gpu_id); 275 | 276 | if (dst_mat_gpu.cols == 0) { 277 | dst_mat_gpu = cv::cuda::GpuMat(dst_mat.size(), dst_mat.type()); 278 | dst_grey_gpu = cv::cuda::GpuMat(dst_mat.size(), CV_8UC1); 279 | } 280 | 281 | //dst_grey_gpu.upload(dst_mat, stream); // use BGR 282 | dst_mat_gpu.upload(dst_mat, stream); 283 | cv::cuda::cvtColor(dst_mat_gpu, dst_grey_gpu, CV_BGR2GRAY, 1, stream); 284 | 285 | if (src_grey_gpu.rows != dst_grey_gpu.rows || src_grey_gpu.cols != dst_grey_gpu.cols) { 286 | stream.waitForCompletion(); 287 | src_grey_gpu = dst_grey_gpu.clone(); 288 | cv::cuda::setDevice(old_gpu_id); 289 | return cur_bbox_vec; 290 | } 291 | 292 | ////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 293 | 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 294 | 295 | cv::Mat cur_pts_flow_cpu; 296 | cur_pts_flow_gpu.download(cur_pts_flow_cpu, stream); 297 | 298 | dst_grey_gpu.copyTo(src_grey_gpu, stream); 299 | 300 | cv::Mat err_cpu, status_cpu; 301 | err_gpu.download(err_cpu, stream); 302 | status_gpu.download(status_cpu, stream); 303 | 304 | stream.waitForCompletion(); 305 | 306 | std::vector result_bbox_vec; 307 | 308 | if (err_cpu.cols == cur_bbox_vec.size() && status_cpu.cols == cur_bbox_vec.size()) 309 | { 310 | for (size_t i = 0; i < cur_bbox_vec.size(); ++i) 311 | { 312 | cv::Point2f cur_key_pt = cur_pts_flow_cpu.at(0, i); 313 | cv::Point2f prev_key_pt = prev_pts_flow_cpu.at(0, i); 314 | 315 | float moved_x = cur_key_pt.x - prev_key_pt.x; 316 | float moved_y = cur_key_pt.y - prev_key_pt.y; 317 | 318 | if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i]) 319 | if (err_cpu.at(0, i) < flow_error && status_cpu.at(0, i) != 0 && 320 | ((float)cur_bbox_vec[i].x + moved_x) > 0 && ((float)cur_bbox_vec[i].y + moved_y) > 0) 321 | { 322 | cur_bbox_vec[i].x += moved_x + 0.5; 323 | cur_bbox_vec[i].y += moved_y + 0.5; 324 | result_bbox_vec.push_back(cur_bbox_vec[i]); 325 | } 326 | else good_bbox_vec_flags[i] = false; 327 | else good_bbox_vec_flags[i] = false; 328 | 329 | //if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]); 330 | } 331 | } 332 | 333 | cur_pts_flow_gpu.swap(prev_pts_flow_gpu); 334 | cur_pts_flow_cpu.copyTo(prev_pts_flow_cpu); 335 | 336 | if (old_gpu_id != gpu_id) 337 | cv::cuda::setDevice(old_gpu_id); 338 | 339 | return result_bbox_vec; 340 | } 341 | 342 | }; 343 | 344 | #elif defined(TRACK_OPTFLOW) && defined(OPENCV) 345 | 346 | //#include 347 | #include 348 | 349 | class Tracker_optflow { 350 | public: 351 | const int flow_error; 352 | 353 | 354 | Tracker_optflow(int win_size = 9, int max_level = 3, int iterations = 8000, int _flow_error = -1) : 355 | flow_error((_flow_error > 0)? _flow_error:(win_size*4)) 356 | { 357 | sync_PyrLKOpticalFlow = cv::SparsePyrLKOpticalFlow::create(); 358 | sync_PyrLKOpticalFlow->setWinSize(cv::Size(win_size, win_size)); // 9, 15, 21, 31 359 | sync_PyrLKOpticalFlow->setMaxLevel(max_level); // +- 3 pt 360 | 361 | } 362 | 363 | // just to avoid extra allocations 364 | cv::Mat dst_grey; 365 | cv::Mat prev_pts_flow, cur_pts_flow; 366 | cv::Mat status, err; 367 | 368 | cv::Mat src_grey; // used in both functions 369 | cv::Ptr sync_PyrLKOpticalFlow; 370 | 371 | std::vector cur_bbox_vec; 372 | std::vector good_bbox_vec_flags; 373 | 374 | void update_cur_bbox_vec(std::vector _cur_bbox_vec) 375 | { 376 | cur_bbox_vec = _cur_bbox_vec; 377 | good_bbox_vec_flags = std::vector(cur_bbox_vec.size(), true); 378 | cv::Mat prev_pts, cur_pts_flow; 379 | 380 | for (auto &i : cur_bbox_vec) { 381 | float x_center = (i.x + i.w / 2.0F); 382 | float y_center = (i.y + i.h / 2.0F); 383 | prev_pts.push_back(cv::Point2f(x_center, y_center)); 384 | } 385 | 386 | if (prev_pts.rows == 0) 387 | prev_pts_flow = cv::Mat(); 388 | else 389 | cv::transpose(prev_pts, prev_pts_flow); 390 | } 391 | 392 | 393 | void update_tracking_flow(cv::Mat new_src_mat, std::vector _cur_bbox_vec) 394 | { 395 | if (new_src_mat.channels() == 3) { 396 | 397 | update_cur_bbox_vec(_cur_bbox_vec); 398 | 399 | cv::cvtColor(new_src_mat, src_grey, CV_BGR2GRAY, 1); 400 | } 401 | } 402 | 403 | 404 | std::vector tracking_flow(cv::Mat new_dst_mat, bool check_error = true) 405 | { 406 | if (sync_PyrLKOpticalFlow.empty()) { 407 | std::cout << "sync_PyrLKOpticalFlow isn't initialized \n"; 408 | return cur_bbox_vec; 409 | } 410 | 411 | cv::cvtColor(new_dst_mat, dst_grey, CV_BGR2GRAY, 1); 412 | 413 | if (src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols) { 414 | src_grey = dst_grey.clone(); 415 | return cur_bbox_vec; 416 | } 417 | 418 | if (prev_pts_flow.cols < 1) { 419 | return cur_bbox_vec; 420 | } 421 | 422 | ////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 423 | sync_PyrLKOpticalFlow->calc(src_grey, dst_grey, prev_pts_flow, cur_pts_flow, status, err); // OpenCV 3.x 424 | 425 | dst_grey.copyTo(src_grey); 426 | 427 | std::vector result_bbox_vec; 428 | 429 | if (err.rows == cur_bbox_vec.size() && status.rows == cur_bbox_vec.size()) 430 | { 431 | for (size_t i = 0; i < cur_bbox_vec.size(); ++i) 432 | { 433 | cv::Point2f cur_key_pt = cur_pts_flow.at(0, i); 434 | cv::Point2f prev_key_pt = prev_pts_flow.at(0, i); 435 | 436 | float moved_x = cur_key_pt.x - prev_key_pt.x; 437 | float moved_y = cur_key_pt.y - prev_key_pt.y; 438 | 439 | if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i]) 440 | if (err.at(0, i) < flow_error && status.at(0, i) != 0 && 441 | ((float)cur_bbox_vec[i].x + moved_x) > 0 && ((float)cur_bbox_vec[i].y + moved_y) > 0) 442 | { 443 | cur_bbox_vec[i].x += moved_x + 0.5; 444 | cur_bbox_vec[i].y += moved_y + 0.5; 445 | result_bbox_vec.push_back(cur_bbox_vec[i]); 446 | } 447 | else good_bbox_vec_flags[i] = false; 448 | else good_bbox_vec_flags[i] = false; 449 | 450 | //if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]); 451 | } 452 | } 453 | 454 | prev_pts_flow = cur_pts_flow.clone(); 455 | 456 | return result_bbox_vec; 457 | } 458 | 459 | }; 460 | #else 461 | 462 | class Tracker_optflow {}; 463 | 464 | #endif // defined(TRACK_OPTFLOW) && defined(OPENCV) 465 | 466 | 467 | #ifdef OPENCV 468 | 469 | static cv::Scalar obj_id_to_color(int obj_id) { 470 | int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } }; 471 | int const offset = obj_id * 123457 % 6; 472 | int const color_scale = 150 + (obj_id * 123457) % 100; 473 | cv::Scalar color(colors[offset][0], colors[offset][1], colors[offset][2]); 474 | color *= color_scale; 475 | return color; 476 | } 477 | 478 | class preview_boxes_t { 479 | enum { frames_history = 30 }; // how long to keep the history saved 480 | 481 | struct preview_box_track_t { 482 | unsigned int track_id, obj_id, last_showed_frames_ago; 483 | bool current_detection; 484 | bbox_t bbox; 485 | cv::Mat mat_obj, mat_resized_obj; 486 | preview_box_track_t() : track_id(0), obj_id(0), last_showed_frames_ago(frames_history), current_detection(false) {} 487 | }; 488 | std::vector preview_box_track_id; 489 | size_t const preview_box_size, bottom_offset; 490 | bool const one_off_detections; 491 | public: 492 | preview_boxes_t(size_t _preview_box_size = 100, size_t _bottom_offset = 100, bool _one_off_detections = false) : 493 | preview_box_size(_preview_box_size), bottom_offset(_bottom_offset), one_off_detections(_one_off_detections) 494 | {} 495 | 496 | void set(cv::Mat src_mat, std::vector result_vec) 497 | { 498 | size_t const count_preview_boxes = src_mat.cols / preview_box_size; 499 | if (preview_box_track_id.size() != count_preview_boxes) preview_box_track_id.resize(count_preview_boxes); 500 | 501 | // increment frames history 502 | for (auto &i : preview_box_track_id) 503 | i.last_showed_frames_ago = std::min((unsigned)frames_history, i.last_showed_frames_ago + 1); 504 | 505 | // occupy empty boxes 506 | for (auto &k : result_vec) { 507 | bool found = false; 508 | // find the same (track_id) 509 | for (auto &i : preview_box_track_id) { 510 | if (i.track_id == k.track_id) { 511 | if (!one_off_detections) i.last_showed_frames_ago = 0; // for tracked objects 512 | found = true; 513 | break; 514 | } 515 | } 516 | if (!found) { 517 | // find empty box 518 | for (auto &i : preview_box_track_id) { 519 | if (i.last_showed_frames_ago == frames_history) { 520 | if (!one_off_detections && k.frames_counter == 0) break; // don't show if obj isn't tracked yet 521 | i.track_id = k.track_id; 522 | i.obj_id = k.obj_id; 523 | i.bbox = k; 524 | i.last_showed_frames_ago = 0; 525 | break; 526 | } 527 | } 528 | } 529 | } 530 | 531 | // draw preview box (from old or current frame) 532 | for (size_t i = 0; i < preview_box_track_id.size(); ++i) 533 | { 534 | // get object image 535 | cv::Mat dst = preview_box_track_id[i].mat_resized_obj; 536 | preview_box_track_id[i].current_detection = false; 537 | 538 | for (auto &k : result_vec) { 539 | if (preview_box_track_id[i].track_id == k.track_id) { 540 | if (one_off_detections && preview_box_track_id[i].last_showed_frames_ago > 0) { 541 | preview_box_track_id[i].last_showed_frames_ago = frames_history; break; 542 | } 543 | bbox_t b = k; 544 | cv::Rect r(b.x, b.y, b.w, b.h); 545 | cv::Rect img_rect(cv::Point2i(0, 0), src_mat.size()); 546 | cv::Rect rect_roi = r & img_rect; 547 | if (rect_roi.width > 1 || rect_roi.height > 1) { 548 | cv::Mat roi = src_mat(rect_roi); 549 | cv::resize(roi, dst, cv::Size(preview_box_size, preview_box_size), cv::INTER_NEAREST); 550 | preview_box_track_id[i].mat_obj = roi.clone(); 551 | preview_box_track_id[i].mat_resized_obj = dst.clone(); 552 | preview_box_track_id[i].current_detection = true; 553 | preview_box_track_id[i].bbox = k; 554 | } 555 | break; 556 | } 557 | } 558 | } 559 | } 560 | 561 | 562 | void draw(cv::Mat draw_mat, bool show_small_boxes = false) 563 | { 564 | // draw preview box (from old or current frame) 565 | for (size_t i = 0; i < preview_box_track_id.size(); ++i) 566 | { 567 | auto &prev_box = preview_box_track_id[i]; 568 | 569 | // draw object image 570 | cv::Mat dst = prev_box.mat_resized_obj; 571 | if (prev_box.last_showed_frames_ago < frames_history && 572 | dst.size() == cv::Size(preview_box_size, preview_box_size)) 573 | { 574 | cv::Rect dst_rect_roi(cv::Point2i(i * preview_box_size, draw_mat.rows - bottom_offset), dst.size()); 575 | cv::Mat dst_roi = draw_mat(dst_rect_roi); 576 | dst.copyTo(dst_roi); 577 | 578 | cv::Scalar color = obj_id_to_color(prev_box.obj_id); 579 | int thickness = (prev_box.current_detection) ? 5 : 1; 580 | cv::rectangle(draw_mat, dst_rect_roi, color, thickness); 581 | 582 | unsigned int const track_id = prev_box.track_id; 583 | std::string track_id_str = (track_id > 0) ? std::to_string(track_id) : ""; 584 | 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); 585 | 586 | std::string size_str = std::to_string(prev_box.bbox.w) + "x" + std::to_string(prev_box.bbox.h); 587 | 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); 588 | 589 | if (!one_off_detections && prev_box.current_detection) { 590 | cv::line(draw_mat, dst_rect_roi.tl() + cv::Point2i(preview_box_size, 0), 591 | cv::Point2i(prev_box.bbox.x, prev_box.bbox.y + prev_box.bbox.h), 592 | color); 593 | } 594 | 595 | if (one_off_detections && show_small_boxes) { 596 | cv::Rect src_rect_roi(cv::Point2i(prev_box.bbox.x, prev_box.bbox.y), 597 | cv::Size(prev_box.bbox.w, prev_box.bbox.h)); 598 | unsigned int const color_history = (255 * prev_box.last_showed_frames_ago) / frames_history; 599 | color = cv::Scalar(255 - 3 * color_history, 255 - 2 * color_history, 255 - 1 * color_history); 600 | if (prev_box.mat_obj.size() == src_rect_roi.size()) { 601 | prev_box.mat_obj.copyTo(draw_mat(src_rect_roi)); 602 | } 603 | cv::rectangle(draw_mat, src_rect_roi, color, thickness); 604 | 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); 605 | } 606 | } 607 | } 608 | } 609 | }; 610 | #endif // OPENCV 611 | 612 | //extern "C" { 613 | #endif // __cplusplus 614 | 615 | /* 616 | // C - wrappers 617 | YOLODLL_API void create_detector(char const* cfg_filename, char const* weight_filename, int gpu_id); 618 | YOLODLL_API void delete_detector(); 619 | YOLODLL_API bbox_t* detect_custom(image_t img, float thresh, bool use_mean, int *result_size); 620 | YOLODLL_API bbox_t* detect_resized(image_t img, int init_w, int init_h, float thresh, bool use_mean, int *result_size); 621 | YOLODLL_API bbox_t* detect(image_t img, int *result_size); 622 | YOLODLL_API image_t load_img(char *image_filename); 623 | YOLODLL_API void free_img(image_t m); 624 | 625 | #ifdef __cplusplus 626 | } // extern "C" 627 | 628 | static std::shared_ptr c_detector_ptr; 629 | static std::vector c_result_vec; 630 | 631 | void create_detector(char const* cfg_filename, char const* weight_filename, int gpu_id) { 632 | c_detector_ptr = std::make_shared(cfg_filename, weight_filename, gpu_id); 633 | } 634 | 635 | void delete_detector() { c_detector_ptr.reset(); } 636 | 637 | bbox_t* detect_custom(image_t img, float thresh, bool use_mean, int *result_size) { 638 | c_result_vec = static_cast(c_detector_ptr.get())->detect(img, thresh, use_mean); 639 | *result_size = c_result_vec.size(); 640 | return c_result_vec.data(); 641 | } 642 | 643 | bbox_t* detect_resized(image_t img, int init_w, int init_h, float thresh, bool use_mean, int *result_size) { 644 | c_result_vec = static_cast(c_detector_ptr.get())->detect_resized(img, init_w, init_h, thresh, use_mean); 645 | *result_size = c_result_vec.size(); 646 | return c_result_vec.data(); 647 | } 648 | 649 | bbox_t* detect(image_t img, int *result_size) { 650 | return detect_custom(img, 0.24, true, result_size); 651 | } 652 | 653 | image_t load_img(char *image_filename) { 654 | return static_cast(c_detector_ptr.get())->load_image(image_filename); 655 | } 656 | void free_img(image_t m) { 657 | static_cast(c_detector_ptr.get())->free_image(m); 658 | } 659 | 660 | #endif // __cplusplus 661 | */ 662 | -------------------------------------------------------------------------------- /yolo_TM/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(detect) 4 | 5 | SET(CMAKE_C_COMPILER g++) 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | add_compile_options(-std=c++11) 8 | message(STATUS "optional:-std=c++11") 9 | endif(CMAKE_COMPILER_IS_GNUCXX) 10 | 11 | find_package(OpenCV REQUIRED) 12 | 13 | message(STATUS "OpenCV library status:") 14 | message(STATUS " version: ${OpenCV_VERSION}") 15 | message(STATUS " libraries: ${OpenCV_LIBS}") 16 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 17 | 18 | if(CMAKE_VERSION VERSION_LESS "2.8.11") 19 | include_directories(${OpenCV_INCLUDE_DIRS}) 20 | endif() 21 | 22 | 23 | file(GLOB SRCS ./src/*.cpp) 24 | file(GLOB HDRS ./src/*.h*) 25 | 26 | set(traincascade_files ${SRCS} ${HDRS}) 27 | 28 | add_executable(detect ${traincascade_files}) 29 | 30 | # include_directories(./src) 31 | 32 | target_link_libraries(detect ${OpenCV_LIBS} libdarknet.so) 33 | -------------------------------------------------------------------------------- /yolo_TM/build/cfg/yolov3-head.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | # batch=1 4 | # subdivisions=1 5 | # Training 6 | batch=64 7 | subdivisions=8 8 | width=192 9 | height=192 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.001 19 | burn_in=1000 20 | max_batches = 650200 21 | policy=steps 22 | steps=550000,600000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=32 28 | size=3 29 | stride=1 30 | pad=1 31 | activation=leaky 32 | 33 | # Downsample 34 | 35 | [convolutional] 36 | batch_normalize=1 37 | filters=64 38 | size=3 39 | stride=2 40 | pad=1 41 | activation=leaky 42 | 43 | [convolutional] 44 | batch_normalize=1 45 | filters=32 46 | size=1 47 | stride=1 48 | pad=1 49 | activation=leaky 50 | 51 | [convolutional] 52 | batch_normalize=1 53 | filters=64 54 | size=3 55 | stride=1 56 | pad=1 57 | activation=leaky 58 | 59 | [shortcut] 60 | from=-3 61 | activation=linear 62 | 63 | # Downsample 64 | 65 | [convolutional] 66 | batch_normalize=1 67 | filters=128 68 | size=3 69 | stride=2 70 | pad=1 71 | activation=leaky 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=64 76 | size=1 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [convolutional] 82 | batch_normalize=1 83 | filters=128 84 | size=3 85 | stride=1 86 | pad=1 87 | activation=leaky 88 | 89 | [shortcut] 90 | from=-3 91 | activation=linear 92 | 93 | [convolutional] 94 | batch_normalize=1 95 | filters=64 96 | size=1 97 | stride=1 98 | pad=1 99 | activation=leaky 100 | 101 | [convolutional] 102 | batch_normalize=1 103 | filters=128 104 | size=3 105 | stride=1 106 | pad=1 107 | activation=leaky 108 | 109 | [shortcut] 110 | from=-3 111 | activation=linear 112 | 113 | # Downsample 114 | 115 | [convolutional] 116 | batch_normalize=1 117 | filters=256 118 | size=3 119 | stride=2 120 | pad=1 121 | activation=leaky 122 | 123 | [convolutional] 124 | batch_normalize=1 125 | filters=128 126 | size=1 127 | stride=1 128 | pad=1 129 | activation=leaky 130 | 131 | [convolutional] 132 | batch_normalize=1 133 | filters=256 134 | size=3 135 | stride=1 136 | pad=1 137 | activation=leaky 138 | 139 | [shortcut] 140 | from=-3 141 | activation=linear 142 | 143 | [convolutional] 144 | batch_normalize=1 145 | filters=128 146 | size=1 147 | stride=1 148 | pad=1 149 | activation=leaky 150 | 151 | [convolutional] 152 | batch_normalize=1 153 | filters=256 154 | size=3 155 | stride=1 156 | pad=1 157 | activation=leaky 158 | 159 | [shortcut] 160 | from=-3 161 | activation=linear 162 | 163 | [convolutional] 164 | batch_normalize=1 165 | filters=128 166 | size=1 167 | stride=1 168 | pad=1 169 | activation=leaky 170 | 171 | [convolutional] 172 | batch_normalize=1 173 | filters=256 174 | size=3 175 | stride=1 176 | pad=1 177 | activation=leaky 178 | 179 | [shortcut] 180 | from=-3 181 | activation=linear 182 | 183 | [convolutional] 184 | batch_normalize=1 185 | filters=128 186 | size=1 187 | stride=1 188 | pad=1 189 | activation=leaky 190 | 191 | [convolutional] 192 | batch_normalize=1 193 | filters=256 194 | size=3 195 | stride=1 196 | pad=1 197 | activation=leaky 198 | 199 | [shortcut] 200 | from=-3 201 | activation=linear 202 | 203 | 204 | [convolutional] 205 | batch_normalize=1 206 | filters=128 207 | size=1 208 | stride=1 209 | pad=1 210 | activation=leaky 211 | 212 | [convolutional] 213 | batch_normalize=1 214 | filters=256 215 | size=3 216 | stride=1 217 | pad=1 218 | activation=leaky 219 | 220 | [shortcut] 221 | from=-3 222 | activation=linear 223 | 224 | [convolutional] 225 | batch_normalize=1 226 | filters=128 227 | size=1 228 | stride=1 229 | pad=1 230 | activation=leaky 231 | 232 | [convolutional] 233 | batch_normalize=1 234 | filters=256 235 | size=3 236 | stride=1 237 | pad=1 238 | activation=leaky 239 | 240 | [shortcut] 241 | from=-3 242 | activation=linear 243 | 244 | [convolutional] 245 | batch_normalize=1 246 | filters=128 247 | size=1 248 | stride=1 249 | pad=1 250 | activation=leaky 251 | 252 | [convolutional] 253 | batch_normalize=1 254 | filters=256 255 | size=3 256 | stride=1 257 | pad=1 258 | activation=leaky 259 | 260 | [shortcut] 261 | from=-3 262 | activation=linear 263 | 264 | [convolutional] 265 | batch_normalize=1 266 | filters=128 267 | size=1 268 | stride=1 269 | pad=1 270 | activation=leaky 271 | 272 | [convolutional] 273 | batch_normalize=1 274 | filters=256 275 | size=3 276 | stride=1 277 | pad=1 278 | activation=leaky 279 | 280 | [shortcut] 281 | from=-3 282 | activation=linear 283 | 284 | # Downsample 285 | 286 | [convolutional] 287 | batch_normalize=1 288 | filters=512 289 | size=3 290 | stride=2 291 | pad=1 292 | activation=leaky 293 | 294 | [convolutional] 295 | batch_normalize=1 296 | filters=256 297 | size=1 298 | stride=1 299 | pad=1 300 | activation=leaky 301 | 302 | [convolutional] 303 | batch_normalize=1 304 | filters=512 305 | size=3 306 | stride=1 307 | pad=1 308 | activation=leaky 309 | 310 | [shortcut] 311 | from=-3 312 | activation=linear 313 | 314 | 315 | [convolutional] 316 | batch_normalize=1 317 | filters=256 318 | size=1 319 | stride=1 320 | pad=1 321 | activation=leaky 322 | 323 | [convolutional] 324 | batch_normalize=1 325 | filters=512 326 | size=3 327 | stride=1 328 | pad=1 329 | activation=leaky 330 | 331 | [shortcut] 332 | from=-3 333 | activation=linear 334 | 335 | 336 | [convolutional] 337 | batch_normalize=1 338 | filters=256 339 | size=1 340 | stride=1 341 | pad=1 342 | activation=leaky 343 | 344 | [convolutional] 345 | batch_normalize=1 346 | filters=512 347 | size=3 348 | stride=1 349 | pad=1 350 | activation=leaky 351 | 352 | [shortcut] 353 | from=-3 354 | activation=linear 355 | 356 | 357 | [convolutional] 358 | batch_normalize=1 359 | filters=256 360 | size=1 361 | stride=1 362 | pad=1 363 | activation=leaky 364 | 365 | [convolutional] 366 | batch_normalize=1 367 | filters=512 368 | size=3 369 | stride=1 370 | pad=1 371 | activation=leaky 372 | 373 | [shortcut] 374 | from=-3 375 | activation=linear 376 | 377 | [convolutional] 378 | batch_normalize=1 379 | filters=256 380 | size=1 381 | stride=1 382 | pad=1 383 | activation=leaky 384 | 385 | [convolutional] 386 | batch_normalize=1 387 | filters=512 388 | size=3 389 | stride=1 390 | pad=1 391 | activation=leaky 392 | 393 | [shortcut] 394 | from=-3 395 | activation=linear 396 | 397 | 398 | [convolutional] 399 | batch_normalize=1 400 | filters=256 401 | size=1 402 | stride=1 403 | pad=1 404 | activation=leaky 405 | 406 | [convolutional] 407 | batch_normalize=1 408 | filters=512 409 | size=3 410 | stride=1 411 | pad=1 412 | activation=leaky 413 | 414 | [shortcut] 415 | from=-3 416 | activation=linear 417 | 418 | 419 | [convolutional] 420 | batch_normalize=1 421 | filters=256 422 | size=1 423 | stride=1 424 | pad=1 425 | activation=leaky 426 | 427 | [convolutional] 428 | batch_normalize=1 429 | filters=512 430 | size=3 431 | stride=1 432 | pad=1 433 | activation=leaky 434 | 435 | [shortcut] 436 | from=-3 437 | activation=linear 438 | 439 | [convolutional] 440 | batch_normalize=1 441 | filters=256 442 | size=1 443 | stride=1 444 | pad=1 445 | activation=leaky 446 | 447 | [convolutional] 448 | batch_normalize=1 449 | filters=512 450 | size=3 451 | stride=1 452 | pad=1 453 | activation=leaky 454 | 455 | [shortcut] 456 | from=-3 457 | activation=linear 458 | 459 | # Downsample 460 | 461 | [convolutional] 462 | batch_normalize=1 463 | filters=1024 464 | size=3 465 | stride=2 466 | pad=1 467 | activation=leaky 468 | 469 | [convolutional] 470 | batch_normalize=1 471 | filters=512 472 | size=1 473 | stride=1 474 | pad=1 475 | activation=leaky 476 | 477 | [convolutional] 478 | batch_normalize=1 479 | filters=1024 480 | size=3 481 | stride=1 482 | pad=1 483 | activation=leaky 484 | 485 | [shortcut] 486 | from=-3 487 | activation=linear 488 | 489 | [convolutional] 490 | batch_normalize=1 491 | filters=512 492 | size=1 493 | stride=1 494 | pad=1 495 | activation=leaky 496 | 497 | [convolutional] 498 | batch_normalize=1 499 | filters=1024 500 | size=3 501 | stride=1 502 | pad=1 503 | activation=leaky 504 | 505 | [shortcut] 506 | from=-3 507 | activation=linear 508 | 509 | [convolutional] 510 | batch_normalize=1 511 | filters=512 512 | size=1 513 | stride=1 514 | pad=1 515 | activation=leaky 516 | 517 | [convolutional] 518 | batch_normalize=1 519 | filters=1024 520 | size=3 521 | stride=1 522 | pad=1 523 | activation=leaky 524 | 525 | [shortcut] 526 | from=-3 527 | activation=linear 528 | 529 | [convolutional] 530 | batch_normalize=1 531 | filters=512 532 | size=1 533 | stride=1 534 | pad=1 535 | activation=leaky 536 | 537 | [convolutional] 538 | batch_normalize=1 539 | filters=1024 540 | size=3 541 | stride=1 542 | pad=1 543 | activation=leaky 544 | stopbackward=1 545 | 546 | [shortcut] 547 | from=-3 548 | activation=linear 549 | 550 | ###################### 551 | 552 | [convolutional] 553 | batch_normalize=1 554 | filters=512 555 | size=1 556 | stride=1 557 | pad=1 558 | activation=leaky 559 | 560 | [convolutional] 561 | batch_normalize=1 562 | size=3 563 | stride=1 564 | pad=1 565 | filters=1024 566 | activation=leaky 567 | 568 | [convolutional] 569 | batch_normalize=1 570 | filters=512 571 | size=1 572 | stride=1 573 | pad=1 574 | activation=leaky 575 | 576 | [convolutional] 577 | batch_normalize=1 578 | size=3 579 | stride=1 580 | pad=1 581 | filters=1024 582 | activation=leaky 583 | 584 | [convolutional] 585 | batch_normalize=1 586 | filters=512 587 | size=1 588 | stride=1 589 | pad=1 590 | activation=leaky 591 | 592 | [convolutional] 593 | batch_normalize=1 594 | size=3 595 | stride=1 596 | pad=1 597 | filters=1024 598 | activation=leaky 599 | 600 | 601 | [convolutional] 602 | size=1 603 | stride=1 604 | pad=1 605 | filters=18 606 | activation=linear 607 | 608 | 609 | [yolo] 610 | mask = 6,7,8 611 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 612 | classes=1 613 | num=9 614 | jitter=.3 615 | ignore_thresh = .5 616 | truth_thresh = 1 617 | random=1 618 | 619 | 620 | [route] 621 | layers = -4 622 | 623 | [convolutional] 624 | batch_normalize=1 625 | filters=256 626 | size=1 627 | stride=1 628 | pad=1 629 | activation=leaky 630 | 631 | [upsample] 632 | stride=2 633 | 634 | [route] 635 | layers = -1, 61 636 | 637 | 638 | 639 | [convolutional] 640 | batch_normalize=1 641 | filters=256 642 | size=1 643 | stride=1 644 | pad=1 645 | activation=leaky 646 | 647 | [convolutional] 648 | batch_normalize=1 649 | size=3 650 | stride=1 651 | pad=1 652 | filters=512 653 | activation=leaky 654 | 655 | [convolutional] 656 | batch_normalize=1 657 | filters=256 658 | size=1 659 | stride=1 660 | pad=1 661 | activation=leaky 662 | 663 | [convolutional] 664 | batch_normalize=1 665 | size=3 666 | stride=1 667 | pad=1 668 | filters=512 669 | activation=leaky 670 | 671 | [convolutional] 672 | batch_normalize=1 673 | filters=256 674 | size=1 675 | stride=1 676 | pad=1 677 | activation=leaky 678 | 679 | [convolutional] 680 | batch_normalize=1 681 | size=3 682 | stride=1 683 | pad=1 684 | filters=512 685 | activation=leaky 686 | 687 | [convolutional] 688 | size=1 689 | stride=1 690 | pad=1 691 | filters=18 692 | activation=linear 693 | 694 | 695 | [yolo] 696 | mask = 3,4,5 697 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 698 | classes=1 699 | num=9 700 | jitter=.3 701 | ignore_thresh = .5 702 | truth_thresh = 1 703 | random=1 704 | 705 | 706 | 707 | [route] 708 | layers = -4 709 | 710 | [convolutional] 711 | batch_normalize=1 712 | filters=128 713 | size=1 714 | stride=1 715 | pad=1 716 | activation=leaky 717 | 718 | [upsample] 719 | stride=2 720 | 721 | [route] 722 | layers = -1, 36 723 | 724 | 725 | 726 | [convolutional] 727 | batch_normalize=1 728 | filters=128 729 | size=1 730 | stride=1 731 | pad=1 732 | activation=leaky 733 | 734 | [convolutional] 735 | batch_normalize=1 736 | size=3 737 | stride=1 738 | pad=1 739 | filters=256 740 | activation=leaky 741 | 742 | [convolutional] 743 | batch_normalize=1 744 | filters=128 745 | size=1 746 | stride=1 747 | pad=1 748 | activation=leaky 749 | 750 | [convolutional] 751 | batch_normalize=1 752 | size=3 753 | stride=1 754 | pad=1 755 | filters=256 756 | activation=leaky 757 | 758 | [convolutional] 759 | batch_normalize=1 760 | filters=128 761 | size=1 762 | stride=1 763 | pad=1 764 | activation=leaky 765 | 766 | [convolutional] 767 | batch_normalize=1 768 | size=3 769 | stride=1 770 | pad=1 771 | filters=256 772 | activation=leaky 773 | 774 | [convolutional] 775 | size=1 776 | stride=1 777 | pad=1 778 | filters=18 779 | activation=linear 780 | 781 | 782 | [yolo] 783 | mask = 0,1,2 784 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 785 | classes=1 786 | num=9 787 | jitter=.3 788 | ignore_thresh = .5 789 | truth_thresh = 1 790 | random=1 791 | 792 | -------------------------------------------------------------------------------- /yolo_TM/build/cfg/yolov3-tiny.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | batch=1 4 | subdivisions=1 5 | # Training 6 | # batch=64 7 | # subdivisions=2 8 | width=416 9 | height=416 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.001 19 | burn_in=1000 20 | max_batches = 500200 21 | policy=steps 22 | steps=400000,450000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=16 28 | size=3 29 | stride=1 30 | pad=1 31 | activation=leaky 32 | 33 | [maxpool] 34 | size=2 35 | stride=2 36 | 37 | [convolutional] 38 | batch_normalize=1 39 | filters=32 40 | size=3 41 | stride=1 42 | pad=1 43 | activation=leaky 44 | 45 | [maxpool] 46 | size=2 47 | stride=2 48 | 49 | [convolutional] 50 | batch_normalize=1 51 | filters=64 52 | size=3 53 | stride=1 54 | pad=1 55 | activation=leaky 56 | 57 | [maxpool] 58 | size=2 59 | stride=2 60 | 61 | [convolutional] 62 | batch_normalize=1 63 | filters=128 64 | size=3 65 | stride=1 66 | pad=1 67 | activation=leaky 68 | 69 | [maxpool] 70 | size=2 71 | stride=2 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=256 76 | size=3 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [maxpool] 82 | size=2 83 | stride=2 84 | 85 | [convolutional] 86 | batch_normalize=1 87 | filters=512 88 | size=3 89 | stride=1 90 | pad=1 91 | activation=leaky 92 | 93 | [maxpool] 94 | size=2 95 | stride=1 96 | 97 | [convolutional] 98 | batch_normalize=1 99 | filters=1024 100 | size=3 101 | stride=1 102 | pad=1 103 | activation=leaky 104 | 105 | ########### 106 | 107 | [convolutional] 108 | batch_normalize=1 109 | filters=256 110 | size=1 111 | stride=1 112 | pad=1 113 | activation=leaky 114 | 115 | [convolutional] 116 | batch_normalize=1 117 | filters=512 118 | size=3 119 | stride=1 120 | pad=1 121 | activation=leaky 122 | 123 | [convolutional] 124 | size=1 125 | stride=1 126 | pad=1 127 | filters=255 128 | activation=linear 129 | 130 | 131 | 132 | [yolo] 133 | mask = 3,4,5 134 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 135 | classes=80 136 | num=6 137 | jitter=.3 138 | ignore_thresh = .7 139 | truth_thresh = 1 140 | random=1 141 | 142 | [route] 143 | layers = -4 144 | 145 | [convolutional] 146 | batch_normalize=1 147 | filters=128 148 | size=1 149 | stride=1 150 | pad=1 151 | activation=leaky 152 | 153 | [upsample] 154 | stride=2 155 | 156 | [route] 157 | layers = -1, 8 158 | 159 | [convolutional] 160 | batch_normalize=1 161 | filters=256 162 | size=3 163 | stride=1 164 | pad=1 165 | activation=leaky 166 | 167 | [convolutional] 168 | size=1 169 | stride=1 170 | pad=1 171 | filters=255 172 | activation=linear 173 | 174 | [yolo] 175 | mask = 1,2,3 176 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 177 | classes=80 178 | num=6 179 | jitter=.3 180 | ignore_thresh = .7 181 | truth_thresh = 1 182 | random=1 183 | -------------------------------------------------------------------------------- /yolo_TM/build/detect: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TLMichael/Detect-Track/861bb7e9021202efd4a6c491fa6388ddc602a718/yolo_TM/build/detect -------------------------------------------------------------------------------- /yolo_TM/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utils.h" 3 | 4 | using namespace std; 5 | using namespace cv; 6 | 7 | bool show_visualization = true; //控制imshow的显示功能 8 | 9 | int main() 10 | { 11 | string cfgDir = "cfg/yolov3-head.cfg"; 12 | string weightDir = "cfg/yolov3-head.weights"; 13 | Detector detector(cfgDir, weightDir); 14 | Template tracker; 15 | 16 | VideoCapture capture; 17 | // capture.open( "http://192.168.0.6:8080/video" ); 18 | capture.open( 0 ); 19 | if(!capture.isOpened()) 20 | { 21 | cout << " --(!) Fail to open camera -- Exit!" << endl; 22 | exit(0); 23 | } 24 | 25 | 26 | TickMeter meter; 27 | Mat frame; 28 | Mat frameShow; 29 | 30 | int status = 0; // 0:没有目标,1:找到目标进行跟踪 31 | Rect location; 32 | 33 | while( capture.read(frame) ) 34 | { 35 | if(frame.empty()) 36 | { 37 | cout << " --(!) No captured frame -- Break!" << endl; 38 | break; 39 | } 40 | // resize(frame, frame, Size(640, 480)); 41 | cv::putText(frame, GetCurrentTime2(), cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); 42 | frameShow = frame.clone(); 43 | 44 | meter.start(); 45 | if(status == 0) 46 | { 47 | vector results = detector.detect(frame, 0.15); 48 | vector persons = person_filter(results); 49 | if(persons.size() > 0) 50 | { 51 | cout << "[debug] " << meter.getCounter() << ": " << "persons: " << persons.size() << endl; 52 | for(size_t i = 0; i < persons.size(); i++) 53 | rectangle( frameShow, persons[i], Scalar(20, 20, 20), 1, 8, 0); 54 | location = max_filter(persons); 55 | rectangle(frameShow, location, Scalar(0, 128, 255), 2); 56 | 57 | tracker.initTracking(frame, location); 58 | status = 1; 59 | cout << "[debug] " << meter.getCounter() << ": " << "开始跟踪" << endl; 60 | } 61 | } 62 | else if(status == 1) 63 | { 64 | if( meter.getCounter() % 3 != 0 ) 65 | { 66 | location = tracker.track(frame); 67 | limitRect(location, frame.size()); 68 | if(location.area() == 0) 69 | status = 0; 70 | } 71 | else 72 | { 73 | vector results = detector.detect(frame, 0.15); 74 | vector persons = person_filter(results); 75 | if(persons.size() == 0) 76 | status = 0; 77 | else 78 | { 79 | location = max_filter(persons); 80 | tracker.initTracking(frame, location); 81 | } 82 | } 83 | if(status == 1) 84 | { 85 | cout << "[loc: " << location.x << " " << location.y << " " << location.width << " " << location.height << "]\n"; 86 | rectangle(frameShow, location, Scalar(0, 128, 255), 2); 87 | } 88 | } 89 | 90 | if(show_visualization) 91 | { 92 | imshow("YinFeiLin", frameShow); 93 | char key = waitKey(1); 94 | if (key == 27 || key == 'q' || key == 'Q') 95 | break; 96 | } 97 | 98 | meter.stop(); 99 | } 100 | 101 | double fps = double(meter.getCounter()) / meter.getTimeSec(); 102 | cout << "[YinFeiLin] " << "fps: " << fps << endl; 103 | 104 | return 0; 105 | } -------------------------------------------------------------------------------- /yolo_TM/src/template.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | using namespace cv; 5 | 6 | class Template{ 7 | public: 8 | Template(); 9 | void initTracking(Mat frame, Rect box, int scale = 5); 10 | Rect track(Mat frame); 11 | Rect getLocation(); 12 | private: 13 | Mat model; 14 | Rect location; 15 | int scale; 16 | }; 17 | 18 | Template::Template() 19 | { 20 | this->scale = 5; 21 | } 22 | 23 | void Template::initTracking(Mat frame, Rect box, int scale) 24 | { 25 | this->location = box; 26 | this->scale = scale; 27 | this->location &= Rect(0, 0, frame.cols, frame.rows); 28 | 29 | if(frame.empty()) 30 | { 31 | cout << "ERROR: frame is empty." << endl; 32 | exit(0); 33 | } 34 | if(frame.channels() != 1) 35 | { 36 | cvtColor(frame, frame, CV_RGB2GRAY); 37 | } 38 | this->model = frame(this->location); 39 | } 40 | 41 | Rect Template::track(Mat frame) 42 | { 43 | if(frame.empty()) 44 | { 45 | cout << "ERROR: frame is empty." << endl; 46 | exit(0); 47 | } 48 | Mat gray; 49 | if(frame.channels() != 1) 50 | { 51 | cvtColor(frame, gray, CV_RGB2GRAY); 52 | } 53 | 54 | Rect searchWindow; 55 | searchWindow.width = this->location.width * scale; 56 | searchWindow.height = this->location.height * scale; 57 | searchWindow.x = this->location.x + this->location.width * 0.5 58 | - searchWindow.width * 0.5; 59 | searchWindow.y = this->location.y + this->location.height * 0.5 60 | - searchWindow.height * 0.5; 61 | 62 | if(searchWindow.x < 0) 63 | searchWindow.x = 0; 64 | if(searchWindow.y < 0) 65 | searchWindow.y = 0; 66 | searchWindow &= Rect(0, 0, frame.cols, frame.rows); 67 | 68 | Mat similarity; 69 | matchTemplate(gray(searchWindow), this->model, similarity, CV_TM_CCOEFF_NORMED); 70 | double mag_r; 71 | Point point; 72 | minMaxLoc(similarity, 0, &mag_r, 0, &point); 73 | this->location.x = point.x + searchWindow.x; 74 | this->location.y = point.y + searchWindow.y; 75 | 76 | this->model = gray(location); 77 | return this->location; 78 | } 79 | 80 | Rect Template::getLocation() 81 | { 82 | return this->location; 83 | } -------------------------------------------------------------------------------- /yolo_TM/src/utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "template.h" 11 | #include "yolo_v2_class.hpp" 12 | 13 | vector person_filter(vector results) 14 | { 15 | vector persons; 16 | for(size_t i = 0; i < results.size(); i++) 17 | { 18 | if( results[i].obj_id == 0 ) 19 | { 20 | Rect box; 21 | box.x = results[i].x; 22 | box.y = results[i].y; 23 | box.width = results[i].w; 24 | box.height = results[i].h; 25 | persons.push_back(box); 26 | } 27 | } 28 | return persons; 29 | } 30 | 31 | Rect max_filter(vector persons) 32 | { 33 | int max_aera = persons[0].area(); 34 | int max_index = 0; 35 | for(size_t i = 1; i < persons.size(); i++) 36 | { 37 | int area = persons[i].area(); 38 | if(area > max_aera) 39 | { 40 | max_aera = area; 41 | max_index = i; 42 | } 43 | } 44 | return persons[max_index]; 45 | } 46 | 47 | void limitRect(cv::Rect &location, cv::Size sz) 48 | { 49 | cv::Rect window(cv::Point(0, 0), sz); 50 | location = location & window; 51 | } 52 | 53 | string IntToString(int value) 54 | { 55 | ostringstream convert; 56 | convert << value; 57 | return convert.str(); 58 | } 59 | 60 | string GetCurrentTime() 61 | { 62 | time_t Time = time(NULL); 63 | tm* LocalTime = localtime(&Time); 64 | string Result; 65 | 66 | // add the year 67 | Result += IntToString(LocalTime->tm_year + 1900) + "-"; 68 | // add the month 69 | Result += IntToString(LocalTime->tm_mon + 1) + "-"; 70 | // add the day 71 | Result += IntToString(LocalTime->tm_mday) + "_"; 72 | // add the hour 73 | Result += IntToString(LocalTime->tm_hour) + "-"; 74 | // add the minutes 75 | Result += IntToString(LocalTime->tm_min) + "-"; 76 | // add the seconds 77 | Result += IntToString(LocalTime->tm_sec); 78 | 79 | return Result; 80 | } 81 | 82 | string GetCurrentTime2() 83 | { 84 | time_t Time = time(NULL); 85 | tm* LocalTime = localtime(&Time); 86 | string Result; 87 | 88 | // add the year 89 | Result += IntToString(LocalTime->tm_year + 1900) + "-"; 90 | // add the month 91 | Result += IntToString(LocalTime->tm_mon + 1) + "-"; 92 | // add the day 93 | Result += IntToString(LocalTime->tm_mday) + " "; 94 | // add the hour 95 | Result += IntToString(LocalTime->tm_hour) + ":"; 96 | // add the minutes 97 | Result += IntToString(LocalTime->tm_min) + ":"; 98 | // add the seconds 99 | Result += IntToString(LocalTime->tm_sec); 100 | 101 | return Result; 102 | } -------------------------------------------------------------------------------- /yolo_TM/src/yolo_v2_class.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifdef YOLODLL_EXPORTS 3 | #if defined(_MSC_VER) 4 | #define YOLODLL_API __declspec(dllexport) 5 | #else 6 | #define YOLODLL_API __attribute__((visibility("default"))) 7 | #endif 8 | #else 9 | #if defined(_MSC_VER) 10 | #define YOLODLL_API __declspec(dllimport) 11 | #else 12 | #define YOLODLL_API 13 | #endif 14 | #endif 15 | 16 | struct bbox_t { 17 | unsigned int x, y, w, h; // (x,y) - top-left corner, (w, h) - width & height of bounded box 18 | float prob; // confidence - probability that the object was found correctly 19 | unsigned int obj_id; // class of object - from range [0, classes-1] 20 | unsigned int track_id; // tracking id for video (0 - untracked, 1 - inf - tracked object) 21 | unsigned int frames_counter;// counter of frames on which the object was detected 22 | }; 23 | 24 | struct image_t { 25 | int h; // height 26 | int w; // width 27 | int c; // number of chanels (3 - for RGB) 28 | float *data; // pointer to the image data 29 | }; 30 | 31 | #define C_SHARP_MAX_OBJECTS 1000 32 | struct bbox_t_container { 33 | bbox_t candidates[C_SHARP_MAX_OBJECTS]; 34 | }; 35 | 36 | #ifdef __cplusplus 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #ifdef OPENCV 43 | #include // C++ 44 | #include "opencv2/highgui/highgui_c.h" // C 45 | #include "opencv2/imgproc/imgproc_c.h" // C 46 | #endif // OPENCV 47 | 48 | extern "C" YOLODLL_API int init(const char *configurationFilename, const char *weightsFilename, int gpu); 49 | extern "C" YOLODLL_API int detect_image(const char *filename, bbox_t_container &container); 50 | extern "C" YOLODLL_API int detect_mat(const uint8_t* data, const size_t data_length, bbox_t_container &container); 51 | extern "C" YOLODLL_API int dispose(); 52 | extern "C" YOLODLL_API int get_device_count(); 53 | extern "C" YOLODLL_API int get_device_name(int gpu, char* deviceName); 54 | 55 | class Detector { 56 | std::shared_ptr detector_gpu_ptr; 57 | std::deque> prev_bbox_vec_deque; 58 | const int cur_gpu_id; 59 | public: 60 | float nms = .4; 61 | bool wait_stream; 62 | 63 | YOLODLL_API Detector(std::string cfg_filename, std::string weight_filename, int gpu_id = 0); 64 | YOLODLL_API ~Detector(); 65 | 66 | YOLODLL_API std::vector detect(std::string image_filename, float thresh = 0.2, bool use_mean = false); 67 | YOLODLL_API std::vector detect(image_t img, float thresh = 0.2, bool use_mean = false); 68 | static YOLODLL_API image_t load_image(std::string image_filename); 69 | static YOLODLL_API void free_image(image_t m); 70 | YOLODLL_API int get_net_width() const; 71 | YOLODLL_API int get_net_height() const; 72 | YOLODLL_API int get_net_color_depth() const; 73 | 74 | YOLODLL_API std::vector tracking_id(std::vector cur_bbox_vec, bool const change_history = true, 75 | int const frames_story = 10, int const max_dist = 150); 76 | 77 | std::vector detect_resized(image_t img, int init_w, int init_h, float thresh = 0.2, bool use_mean = false) 78 | { 79 | if (img.data == NULL) 80 | throw std::runtime_error("Image is empty"); 81 | auto detection_boxes = detect(img, thresh, use_mean); 82 | float wk = (float)init_w / img.w, hk = (float)init_h / img.h; 83 | for (auto &i : detection_boxes) i.x *= wk, i.w *= wk, i.y *= hk, i.h *= hk; 84 | return detection_boxes; 85 | } 86 | 87 | #define OPENCV 88 | #ifdef OPENCV 89 | std::vector detect(cv::Mat mat, float thresh = 0.2, bool use_mean = false) 90 | { 91 | if(mat.data == NULL) 92 | throw std::runtime_error("Image is empty"); 93 | auto image_ptr = mat_to_image_resize(mat); 94 | return detect_resized(*image_ptr, mat.cols, mat.rows, thresh, use_mean); 95 | } 96 | 97 | std::shared_ptr mat_to_image_resize(cv::Mat mat) const 98 | { 99 | if (mat.data == NULL) return std::shared_ptr(NULL); 100 | 101 | cv::Size network_size = cv::Size(get_net_width(), get_net_height()); 102 | cv::Mat det_mat; 103 | if (mat.size() != network_size) 104 | cv::resize(mat, det_mat, network_size); 105 | else 106 | det_mat = mat; // only reference is copied 107 | 108 | return mat_to_image(det_mat); 109 | } 110 | 111 | static std::shared_ptr mat_to_image(cv::Mat img_src) 112 | { 113 | cv::Mat img; 114 | cv::cvtColor(img_src, img, cv::COLOR_RGB2BGR); 115 | std::shared_ptr image_ptr(new image_t, [](image_t *img) { free_image(*img); delete img; }); 116 | std::shared_ptr ipl_small = std::make_shared(img); 117 | *image_ptr = ipl_to_image(ipl_small.get()); 118 | return image_ptr; 119 | } 120 | 121 | private: 122 | 123 | static image_t ipl_to_image(IplImage* src) 124 | { 125 | unsigned char *data = (unsigned char *)src->imageData; 126 | int h = src->height; 127 | int w = src->width; 128 | int c = src->nChannels; 129 | int step = src->widthStep; 130 | image_t out = make_image_custom(w, h, c); 131 | int count = 0; 132 | 133 | for (int k = 0; k < c; ++k) { 134 | for (int i = 0; i < h; ++i) { 135 | int i_step = i*step; 136 | for (int j = 0; j < w; ++j) { 137 | out.data[count++] = data[i_step + j*c + k] / 255.; 138 | } 139 | } 140 | } 141 | 142 | return out; 143 | } 144 | 145 | static image_t make_empty_image(int w, int h, int c) 146 | { 147 | image_t out; 148 | out.data = 0; 149 | out.h = h; 150 | out.w = w; 151 | out.c = c; 152 | return out; 153 | } 154 | 155 | static image_t make_image_custom(int w, int h, int c) 156 | { 157 | image_t out = make_empty_image(w, h, c); 158 | out.data = (float *)calloc(h*w*c, sizeof(float)); 159 | return out; 160 | } 161 | 162 | #endif // OPENCV 163 | 164 | }; 165 | 166 | 167 | 168 | #if defined(TRACK_OPTFLOW) && defined(OPENCV) && defined(GPU) 169 | 170 | #include 171 | #include 172 | #include 173 | #include 174 | 175 | class Tracker_optflow { 176 | public: 177 | const int gpu_count; 178 | const int gpu_id; 179 | const int flow_error; 180 | 181 | 182 | Tracker_optflow(int _gpu_id = 0, int win_size = 9, int max_level = 3, int iterations = 8000, int _flow_error = -1) : 183 | gpu_count(cv::cuda::getCudaEnabledDeviceCount()), gpu_id(std::min(_gpu_id, gpu_count-1)), 184 | flow_error((_flow_error > 0)? _flow_error:(win_size*4)) 185 | { 186 | int const old_gpu_id = cv::cuda::getDevice(); 187 | cv::cuda::setDevice(gpu_id); 188 | 189 | stream = cv::cuda::Stream(); 190 | 191 | sync_PyrLKOpticalFlow_gpu = cv::cuda::SparsePyrLKOpticalFlow::create(); 192 | sync_PyrLKOpticalFlow_gpu->setWinSize(cv::Size(win_size, win_size)); // 9, 15, 21, 31 193 | sync_PyrLKOpticalFlow_gpu->setMaxLevel(max_level); // +- 3 pt 194 | sync_PyrLKOpticalFlow_gpu->setNumIters(iterations); // 2000, def: 30 195 | 196 | cv::cuda::setDevice(old_gpu_id); 197 | } 198 | 199 | // just to avoid extra allocations 200 | cv::cuda::GpuMat src_mat_gpu; 201 | cv::cuda::GpuMat dst_mat_gpu, dst_grey_gpu; 202 | cv::cuda::GpuMat prev_pts_flow_gpu, cur_pts_flow_gpu; 203 | cv::cuda::GpuMat status_gpu, err_gpu; 204 | 205 | cv::cuda::GpuMat src_grey_gpu; // used in both functions 206 | cv::Ptr sync_PyrLKOpticalFlow_gpu; 207 | cv::cuda::Stream stream; 208 | 209 | std::vector cur_bbox_vec; 210 | std::vector good_bbox_vec_flags; 211 | cv::Mat prev_pts_flow_cpu; 212 | 213 | void update_cur_bbox_vec(std::vector _cur_bbox_vec) 214 | { 215 | cur_bbox_vec = _cur_bbox_vec; 216 | good_bbox_vec_flags = std::vector(cur_bbox_vec.size(), true); 217 | cv::Mat prev_pts, cur_pts_flow_cpu; 218 | 219 | for (auto &i : cur_bbox_vec) { 220 | float x_center = (i.x + i.w / 2.0F); 221 | float y_center = (i.y + i.h / 2.0F); 222 | prev_pts.push_back(cv::Point2f(x_center, y_center)); 223 | } 224 | 225 | if (prev_pts.rows == 0) 226 | prev_pts_flow_cpu = cv::Mat(); 227 | else 228 | cv::transpose(prev_pts, prev_pts_flow_cpu); 229 | 230 | if (prev_pts_flow_gpu.cols < prev_pts_flow_cpu.cols) { 231 | prev_pts_flow_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), prev_pts_flow_cpu.type()); 232 | cur_pts_flow_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), prev_pts_flow_cpu.type()); 233 | 234 | status_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), CV_8UC1); 235 | err_gpu = cv::cuda::GpuMat(prev_pts_flow_cpu.size(), CV_32FC1); 236 | } 237 | 238 | prev_pts_flow_gpu.upload(cv::Mat(prev_pts_flow_cpu), stream); 239 | } 240 | 241 | 242 | void update_tracking_flow(cv::Mat src_mat, std::vector _cur_bbox_vec) 243 | { 244 | int const old_gpu_id = cv::cuda::getDevice(); 245 | if (old_gpu_id != gpu_id) 246 | cv::cuda::setDevice(gpu_id); 247 | 248 | if (src_mat.channels() == 3) { 249 | if (src_mat_gpu.cols == 0) { 250 | src_mat_gpu = cv::cuda::GpuMat(src_mat.size(), src_mat.type()); 251 | src_grey_gpu = cv::cuda::GpuMat(src_mat.size(), CV_8UC1); 252 | } 253 | 254 | update_cur_bbox_vec(_cur_bbox_vec); 255 | 256 | //src_grey_gpu.upload(src_mat, stream); // use BGR 257 | src_mat_gpu.upload(src_mat, stream); 258 | cv::cuda::cvtColor(src_mat_gpu, src_grey_gpu, CV_BGR2GRAY, 1, stream); 259 | } 260 | if (old_gpu_id != gpu_id) 261 | cv::cuda::setDevice(old_gpu_id); 262 | } 263 | 264 | 265 | std::vector tracking_flow(cv::Mat dst_mat, bool check_error = true) 266 | { 267 | if (sync_PyrLKOpticalFlow_gpu.empty()) { 268 | std::cout << "sync_PyrLKOpticalFlow_gpu isn't initialized \n"; 269 | return cur_bbox_vec; 270 | } 271 | 272 | int const old_gpu_id = cv::cuda::getDevice(); 273 | if(old_gpu_id != gpu_id) 274 | cv::cuda::setDevice(gpu_id); 275 | 276 | if (dst_mat_gpu.cols == 0) { 277 | dst_mat_gpu = cv::cuda::GpuMat(dst_mat.size(), dst_mat.type()); 278 | dst_grey_gpu = cv::cuda::GpuMat(dst_mat.size(), CV_8UC1); 279 | } 280 | 281 | //dst_grey_gpu.upload(dst_mat, stream); // use BGR 282 | dst_mat_gpu.upload(dst_mat, stream); 283 | cv::cuda::cvtColor(dst_mat_gpu, dst_grey_gpu, CV_BGR2GRAY, 1, stream); 284 | 285 | if (src_grey_gpu.rows != dst_grey_gpu.rows || src_grey_gpu.cols != dst_grey_gpu.cols) { 286 | stream.waitForCompletion(); 287 | src_grey_gpu = dst_grey_gpu.clone(); 288 | cv::cuda::setDevice(old_gpu_id); 289 | return cur_bbox_vec; 290 | } 291 | 292 | ////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 293 | 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 294 | 295 | cv::Mat cur_pts_flow_cpu; 296 | cur_pts_flow_gpu.download(cur_pts_flow_cpu, stream); 297 | 298 | dst_grey_gpu.copyTo(src_grey_gpu, stream); 299 | 300 | cv::Mat err_cpu, status_cpu; 301 | err_gpu.download(err_cpu, stream); 302 | status_gpu.download(status_cpu, stream); 303 | 304 | stream.waitForCompletion(); 305 | 306 | std::vector result_bbox_vec; 307 | 308 | if (err_cpu.cols == cur_bbox_vec.size() && status_cpu.cols == cur_bbox_vec.size()) 309 | { 310 | for (size_t i = 0; i < cur_bbox_vec.size(); ++i) 311 | { 312 | cv::Point2f cur_key_pt = cur_pts_flow_cpu.at(0, i); 313 | cv::Point2f prev_key_pt = prev_pts_flow_cpu.at(0, i); 314 | 315 | float moved_x = cur_key_pt.x - prev_key_pt.x; 316 | float moved_y = cur_key_pt.y - prev_key_pt.y; 317 | 318 | if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i]) 319 | if (err_cpu.at(0, i) < flow_error && status_cpu.at(0, i) != 0 && 320 | ((float)cur_bbox_vec[i].x + moved_x) > 0 && ((float)cur_bbox_vec[i].y + moved_y) > 0) 321 | { 322 | cur_bbox_vec[i].x += moved_x + 0.5; 323 | cur_bbox_vec[i].y += moved_y + 0.5; 324 | result_bbox_vec.push_back(cur_bbox_vec[i]); 325 | } 326 | else good_bbox_vec_flags[i] = false; 327 | else good_bbox_vec_flags[i] = false; 328 | 329 | //if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]); 330 | } 331 | } 332 | 333 | cur_pts_flow_gpu.swap(prev_pts_flow_gpu); 334 | cur_pts_flow_cpu.copyTo(prev_pts_flow_cpu); 335 | 336 | if (old_gpu_id != gpu_id) 337 | cv::cuda::setDevice(old_gpu_id); 338 | 339 | return result_bbox_vec; 340 | } 341 | 342 | }; 343 | 344 | #elif defined(TRACK_OPTFLOW) && defined(OPENCV) 345 | 346 | //#include 347 | #include 348 | 349 | class Tracker_optflow { 350 | public: 351 | const int flow_error; 352 | 353 | 354 | Tracker_optflow(int win_size = 9, int max_level = 3, int iterations = 8000, int _flow_error = -1) : 355 | flow_error((_flow_error > 0)? _flow_error:(win_size*4)) 356 | { 357 | sync_PyrLKOpticalFlow = cv::SparsePyrLKOpticalFlow::create(); 358 | sync_PyrLKOpticalFlow->setWinSize(cv::Size(win_size, win_size)); // 9, 15, 21, 31 359 | sync_PyrLKOpticalFlow->setMaxLevel(max_level); // +- 3 pt 360 | 361 | } 362 | 363 | // just to avoid extra allocations 364 | cv::Mat dst_grey; 365 | cv::Mat prev_pts_flow, cur_pts_flow; 366 | cv::Mat status, err; 367 | 368 | cv::Mat src_grey; // used in both functions 369 | cv::Ptr sync_PyrLKOpticalFlow; 370 | 371 | std::vector cur_bbox_vec; 372 | std::vector good_bbox_vec_flags; 373 | 374 | void update_cur_bbox_vec(std::vector _cur_bbox_vec) 375 | { 376 | cur_bbox_vec = _cur_bbox_vec; 377 | good_bbox_vec_flags = std::vector(cur_bbox_vec.size(), true); 378 | cv::Mat prev_pts, cur_pts_flow; 379 | 380 | for (auto &i : cur_bbox_vec) { 381 | float x_center = (i.x + i.w / 2.0F); 382 | float y_center = (i.y + i.h / 2.0F); 383 | prev_pts.push_back(cv::Point2f(x_center, y_center)); 384 | } 385 | 386 | if (prev_pts.rows == 0) 387 | prev_pts_flow = cv::Mat(); 388 | else 389 | cv::transpose(prev_pts, prev_pts_flow); 390 | } 391 | 392 | 393 | void update_tracking_flow(cv::Mat new_src_mat, std::vector _cur_bbox_vec) 394 | { 395 | if (new_src_mat.channels() == 3) { 396 | 397 | update_cur_bbox_vec(_cur_bbox_vec); 398 | 399 | cv::cvtColor(new_src_mat, src_grey, CV_BGR2GRAY, 1); 400 | } 401 | } 402 | 403 | 404 | std::vector tracking_flow(cv::Mat new_dst_mat, bool check_error = true) 405 | { 406 | if (sync_PyrLKOpticalFlow.empty()) { 407 | std::cout << "sync_PyrLKOpticalFlow isn't initialized \n"; 408 | return cur_bbox_vec; 409 | } 410 | 411 | cv::cvtColor(new_dst_mat, dst_grey, CV_BGR2GRAY, 1); 412 | 413 | if (src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols) { 414 | src_grey = dst_grey.clone(); 415 | return cur_bbox_vec; 416 | } 417 | 418 | if (prev_pts_flow.cols < 1) { 419 | return cur_bbox_vec; 420 | } 421 | 422 | ////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 423 | sync_PyrLKOpticalFlow->calc(src_grey, dst_grey, prev_pts_flow, cur_pts_flow, status, err); // OpenCV 3.x 424 | 425 | dst_grey.copyTo(src_grey); 426 | 427 | std::vector result_bbox_vec; 428 | 429 | if (err.rows == cur_bbox_vec.size() && status.rows == cur_bbox_vec.size()) 430 | { 431 | for (size_t i = 0; i < cur_bbox_vec.size(); ++i) 432 | { 433 | cv::Point2f cur_key_pt = cur_pts_flow.at(0, i); 434 | cv::Point2f prev_key_pt = prev_pts_flow.at(0, i); 435 | 436 | float moved_x = cur_key_pt.x - prev_key_pt.x; 437 | float moved_y = cur_key_pt.y - prev_key_pt.y; 438 | 439 | if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i]) 440 | if (err.at(0, i) < flow_error && status.at(0, i) != 0 && 441 | ((float)cur_bbox_vec[i].x + moved_x) > 0 && ((float)cur_bbox_vec[i].y + moved_y) > 0) 442 | { 443 | cur_bbox_vec[i].x += moved_x + 0.5; 444 | cur_bbox_vec[i].y += moved_y + 0.5; 445 | result_bbox_vec.push_back(cur_bbox_vec[i]); 446 | } 447 | else good_bbox_vec_flags[i] = false; 448 | else good_bbox_vec_flags[i] = false; 449 | 450 | //if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]); 451 | } 452 | } 453 | 454 | prev_pts_flow = cur_pts_flow.clone(); 455 | 456 | return result_bbox_vec; 457 | } 458 | 459 | }; 460 | #else 461 | 462 | class Tracker_optflow {}; 463 | 464 | #endif // defined(TRACK_OPTFLOW) && defined(OPENCV) 465 | 466 | 467 | #ifdef OPENCV 468 | 469 | static cv::Scalar obj_id_to_color(int obj_id) { 470 | int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } }; 471 | int const offset = obj_id * 123457 % 6; 472 | int const color_scale = 150 + (obj_id * 123457) % 100; 473 | cv::Scalar color(colors[offset][0], colors[offset][1], colors[offset][2]); 474 | color *= color_scale; 475 | return color; 476 | } 477 | 478 | class preview_boxes_t { 479 | enum { frames_history = 30 }; // how long to keep the history saved 480 | 481 | struct preview_box_track_t { 482 | unsigned int track_id, obj_id, last_showed_frames_ago; 483 | bool current_detection; 484 | bbox_t bbox; 485 | cv::Mat mat_obj, mat_resized_obj; 486 | preview_box_track_t() : track_id(0), obj_id(0), last_showed_frames_ago(frames_history), current_detection(false) {} 487 | }; 488 | std::vector preview_box_track_id; 489 | size_t const preview_box_size, bottom_offset; 490 | bool const one_off_detections; 491 | public: 492 | preview_boxes_t(size_t _preview_box_size = 100, size_t _bottom_offset = 100, bool _one_off_detections = false) : 493 | preview_box_size(_preview_box_size), bottom_offset(_bottom_offset), one_off_detections(_one_off_detections) 494 | {} 495 | 496 | void set(cv::Mat src_mat, std::vector result_vec) 497 | { 498 | size_t const count_preview_boxes = src_mat.cols / preview_box_size; 499 | if (preview_box_track_id.size() != count_preview_boxes) preview_box_track_id.resize(count_preview_boxes); 500 | 501 | // increment frames history 502 | for (auto &i : preview_box_track_id) 503 | i.last_showed_frames_ago = std::min((unsigned)frames_history, i.last_showed_frames_ago + 1); 504 | 505 | // occupy empty boxes 506 | for (auto &k : result_vec) { 507 | bool found = false; 508 | // find the same (track_id) 509 | for (auto &i : preview_box_track_id) { 510 | if (i.track_id == k.track_id) { 511 | if (!one_off_detections) i.last_showed_frames_ago = 0; // for tracked objects 512 | found = true; 513 | break; 514 | } 515 | } 516 | if (!found) { 517 | // find empty box 518 | for (auto &i : preview_box_track_id) { 519 | if (i.last_showed_frames_ago == frames_history) { 520 | if (!one_off_detections && k.frames_counter == 0) break; // don't show if obj isn't tracked yet 521 | i.track_id = k.track_id; 522 | i.obj_id = k.obj_id; 523 | i.bbox = k; 524 | i.last_showed_frames_ago = 0; 525 | break; 526 | } 527 | } 528 | } 529 | } 530 | 531 | // draw preview box (from old or current frame) 532 | for (size_t i = 0; i < preview_box_track_id.size(); ++i) 533 | { 534 | // get object image 535 | cv::Mat dst = preview_box_track_id[i].mat_resized_obj; 536 | preview_box_track_id[i].current_detection = false; 537 | 538 | for (auto &k : result_vec) { 539 | if (preview_box_track_id[i].track_id == k.track_id) { 540 | if (one_off_detections && preview_box_track_id[i].last_showed_frames_ago > 0) { 541 | preview_box_track_id[i].last_showed_frames_ago = frames_history; break; 542 | } 543 | bbox_t b = k; 544 | cv::Rect r(b.x, b.y, b.w, b.h); 545 | cv::Rect img_rect(cv::Point2i(0, 0), src_mat.size()); 546 | cv::Rect rect_roi = r & img_rect; 547 | if (rect_roi.width > 1 || rect_roi.height > 1) { 548 | cv::Mat roi = src_mat(rect_roi); 549 | cv::resize(roi, dst, cv::Size(preview_box_size, preview_box_size), cv::INTER_NEAREST); 550 | preview_box_track_id[i].mat_obj = roi.clone(); 551 | preview_box_track_id[i].mat_resized_obj = dst.clone(); 552 | preview_box_track_id[i].current_detection = true; 553 | preview_box_track_id[i].bbox = k; 554 | } 555 | break; 556 | } 557 | } 558 | } 559 | } 560 | 561 | 562 | void draw(cv::Mat draw_mat, bool show_small_boxes = false) 563 | { 564 | // draw preview box (from old or current frame) 565 | for (size_t i = 0; i < preview_box_track_id.size(); ++i) 566 | { 567 | auto &prev_box = preview_box_track_id[i]; 568 | 569 | // draw object image 570 | cv::Mat dst = prev_box.mat_resized_obj; 571 | if (prev_box.last_showed_frames_ago < frames_history && 572 | dst.size() == cv::Size(preview_box_size, preview_box_size)) 573 | { 574 | cv::Rect dst_rect_roi(cv::Point2i(i * preview_box_size, draw_mat.rows - bottom_offset), dst.size()); 575 | cv::Mat dst_roi = draw_mat(dst_rect_roi); 576 | dst.copyTo(dst_roi); 577 | 578 | cv::Scalar color = obj_id_to_color(prev_box.obj_id); 579 | int thickness = (prev_box.current_detection) ? 5 : 1; 580 | cv::rectangle(draw_mat, dst_rect_roi, color, thickness); 581 | 582 | unsigned int const track_id = prev_box.track_id; 583 | std::string track_id_str = (track_id > 0) ? std::to_string(track_id) : ""; 584 | 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); 585 | 586 | std::string size_str = std::to_string(prev_box.bbox.w) + "x" + std::to_string(prev_box.bbox.h); 587 | 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); 588 | 589 | if (!one_off_detections && prev_box.current_detection) { 590 | cv::line(draw_mat, dst_rect_roi.tl() + cv::Point2i(preview_box_size, 0), 591 | cv::Point2i(prev_box.bbox.x, prev_box.bbox.y + prev_box.bbox.h), 592 | color); 593 | } 594 | 595 | if (one_off_detections && show_small_boxes) { 596 | cv::Rect src_rect_roi(cv::Point2i(prev_box.bbox.x, prev_box.bbox.y), 597 | cv::Size(prev_box.bbox.w, prev_box.bbox.h)); 598 | unsigned int const color_history = (255 * prev_box.last_showed_frames_ago) / frames_history; 599 | color = cv::Scalar(255 - 3 * color_history, 255 - 2 * color_history, 255 - 1 * color_history); 600 | if (prev_box.mat_obj.size() == src_rect_roi.size()) { 601 | prev_box.mat_obj.copyTo(draw_mat(src_rect_roi)); 602 | } 603 | cv::rectangle(draw_mat, src_rect_roi, color, thickness); 604 | 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); 605 | } 606 | } 607 | } 608 | } 609 | }; 610 | #endif // OPENCV 611 | 612 | //extern "C" { 613 | #endif // __cplusplus 614 | 615 | /* 616 | // C - wrappers 617 | YOLODLL_API void create_detector(char const* cfg_filename, char const* weight_filename, int gpu_id); 618 | YOLODLL_API void delete_detector(); 619 | YOLODLL_API bbox_t* detect_custom(image_t img, float thresh, bool use_mean, int *result_size); 620 | YOLODLL_API bbox_t* detect_resized(image_t img, int init_w, int init_h, float thresh, bool use_mean, int *result_size); 621 | YOLODLL_API bbox_t* detect(image_t img, int *result_size); 622 | YOLODLL_API image_t load_img(char *image_filename); 623 | YOLODLL_API void free_img(image_t m); 624 | 625 | #ifdef __cplusplus 626 | } // extern "C" 627 | 628 | static std::shared_ptr c_detector_ptr; 629 | static std::vector c_result_vec; 630 | 631 | void create_detector(char const* cfg_filename, char const* weight_filename, int gpu_id) { 632 | c_detector_ptr = std::make_shared(cfg_filename, weight_filename, gpu_id); 633 | } 634 | 635 | void delete_detector() { c_detector_ptr.reset(); } 636 | 637 | bbox_t* detect_custom(image_t img, float thresh, bool use_mean, int *result_size) { 638 | c_result_vec = static_cast(c_detector_ptr.get())->detect(img, thresh, use_mean); 639 | *result_size = c_result_vec.size(); 640 | return c_result_vec.data(); 641 | } 642 | 643 | bbox_t* detect_resized(image_t img, int init_w, int init_h, float thresh, bool use_mean, int *result_size) { 644 | c_result_vec = static_cast(c_detector_ptr.get())->detect_resized(img, init_w, init_h, thresh, use_mean); 645 | *result_size = c_result_vec.size(); 646 | return c_result_vec.data(); 647 | } 648 | 649 | bbox_t* detect(image_t img, int *result_size) { 650 | return detect_custom(img, 0.24, true, result_size); 651 | } 652 | 653 | image_t load_img(char *image_filename) { 654 | return static_cast(c_detector_ptr.get())->load_image(image_filename); 655 | } 656 | void free_img(image_t m) { 657 | static_cast(c_detector_ptr.get())->free_image(m); 658 | } 659 | 660 | #endif // __cplusplus 661 | */ 662 | --------------------------------------------------------------------------------