4,445
社区成员
发帖
与我相关
我的任务
分享
int main(){
/*基本变量定义*/
Mat frame; //原始视频帧
Mat frame2; //原始视频帧2,用于比较帧差
Mat frame3; //原始视频帧3,用于比较帧差
Mat forMat; //前景图像
Mat forMat2; //前景图像2
Mat forMat3; //前景图像3
Mat disMat; //界面背景图片
int nfps = 1; //记录播放的帧数
string sbrkIn; //显示入侵人数
string sbrkNum; //显示入侵次数
double yfps; //视频的实际帧率
double tOut; //播放一帧所需要的时间(s)
double htOut = 0; //播放理论帧率一半帧数所需时间
int nFrmNum = 0; //播放的帧数
int cut_num = 0; //记录截屏次数
/*播放视频前准备*/
string fileName[5]; //记录文件位置
VideoCapture cap; //存储视频信息
uchar s; //记录像素值
int warnin = 30; //控制图像报警帧数
//初始化
disMat = imread("C:/Users/lenovo/Desktop/bk.png");
box = Rect(0, 0, -1, -1);
initButtonLocation();
//获取视频文件的位置(从配置文件中获取)
ifstream fst; //文件流
char cLine[60]; //读取数据存放数组
string config = "C:/Users/lenovo/Documents/Visual Studio 2013/Projects/opencvRQ/opencvRQ/Text.txt"; //配置文件位置
fst.open(config);
int loc_equal; //"="所在位置
int num_file = 0; //第几行
while (fst.getline(cLine, 60)){
for (int i = 0; i < 60; i++){
if (cLine[i] == '='){
loc_equal = i;
break;
}
}
for (int i = loc_equal; i < 60; i++){
cLine[i - loc_equal] = cLine[i + 1];
}
fileName[num_file++] = cLine;
}
//创建窗口
namedWindow("video", 0);
namedWindow("foreground", 0);
//窗口有序化
resizeWindow("video", 853, 650);
moveWindow("video", 257, 20);
moveWindow("foreground", 690, 0);
//打开视频
cap.open(fileName[0]);
cout << cLine << endl;
if (!cap.isOpened()){
cout << "无法打开视频文件";
return 0;
}
//获取第一帧并画框
cap >> frame;
cvSetMouseCallback("video", on_mouse, (void*)&frame); //鼠标响应函数
createTrackbar("阈值", "video", &INOUT, 200, onChange); //滑动条响应函数
/**视频播放前需要画一个框
--------------------------------
*resize 首先改变frame的尺寸,使它能适应框的尺寸
*MatROI 划定敏感区域,把frame放入正确的位置
*disMat 展现处理完的图像
*-------------------------*
*注意一定要改变图像的size,否则划定敏感区域的时候会报错
*注意在开始播放(这里)和播放中(下面)都要进行这一系列的操作
*/
while (out == false){
resize(frame, frame, Size(853, 480));
Mat MatROI = disMat(Rect(0, 0, frame.cols, frame.rows));
frame.copyTo(MatROI);
if (Drawing)
DrawRect1(disMat, box);
imshow("video", disMat);
if (waitKey(100) == 27)
break;
}
//开始播放视频并检测
Mat tdisMat; //保存原背景图像
int fps = cap.get(CV_CAP_PROP_FPS); //获取视频的原本播放帧率
int hFps_temp = fps / 2; //一半帧率,用于计数
yfps = fps; //实际帧率的初始化,因为是15帧计算一次,但
tOut = (double)getTickCount(); //获取当前系统时间
bool stop = false; //判断视频是否结束
disMat.copyTo(tdisMat); //tdisMat初始化
Ptr<BackgroundSubtractorMOG2> bk = createBackgroundSubtractorMOG2(100, 25, true); //高斯建模
int nb[4] = { 0, 0, 0, 0 }; //边界较大框的前景像素点
int ns[4] = { 0, 0, 0, 0 }; //边界较小框的前景像素点
int nb_temp[4] = { 0, 0, 0, 0 }; //边界较大框的前景像素点(前一帧)
int ns_temp[4] = { 0, 0, 0, 0 }; //边界较小框的前景像素点(前一帧)
//log画分割线
fstream fst2("./日志/log.txt", ios::app);
if (!fst2.is_open()){
cout << "无法打开文件log.txt";
return -1;
}
fst2 << "-------------------------------------------------------------" << endl;
fst2.close();
while (!stop){
//初始化
disMat = tdisMat.clone(); //更新大背景
tOut = (double)cv::getTickCount();
//获取帧数并计算时间
nfps = nfps + 1;
string time = GetRungingTime(fps, nfps);
//计算帧率
tOut = (double)(getTickCount() - tOut) / getTickFrequency();
htOut += tOut;
hFps_temp--;
if (!hFps_temp){
hFps_temp = fps / 2;
yfps = 1.0 / (htOut / hFps_temp) / 10000;
htOut = 0;
}
//获取图像并进行相关处理
frame2 = frame; //保存两帧图像
cap >> frame;
if (frame.empty())
break;
//GaussianBlur(frame, frame, Size(3, 3), 0, 0); //高斯滤波
resize(frame, frame, Size(853, 480));
Mat MatROI = disMat(Rect(0, 0, frame.cols, frame.rows));
Mat e = getStructuringElement(MORPH_RECT, cv::Size(2, 2));
//erode(frame, frame, e);
/*Mat gframe(Size(frame.rows,frame.cols), CV_8UC1);
cvtCOLOR(frame, gframe);*/
forMat.create(frame.rows, frame.cols, CV_8UC1);
bk->apply(frame, forMat, 0.006); //高斯建模
//medianBlur(forMat, forMat, 5); //中值滤波,效果较好
//dilate(forMat, forMat, e); //膨胀
//erode(frame, frame, e); //腐蚀
//dilate(forMat, forMat, e); //膨胀
//计算四个边界的前景点
/*ns_temp = ns;
nb_temp = nb;
ns = lineCount(forMat, xx1 + SPACE, xx2 - SPACE, yy1 + SPACE, yy2 - SPACE);
nb = lineCount(forMat, xx1 - SPACE, xx2 + SPACE, yy1 - SPACE, yy2 + SPACE);
*/
for (int i = 0; i < 4; i++){
ns_temp[i] = ns[i];
nb_temp[i] = nb[i];
}
int* temp1 = LineCount(forMat, xx1 + SPACE, xx2 - SPACE, yy1 + SPACE, yy2 - SPACE);
int* temp2 = LineCount(forMat, xx1 - SPACE, xx2 + SPACE, yy1 - SPACE, yy2 + SPACE);
for (int i = 0; i < 4; i++){
ns[i] = temp1[i];
nb[i] = temp2[i];
}
//****************************画框前景背景分离图像***************************
Rect box1;
box1 = Rect(xx1 + SPACE, yy1 + SPACE, xx2 - xx1 - 2 * SPACE, yy2 - yy1 - 2 * SPACE);
rectangle(forMat, box1, Scalar(0xff, 0x00, 0xf0), 1);
Rect box2;
box1 = Rect(xx1 - SPACE, yy1 - SPACE, xx2 - xx1 + 2 * SPACE, yy2 - yy1 + 2 * SPACE);
rectangle(forMat, box1, Scalar(0xff, 0x00, 0x00), 1);
//************************************************************
//判断进出
cout << endl;
SYSTEMTIME sys;
GetLocalTime(&sys); //获取系统时间
if (Nowarm[0] != 0)
Nowarm[0]--;
if (Nowarm[1] != 0)
Nowarm[1]--;
//区域边界交界处像素点
int pix[2];
pix[0] = forMat.at<uchar>((yy1 + yy2) / 2, xx2+SPACE);
pix[0] = forMat.at<uchar>((yy1 + yy2) / 2, xx1-SPACE);
for (int i = 0; i<4; i++){
if (nb_temp[i]>INOUT && ns_temp[i]<INOUT && nb[i]>INOUT && ns[i]>INOUT && Nowarm[i / 2] == 0)
{
cout << endl;
warnin = WAEMNUM; //通过次数(WAEMNUM)控制显示时间
brkIn += 1; //有人入侵
brkNum += 1; //入侵次数加1
}
if (warnin > 0){
if (WAEMNUM == warnin){
//去除一个人判断两次的情况
int temp = 0;
if (i == 0 || i == 1){
for (int j = yy1; j < yy2; j++)
if (forMat.at<uchar>(j, xx2) == 255)
temp++;
}
if (i == 2 || i == 3){
for (int j = yy1; j < yy2; j++)
if (forMat.at<uchar>(j, xx1) == 255)
temp++;
}
if (temp < 100 && pix[i / 2] == 255){
Nowarm[i / 2] = 20;
}
//waitKey(0);
//创建扬声器进程
HANDLE handle = CreateThread(NULL, 0, Beep, NULL, 0, NULL);
CloseHandle(handle);
cut_num++;
Mat src = frame;
fstream fst("./日志/log.txt", ios::app);
if (!fst.is_open()){
cout << "无法打开文件log.txt";
return -1;
}
fst << sys.wYear << "年" << sys.wMonth << "月" << sys.wDay << "日 " << sys.wHour << ":" << sys.wMinute << ":" << sys.wSecond;
fst << " " << "入侵警告,视频:" << fileName[0] << " ,视频播放时间" << time << endl;
fst.close();
char dd[5];
string strcut;
_itoa_s(cut_num, dd, 10);
strcut = string(dd);
string cutloc = "./入侵截图/" + strcut + ".jpg";
imwrite(cutloc, src);
}
//在原图像上报警
rectangle(frame, box, Scalar(0x00, 0xff, 0xff), 2);
//在二值图像上报警
rectangle(forMat, box, Scalar(0xff, 0xff, 0xff), 2);
putText(forMat, "Warning in", Point(0, 20), CV_FONT_HERSHEY_SIMPLEX, 1, CV_RGB(255, 255, 255));
warnin--;
}
//如果没有目标入侵
else{
//在原图像上画框
rectangle(frame, box, Scalar(0x00, 0xff, 0x00), 2);
//在二值图像上画框
rectangle(forMat, box, Scalar(0xff, 0xff, 0xff), 2);
}
}
//+-----------------信息显示模块位置图---------------------------------------
//|---时间(151,533)-------次数(435, 533)----------------------------------------------
//|--------------------------------------------------------
//|--------------------------------------------------------
//|---入侵(151, 600)------帧率(435, 600)-----------------------------------------------
//|--------------------------------------------------------
//显示按钮
show(disMat);
//显示时间
putText(disMat, time, Point(151, 533), CV_FONT_HERSHEY_COMPLEX, 0.6, CV_RGB(0x00, 0x00, 0x00));
//将人数int转换成人数string并显示
char aa[2];
_itoa_s(brkIn, aa, 10);
sbrkIn = string(aa);
putText(disMat, sbrkIn, Point(151, 600), CV_FONT_HERSHEY_COMPLEX, 0.6, CV_RGB(0x00, 0x00, 0x00));
//将入侵次数int转换成人数string并显示
char bb[4];
_itoa_s(brkNum, bb, 10);
sbrkNum = string(bb);
putText(disMat, sbrkNum, Point(435, 533), CV_FONT_HERSHEY_COMPLEX, 0.6, CV_RGB(0x00, 0x00, 0x00));
//将帧率int转换成帧率string并显示
char cc[5];
_itoa_s(yfps, cc, 10);
string sfps = string(cc);
putText(disMat, sfps, Point(435, 600), CV_FONT_HERSHEY_COMPLEX, 0.6, CV_RGB(0x00, 0x00, 0x00));
//最终显示
frame.copyTo(MatROI);
imshow("video", disMat);
imshow("foreground", forMat);
int n = waitKey(1);
if (n == 32){
while (waitKey(0) != 32){}
}
/*if (n == 77){
for (int i = 0; i < SPEED; i++)
cap >> frame;
}*/
}
}