对6.1进行了一些优化
题外话:
稍加观察思索就会发现,我只测试了一个视频场景,而且这个场景是特意选择的。
背景十分干净,是白色的墙壁,没有过多的干扰。我这个是不可能在雪地里追踪到白色的兔子的。我在测试的时候还发现,当我把矩形框框得比较大的时候,也就是包含的墙壁比较多,它就很大概率会丢失目标,开始乱跑。
我这个做法是只处理了矩形框,如果是追踪⚽️等圆形物体, 我觉得圆形区域去追踪会更好一点。所以为了展示良好的效果,拍摄的目标被我刻意选择为了标准的矩形。
#include <bits/stdc++.h> #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/video.hpp" #include "opencv2/objdetect.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include "opencv2/ml.hpp" #define p(a) putchar(a) #define For(i,a,b) for(int i=a;i<=b;++i) using namespace std; using namespace cv; int w,h,w0,h0,bc0,bc1,cnt; double fps,part,diff,val; bool lu_flag,flag; Point lu,rd,mid,st,ed,best_st,best_ed; Mat temp,image,IMAGE,tb; MatND hist; int channels[] = {0,1,2}; int SIZE[] = {32,32,32}; float R[] = {0,255}; float G[] = {0,255}; float B[] = {0,255}; const float *ranges[] = {R, G ,B}; const char * path = "/Users/war/Downloads/track0.mp4"; void in(int &x){ int y=1;char c=getchar();x=0; while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();} x*=y; } void o(int x){ if(x<0){p('-');x=-x;} if(x>9)o(x/10); p(x%10+'0'); } void onMouse(int event, int x, int y, int flags, void *ustc){ if(event == EVENT_LBUTTONDOWN){ lu_flag = 1; lu = Point(x,y); } if(event == EVENT_MOUSEMOVE && lu_flag){ temp = image.clone(); rd = Point(x,y); if(lu != rd) rectangle(temp, lu, rd, Scalar(255, 0, 0), 3); imshow("temp",temp); } if(event == EVENT_LBUTTONUP){ lu_flag = 0;flag = 1; rd = Point(x,y); IMAGE = image(Rect(lu, rd)); } } void init(){ VideoCapture video(path); if(!video.isOpened()){ cout<<"视频打开失败!"<<endl; return; } fps = video.get(CAP_PROP_FPS); part = 1000.0 / fps; namedWindow("temp"); setMouseCallback("temp", onMouse); while(1){ if(!lu_flag) video >> image; if(!image.data || waitKey(part) == 27) break; imshow("temp",image); if(flag){ destroyWindow("temp"); break; } } video.release(); } double cal(){ Mat temp0; calcHist(&temp, 1, channels, Mat(), temp0, 3, SIZE, ranges, true, false); normalize(temp0, temp0, 0, 1, NORM_MINMAX); return compareHist(hist, temp0, 3); } void tracking(){ w = abs(lu.x - rd.x); h = abs(lu.y - rd.y); auto x0 = lu.x - w; auto x1 = rd.x + w; auto y0 = rd.y - h; auto y1 = lu.y + h; x0 = max(0, x0); x1 = min(x1, image.cols); y0 = max(0, y0); y1 = min(y1, image.rows); VideoCapture video(path); if(!video.isOpened()){ cout<<"视频打开失败!"<<endl; return; } fps = video.get(CAP_PROP_FPS); part = 1000.0 / fps; namedWindow("tracking"); while(1){ video >> image; if(!image.data || waitKey(part) == 27) break; diff = 1.0; bc0 = max(1 ,IMAGE.rows / 7); bc1 = max(1,IMAGE.cols / 7); for(int i = y0; i <= y1; i += bc0){ for(st.x=x0,st.y=i; st.x <= x1; st.x += bc1){ ed.x = min(st.x + w, image.cols-1); ed.y = min(st.y + h, image.rows-1); temp = image(Rect(st,ed)); val = cal(); if(diff > val){ diff = val; best_st = st; best_ed = ed; tb = temp; } } } if(diff < 0.5){ x0 = best_st.x - w; x1 = best_ed.x + w; y0 = best_st.y - h; y1 = best_ed.y + h; x0 = max(0, x0); x1 = min(x1, image.cols); y0 = max(0, y0); y1 = min(y1, image.rows); rectangle(image, best_st, best_ed, Scalar(0, 0, 255), 3); if((++cnt)%10==0){ calcHist(&tb, 1, channels, Mat(), hist, 3, SIZE, ranges, true, false); normalize(hist, hist, 0, 1, NORM_MINMAX); } } imshow("tracking",image); } video.release(); } signed main(){ init(); calcHist(&IMAGE, 1, channels, Mat(), hist, 3, SIZE, ranges, true, false); normalize(hist, hist, 0, 1, NORM_MINMAX); tracking(); waitKey(0); return 0; }