#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<ctype.h>
using namespace std;
using namespace cv;
Mat image; //当前帧图像
Mat imageCopy; //用于拷贝的当前帧图像
Mat rectImage; //子图像
Point beginPoint; //矩形框起点
Point endPoint; //矩形框终点
bool leftButtonDownFlag = false; //左键单击后视频暂停播放的标志位
int frameCount = 0; //帧数统计
int trackCount = 0; //等于1时初始化直方图
void onMouse(int event, int x, int y, int flags, void* ustc); //鼠标回调函数
int main(int argc, char* argv[]) {
VideoCapture capture("1.AVI");
//VideoCapture capture(0);
int capture_fps = capture.get(CV_CAP_PROP_FPS); //获取视频帧率
int capture_count = capture.get(CV_CAP_PROP_FRAME_COUNT);
int capture_width = capture.get(CV_CAP_PROP_FRAME_WIDTH);
int capture_height = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
cout << "视频帧率:" << capture_fps << endl;
cout << "视频帧数:" << capture_count << endl;
cout << "视频宽度:" << capture_width << endl;
cout << "视频高度:" << capture_height << endl;
int pauseTime = 1000 / capture_fps; //两幅画面中间间隔
namedWindow("Video");
setMouseCallback("Video", onMouse);//函数setMousecallback用于鼠标在图上做标记等作用
int hbinNum = 16;//每一维上直方图的个数,如果是一维直方图,就是竖条(bin)的个数
float hranges[] = { 40, 250 };//每一维数值的取值范围数组
const float* phranges = hranges;//const修饰phranges指针,指针phranges的指向可以修改,但是phranges指向的值不可以改;指针phranges指向的是hranges的首地址
bool backprojectMode = false;
namedWindow("Video", 0);
capture >> image;
int rows = image.rows;
int cols = image.cols;
Mat image1 = image.clone();
Mat dst, edge, gray;//定义canny边缘检测所需的变量
Mat abs_grad_x, abs_grad_y;//定义sobel算子求方向梯度所需的变量
Mat grad_x(rows, cols, CV_8UC1, Scalar::all(0));//定义sobel算子求方向梯度所需的变量
Mat grad_y(rows, cols, CV_8UC1, Scalar::all(0));//定义sobel算子求方向梯度所需的变量
Mat theta(rows, cols, CV_32FC1, Scalar::all(0));
Mat gradient(rows, cols, CV_32FC1, Scalar::all(0));//梯度矩阵
Mat angle(rows, cols, CV_32FC1, Scalar::all(0));//梯度方向角度
Mat mask, hist, histImg = Mat::zeros(image.size(), image.type()), backproj;//初始化histImg存储直方图数据,使其规格与捕获的image相同
Rect trackWindow;//定义一个捕捉矩形窗口
//**********************读取视频********************************
while (true) {
if (!leftButtonDownFlag) //鼠标左键按下绘制矩形时,视频暂停播放
{
capture >> image;//读取当前帧
frameCount++; //帧数增加,视频向前增加
}
if (!image.data || waitKey(pauseTime + 30) == 27) //当当前帧的数据为空或两帧画面的时间间隔不满足规定的数值时,退出播放
{
break;
}
//***************camshiftdemo代码的脉络分析********************
//提取边缘梯度大小与幅值
if (trackCount > 0) {
dst.create(image1.size(), image1.type());
dst = Scalar::all(0);
cvtColor(image1, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, edge, Size(3, 3), 0, 0);
Canny(edge, edge, 3, 9, 3);//canny算子获得边缘图
Sobel(gray, grad_x, CV_16S,1, 0, 3, 1, 1);//求X方向的梯度
Sobel(gray, grad_y, CV_16S,0, 1, 3, 1, 1);//求Y方向的梯度
cartToPolar(grad_x, grad_y, gradient, angle);//计算梯度方向与梯度幅值
convertScaleAbs(grad_x, grad_x);
convertScaleAbs(grad_y, grad_y);
//绘制直方图
if (trackCount == 1) {
histImg = Scalar::all(0);
Mat roi(angle, Rect(beginPoint, endPoint)), maskroi(mask, Rect(beginPoint, endPoint));
calcHist(&roi, 1, 0, maskroi, hist, 1, &hbinNum, &phranges);//掩膜maskroi是用来确定输入图像的哪些像素被计数;mask也设置ROI, 是要让hue中截取出来放在mask中的 区域大小位置都和hue中一致, 不要改变原来的位置这点很有用。
normalize(hist, hist, 0, 255, CV_MINMAX);
trackCount++;
trackWindow = Rect(beginPoint, endPoint);
}
calcBackProject(&angle, 1, 0, hist, backproj, &phranges);//直方图反向投影
backproj &= mask;
meanShift(backproj, trackWindow, TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1));//CamshiftDemo
//***画出跟踪区域的位置
if (backprojectMode) {
cvtColor(backproj, image, CV_GRAY2BGR);
}
rectangle(image, Point(trackWindow.x, trackWindow.y), Point(trackWindow.x + trackWindow.width, trackWindow.y + trackWindow.height), Scalar(0, 0, 255), 1, CV_AA);//画跟踪矩形框
trackCount++;
// writer << image;
}
imshow("Video", image);
}
waitKey(0);
return 0;
}
//鼠标回调函数
void onMouse(int event, int x, int y, int flags, void *ustc)
{
if (event == CV_EVENT_LBUTTONDOWN)
{
leftButtonDownFlag = true; //标志位
beginPoint = Point(x, y); //设置左键按下点的矩形起点
endPoint = beginPoint;
}
if (event == CV_EVENT_MOUSEMOVE && leftButtonDownFlag)
{
imageCopy = image.clone();
endPoint = Point(x, y);
if (beginPoint != endPoint)
{
//在复制的图像上绘制矩形
rectangle(imageCopy, beginPoint, endPoint, Scalar(0, 0, 255), 2);
}
imshow("Video", imageCopy);
}
if (event == CV_EVENT_LBUTTONUP)
{
leftButtonDownFlag = false;
Mat subImage = image(Rect(beginPoint, endPoint)); //子图像
rectImage = subImage.clone();
trackCount = 1;
//imshow("Sub Image", rectImage);
}
}