关于opencv 中 高斯建模(BackgroundSubtractorMOG2)中 阴影检测参数的问题

qq_33510982 2018-01-16 10:45:26

因为毕设要用到opencv,所以在学习,最近碰到了一个问题,再用高斯建模BackgroundSubtractorMOG2的时候,里面有个参数控制阴影检测开关的,设为false的时候程序能运行,设为true的时候程序就崩了,搞了很多天,都没弄好,求大神解惑。

以下为错误信息和代码(高斯建模部分我用黑体和蓝色标注了)

0x00007FFA61611009 (amdocl64.dll) (opencvRQ.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0x00000000000009D8 时发生访问冲突。

错误是在使用高斯建模的成员函数apply的时候报的

Ptr<BackgroundSubtractorMOG2> bk = createBackgroundSubtractorMOG2(100, 25, true); //高斯建模

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;
}*/
}

}



...全文
782 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

4,445

社区成员

发帖
与我相关
我的任务
社区描述
图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧