#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;
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/Desktop//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 = lu.x + w;
auto y0 = rd.y - h;
auto y1 = rd.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 = IMAGE.rows / 10; bc1 = IMAGE.cols / 10;
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 < 1.0){
auto x0 = best_st.x - w;
auto x1 = best_st.x + w;
auto y0 = best_ed.y - h;
auto 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), 2);
}
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;
}