// svibe.cpp : 定义控制台应用程序的入口点。 #include #include #include "svibe.h" #include "stdlib.h" #include "math.h" #include "string.h" #include "MSRegionSurveilance.h" #include "gaussFilte.h" #include #include #include "help.h" //#include "vpt.h" /************************************************************************/ /* 函数: get_ArrowDir() by zl */ /* 作用: 获取方向和用于绘制箭头的两个端点; */ /* 参数: pROI0&pROI1:拌线两个端点; */ /* dir:确定单向警报方向的坐标点; */ /* 返回: 1:正方向;0:负方向 */ /************************************************************************/ int RegionSurveillance::get_ArrowDir(CMPoint pROI0, CMPoint pROI1, CMPoint dir) { float distance = (float)abs(pROI0.y - pROI1.y); //获取方向 float k1, k2; //k1为原线段的斜率 if (pROI0.y > pROI1.y) //在拌线靠近图像下方的端点处画箭头 { pStart.x = pROI0.x; pStart.y = pROI0.y; } else { pStart.x = pROI1.x; pStart.y = pROI1.y; } if (pROI0.x != pROI1.x) //若不为一根垂直线 { k1 = (float)(pROI0.y - pROI1.y) / (float)(pROI0.x - pROI1.x); if (k1 != 0) //若不为一根平行线 { k2 = -1 / k1; float b = pROI1.y - k1 * pROI1.x;//y = kx + b 坐标系一图像左上顶点为原点,向右为x正方形 向下为y正方向 if ((k1 < 0 && (float)((float)dir.y - k1 * (float)dir.x - b) < 0)||(k1 > 0 && (float)((float)dir.y - k1 * (float)dir.x - b) > 0)) { if (distance < 30) //当两点y值差异较小时,垂线比较陡 若减去20 可能导致箭头太长 { pEnd.x = pStart.x - 2; } else pEnd.x = pStart.x - 20; } else { if (distance < 30) { pEnd.x = pStart.x + 2; } else pEnd.x = pStart.x + 20; } pEnd.y = (int)((pEnd.x - pStart.x) * k2 + pStart.y); } else //若为水平线 { pEnd.x = pStart.x; if (dir.y > pStart.y) pEnd.y = pStart.y + 20; else pEnd.y = pStart.y - 20; } } else //若为垂直线 { pEnd.y = pStart.y; if (dir.x > pStart.x) pEnd.x = pStart.x + 20; else pEnd.x = pStart.x - 20; } //防止越界 pEnd.x = pEnd.x >= 0 ? pEnd.x : 0; pEnd.x = pEnd.x <= GlobelWidth ? pEnd.x : GlobelWidth; pEnd.y = pEnd.y >= 0 ? pEnd.y : 0; pEnd.y = pEnd.y <= GlobelHeight ? pEnd.y : GlobelHeight; if (pROI0.x == pROI1.x) //若为垂直线 { if (pEnd.x > pStart.x) return 1; else return 0; } else if (k1 <= 0) //若不为垂直线且斜率小于等于0(含水平线情况) { if ((pStart.x != pEnd.x && pEnd.x > pStart.x) || (pStart.x == pEnd.x && pEnd.y > pStart.y)) return 0; else return 1; } else { if ((pStart.x != pEnd.x && pEnd.x > pStart.x) || (pStart.x == pEnd.x && pEnd.y > pStart.y)) return 1; else return 0; } } /****************************************************************************** * Function: RSinit * Description: MaskImgData内存非配及VIBE 模型初始化 * Calls: VibeModelInitC3 * Called By: main * Input: nWidth 图像宽度 nHeight 图像高度 frameImgData 图像RGB * Output: vbM VIBE 模型 * Return: 0 输入通道参数不合理 1 正常 *******************************************************************************/ int RegionSurveillance::RSinit(int nWidth, int nHeight, int widthstep, unsigned char* frameImgData, int nChannel, int nChannel_deal, bool nfiltFlag, int minArea, int maxArea) { if(nWidth < 600 || nHeight < 300) //如果尺寸过小 修改vibe参数 VBPARAM = new VIBEPARAM(35, 18); else VBPARAM = new VIBEPARAM(20, 35); //checkMID:软件许可检测 by zl if (/*checkMIDkeySet() == -1 */ checkTime() == -1 || (nChannel != 1 && nChannel != 3) || (nChannel_deal != 1 && nChannel_deal != 3) || (nChannel_deal > nChannel)) { return 0; } channel_num = nChannel; dwGlobalID = 100; GlobelWidth = nWidth; GlobelHeight = nHeight; GlobelWidthstep = widthstep; gfiltFlag = nfiltFlag; OBJECT_AREA_MIN = minArea; //默认最大过滤面积为1,000,000 by zl 20160304 OBJECT_AREA_MAX = maxArea; //默认最小过滤面积为300 by zl 20160304 /* int widthstep = nWidth * 3; if (widthstep % 4) { widthstep = (widthstep / 4 + 1) * 4; } */ MaskImgData = (unsigned char*) malloc(sizeof(unsigned char*) * GlobelWidth * GlobelHeight); memset(MaskImgData, 0, sizeof(unsigned char*)); if (!vbM) { // 初始化模型 if (nChannel == 3) { if (nChannel_deal == 3) { // 高斯模糊 if (nfiltFlag == 1) { unsigned char* inputData = NULL; inputData = new unsigned char[GlobelWidth * GlobelHeight]; int i = 0; while (i < nChannel) { for (int nheight = 0; nheight < GlobelHeight; nheight++) { for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) { inputData[nheight * GlobelWidth + nwidth] = frameImgData[nheight * widthstep + nwidth * nChannel + i]; } } gaussianFilter(inputData, GlobelWidth, GlobelHeight, gWinSize); for (int nheight = 0; nheight < GlobelHeight; nheight++) { for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) { frameImgData[nheight * widthstep + nwidth * nChannel + i] = inputData[nheight * GlobelWidth + nwidth]; } } i++; } delete[] inputData; } vbM = VibeModelInitC3(frameImgData); } else { greyImgData = (unsigned char*) malloc(sizeof(unsigned char*) * GlobelWidth * nHeight); memset(greyImgData, 0, sizeof(unsigned char*)); // 将RGB图像转换为灰度图像 VibeRGBToGray(frameImgData, greyImgData); // 高斯模糊 if (nfiltFlag == 1) { unsigned char* inputData = NULL; inputData = new unsigned char[GlobelWidth * GlobelHeight]; for (int nheight = 0; nheight < GlobelHeight; nheight++) { for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) { inputData[nheight * GlobelWidth + nwidth] = greyImgData[nheight * GlobelWidth + nwidth]; } } gaussianFilter(inputData, GlobelWidth, GlobelHeight, gWinSize); for (int nheight = 0; nheight < GlobelHeight; nheight++) { for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) { greyImgData[nheight * GlobelWidth + nwidth] = inputData[nheight * GlobelWidth + nwidth]; } } delete[] inputData; } vbM = VibeModelInitC1(greyImgData); } } else { // 高斯模糊 if (nfiltFlag == 1) { unsigned char* inputData = NULL; inputData = new unsigned char[GlobelWidth * GlobelHeight]; for (int nheight = 0; nheight < GlobelHeight; nheight++) { for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) { inputData[nheight * GlobelWidth + nwidth] = frameImgData[nheight * widthstep + nwidth]; } } gaussianFilter(inputData, GlobelWidth, GlobelHeight, gWinSize); for (int nheight = 0; nheight < GlobelHeight; nheight++) { for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) { frameImgData[nheight * widthstep + nwidth] = inputData[nheight * GlobelWidth + nwidth]; } } delete[] inputData; } vbM = VibeModelInitC1(frameImgData); } } pConExtraction = new CConExtraction(); left_flag = 1; // 逗留标志 0 遗留 1移除 maskImg = new unsigned char[nWidth*nHeight]; //膨胀和腐蚀 加速用 memset(maskImg, 0, sizeof(maskImg[0])*nWidth*nHeight); //膨胀和腐蚀 加速用 return 1; } VibeModel_t * RegionSurveillance::VibeModelInitC1(uint8_t *image_data) { int32_t x, y, xNG, yNG, index; RandInit(); RandNeighborInit(GlobelWidth, GlobelHeight); vbM = (VibeModel_t *) malloc(sizeof(VibeModel_t)); vbM->width = GlobelWidth; vbM->height = GlobelHeight; vbM->nChannel = 1; vbM->nSample = VBPARAM->P_SAMPLES; vbM->threshold = VBPARAM->P_THRESHOLD; vbM->nMatch = VBPARAM->P_MATCH; vbM->upSpeed = VBPARAM->P_UPSPEED; vbM->widthstep = GlobelWidthstep; vbM->bg_samples = (uint8_t *)malloc(vbM->width * vbM->height * vbM->nSample); for (y = 0; y < GlobelHeight; y++) { for (x = 0; x < GlobelWidth; x++) { for (index = 0; index < vbM->nSample; index++) { GetRandNeighborXY(x, y, &xNG, &yNG); vbM->bg_samples[y * vbM->width * vbM->nSample + x * vbM->nSample + index] = image_data[yNG * vbM->width + xNG]; } } } g_frameCount++; return vbM; } /****************************************************************************** * Function: VibeModelInitC3 * Description: VIBE模型初始化 * Calls: RandInit RandNeighborInit GetRandNeighborXY * Called By: RSinit * Input: image_data 图像RGB * Output: g_XNeighborTable 22100012 g_YNeighborTable 10001222 g_randTable 65536个随机数 g_XTable 0 0 1 2 3 ... 宽度-1 宽度-1 g_YTable 0 0 1 2 3 ... 高度-1 高度-1 * Return: vbM *******************************************************************************/ VibeModel_t* RegionSurveillance::VibeModelInitC3(uint8_t *image_data) { int32_t x, y, xNG, yNG, index; int32_t image_offset = 0, sample_offset = 0; RandInit(); RandNeighborInit(GlobelWidth, GlobelHeight); vbM = (VibeModel_t *) malloc(sizeof(VibeModel_t)); vbM->width = GlobelWidth; vbM->height = GlobelHeight; vbM->nChannel = 3; vbM->widthstep = GlobelWidthstep; vbM->nSample = VBPARAM->P_SAMPLES; vbM->threshold = VBPARAM->P_THRESHOLD; vbM->nMatch = VBPARAM->P_MATCH; vbM->upSpeed = VBPARAM->P_UPSPEED; vbM->bg_samples = (uint8_t *) malloc(vbM->width * vbM->height * 3 * vbM->nSample); for (y = 0; y < GlobelHeight; y++) { for (x = 0; x < GlobelWidth; x++) { for (index = 0; index < vbM->nSample; index++) { GetRandNeighborXY(x, y, &xNG, &yNG); sample_offset = ((y * vbM->width * vbM->nSample + x * vbM->nSample + index) << 1) + (y * vbM->width * vbM->nSample + x * vbM->nSample + index); image_offset = ((yNG * vbM->width + xNG) << 1) + (yNG * vbM->width + xNG); vbM->bg_samples[sample_offset] = image_data[image_offset]; vbM->bg_samples[sample_offset + 1] = image_data[image_offset + 1]; vbM->bg_samples[sample_offset + 2] = image_data[image_offset + 2]; } } } g_frameCount++; return vbM; } void RegionSurveillance::VibeModelUpdateC1(VibeModel_t *model, uint8_t *image, uint8_t *output) { int32_t x, y, xNG, yNG, count, index, dist, sampleOffset, imageOffset; uint32_t rand; for (y = 0; y < model->height; y++) { for (x = 0; x < model->width; x++) { sampleOffset = y * model->width * model->nSample + x * model->nSample; imageOffset = y * model->width + x; // compare pixel to background model count = 0; index = 0; while ((count < model->nMatch) && (index < model->nSample)) { //Euclidean distance computation dist = abs(image[imageOffset] - model->bg_samples[sampleOffset + index]); if (dist < model->threshold) { count++; } index++; } // classify pixel and update model // foreground if (count < model->nMatch) { output[imageOffset] = VBPARAM->DEFAULT_COLOR_FOREGROUND; if (g_frameCount < model->nSample) { rand = GetRand() % (model->nSample); model->bg_samples[sampleOffset + rand] = image[imageOffset]; GetRandNeighborXY(x, y, &xNG, &yNG); rand = GetRand() % (model->nSample); model->bg_samples[yNG * model->width * model->nSample + xNG * model->nSample + rand] = image[imageOffset]; } } else { output[imageOffset] = VBPARAM->DEFAULT_COLOR_BACKGROUND; if (g_frameCount < model->nSample) { rand = GetRand() % (model->nSample); model->bg_samples[sampleOffset + rand] = image[imageOffset]; GetRandNeighborXY(x, y, &xNG, &yNG); rand = GetRand() % (model->nSample); model->bg_samples[yNG * model->width * model->nSample + xNG * model->nSample + rand] = image[imageOffset]; } else { //update current pixel model rand = GetRand() % (model->upSpeed); if (rand == 0 && left_flag == 1) { rand = GetRand() % (model->nSample); model->bg_samples[sampleOffset + rand] = image[imageOffset]; } //update neighboring pixel model rand = GetRand() % (model->upSpeed); if (rand == 0 && left_flag == 1) { GetRandNeighborXY(x, y, &xNG, &yNG); rand = GetRand() % (model->nSample); model->bg_samples[yNG * model->width * model->nSample + xNG * model->nSample + rand] = image[imageOffset]; } } } }// end of for x loop }// end of for y loop VibeModelDilation2(output, maskImg, model->width, model->height);// 膨胀 VibeModelErosion2(maskImg, output, model->width, model->height);// 腐蚀 //未加速版本 //VibeModelDilation(output, model->width, model->height);// 膨胀 //VibeModelErosion(output, model->width, model->height);// 腐蚀 g_frameCount++; } /****************************************************************************** * Function: VibeModelUpdateC3 * Description: VIBE模型更新 * Calls: GetRand GetRandNeighborXY VibeModelDilation VibeModelErosion * Called By: RSDetect * Input: model VBM 模型 image 图像RGB * Output: output 前景是255 背景是0 model VBM 模型 *******************************************************************************/ void RegionSurveillance::VibeModelUpdateC3(VibeModel_t *model, uint8_t *image, uint8_t *output) { int32_t x, y, xNG, yNG; int32_t count, index; double dist; int32_t sampleOffset, imageOffset; uint32_t rand; int tmpValue = 0; int countArry = 0; for (y = 0; y < model->height; y++) { for (x = 0; x < model->width; x++) { // 当前点对应的模板中的索引 sampleOffset = ((y * model-> width * model->nSample + x * model->nSample) << 1) + (y * model-> width * model->nSample + x * model->nSample); // 当前点对应的RGB中的索引 imageOffset = ((y * model->width + x) << 1) + (y * model->width + x); // if (imageOffset>=(model->width * model->height)) // int sDEBUG=1; //compare pixel to background model count = 0; index = 0; // 如果当前满足阈值的点数小于规定匹配点数 且 当前评估的点数小于20个点 while ((count < model->nMatch) && (index < model->nSample)) { //Euclidean distance computation tmpValue = sampleOffset + ((index << 1) + index); dist = (double)((image[imageOffset] - model->bg_samples[tmpValue ])*(image[imageOffset] - model->bg_samples[tmpValue])) + (double)((image[imageOffset + 1] - model->bg_samples[tmpValue + 1])*(image[imageOffset + 1] - model->bg_samples[tmpValue+ 1])) + (double)((image[imageOffset + 2] - model->bg_samples[tmpValue + 2])*(image[imageOffset + 2] - model->bg_samples[tmpValue + 2])); // 三通道计算距离之和 //dist = abs(image[imageOffset] - model->bg_samples[tmpValue]) + abs(image[imageOffset + 1] - model->bg_samples[tmpValue + 1]) //+ abs(image[imageOffset + 2] - model->bg_samples[tmpValue + 2]); // 满足阈值条件的点 if (dist < model->threshold * model->threshold * 3) { count++; } index++; } // 如果当前点为前景 if (count < model->nMatch) { output[y * model->width + x] = VBPARAM->DEFAULT_COLOR_FOREGROUND; // 前20帧增加模板信息 if (g_frameCount < model->nSample) { // 随机更新当前点对应的模板中的某一背景 rand = GetRand() % (model->nSample); tmpValue = sampleOffset + ((rand << 1) +rand ); model->bg_samples[tmpValue] = image[imageOffset]; model->bg_samples[tmpValue + 1] = image[imageOffset + 1]; model->bg_samples[tmpValue + 2] = image[imageOffset + 2]; // 同时随机对当前点的某一个相邻点对应的模板中的随机一背景进行更新 GetRandNeighborXY(x, y, &xNG, &yNG); rand = GetRand() % (model->nSample); tmpValue = ((yNG * model->width * model->nSample + xNG * model->nSample + rand) << 1)+ (yNG * model->width * model->nSample + xNG * model->nSample + rand); model->bg_samples[tmpValue] = image[imageOffset]; model->bg_samples[tmpValue + 1] = image[imageOffset + 1]; model->bg_samples[tmpValue + 2] = image[imageOffset + 2]; } } // 如果当前点为背景 else { output[y * model->width + x] = VBPARAM->DEFAULT_COLOR_BACKGROUND; // 对前20帧进行VIBE模板更新(同前景) if (g_frameCount < model->nSample) { //curr rand = GetRand() % (model->nSample); tmpValue = sampleOffset + ((rand << 1) + rand); model->bg_samples[tmpValue] = image[imageOffset]; model->bg_samples[tmpValue + 1] = image[imageOffset + 1]; model->bg_samples[tmpValue + 2] = image[imageOffset + 2]; //neighbor GetRandNeighborXY(x, y, &xNG, &yNG); rand = GetRand() % (model->nSample); tmpValue = ((yNG * model->width * model->nSample + xNG * model->nSample + rand) << 1) + (yNG * model->width * model->nSample + xNG * model->nSample + rand) ; model->bg_samples[tmpValue] = image[imageOffset]; model->bg_samples[tmpValue + 1] = image[imageOffset + 1]; model->bg_samples[tmpValue + 2] = image[imageOffset + 2]; } else { //update current pixel model rand = GetRand() % (model->upSpeed); if (rand == 0 && left_flag == 1) { rand = GetRand() % (model->nSample); tmpValue = sampleOffset + ((rand << 1) + rand); model->bg_samples[tmpValue] = image[imageOffset]; model->bg_samples[tmpValue + 1] = image[imageOffset + 1]; model->bg_samples[tmpValue + 2] = image[imageOffset + 2]; } //update neighboring pixel model // 满足条件才进行背景更新(为了提速) rand = GetRand() % (model->upSpeed); if (rand == 0 && left_flag == 1) { GetRandNeighborXY(x, y, &xNG, &yNG); rand = GetRand() % (model->nSample); tmpValue = ((yNG * model->width * model->nSample + xNG * model->nSample + rand) << 1) + (yNG * model->width * model->nSample + xNG * model->nSample + rand); model->bg_samples[tmpValue] = image[imageOffset]; model->bg_samples[tmpValue + 1] = image[imageOffset + 1]; model->bg_samples[tmpValue + 2] = image[imageOffset + 2]; } } /////////////////////////////////////////////////////////////////////////////////////////////// //bkImageData[imageOffset] =(bkImageData[imageOffset] + image[imageOffset]) >> 1; //bkImageData[imageOffset + 1] =(bkImageData[imageOffset + 1] + image[imageOffset + 1]) >> 1; //bkImageData[imageOffset + 2] =(bkImageData[imageOffset + 2] + image[imageOffset + 2]) >> 1; /////////////////////////////////////////////////////////////////////////////////////////////// } }// end of for x loop }// end of for y loop //VibeModelDilation(output, model->width, model->height); // 膨胀 //VibeModelErosion(output, model->width, model->height);// 腐蚀 VibeModelDilation2(output, maskImg, model->width, model->height); // 加速 膨胀 VibeModelErosion2(maskImg, output, model->width, model->height); // 加速 膨胀 //VibeModelErosion(output,model->width,model->height); g_frameCount++; //VibeModelGetTrace(output,image,model->width,model->height,model->widthstep); } #include void RegionSurveillance::RSinit_backgroud(int nWidth, int nHeight, int channels, unsigned char* frameImgData) { pConExtraction->InitBackgroud(frameImgData, nWidth, nHeight, channels); } void RegionSurveillance::RSDetect(unsigned char* frameImgData, RegionInfo* pRegionInfo) { /* int widthstep = nWidth * 3; if (widthstep % 4) { widthstep = (widthstep / 4 + 1) * 4; } */ // 获得当前帧的前景和背景(前景255 背景0)同时对VIBE模板进行更新 //VibeModelUpdateC3(vbM, frameImgData, greyImgData, MaskImgData); //if (vbM->nChannel == 3) //{ // // 高斯模糊 // if (gfiltFlag == 1) // { // unsigned char* inputData = NULL; // inputData = new unsigned char[GlobelWidth * GlobelHeight]; // int i = 0; // while (i < 3) // { // for (int nheight = 0; nheight < GlobelHeight; nheight++) // { // for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) // { // inputData[nheight * GlobelWidth + nwidth] = frameImgData[nheight * GlobelWidthstep + nwidth * 3 + i]; // } // } // gaussianFilter(inputData, GlobelWidth, GlobelHeight, gWinSize); // for (int nheight = 0; nheight < GlobelHeight; nheight++) // { // for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) // { // frameImgData[nheight * GlobelWidthstep + nwidth * 3 + i] = inputData[nheight * GlobelWidth + nwidth]; // } // } // i++; // } // delete[] inputData; // } // VibeModelUpdateC3(vbM, frameImgData, MaskImgData); //} //else //{ // if (channel_num == 3) // { // // 将RGB图像转换为灰度图像 // VibeRGBToGray(frameImgData, greyImgData); // // 高斯模糊 // if (gfiltFlag == 1) // { // unsigned char* inputData = NULL; // inputData = new unsigned char[GlobelWidth * GlobelHeight]; // // for (int nheight = 0; nheight < GlobelHeight; nheight++) // { // for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) // { // inputData[nheight * GlobelWidth + nwidth] = greyImgData[nheight * GlobelWidth + nwidth]; // } // } // gaussianFilter(inputData, GlobelWidth, GlobelHeight, gWinSize); // for (int nheight = 0; nheight < GlobelHeight; nheight++) // { // for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) // { // greyImgData[nheight * GlobelWidth + nwidth] = inputData[nheight * GlobelWidth + nwidth]; // } // } // // delete[] inputData; // } // // VibeModelUpdateC1(vbM, greyImgData, MaskImgData); // } // else // { // // 高斯模糊 // if (gfiltFlag == 1) // { // unsigned char* inputData = NULL; // inputData = new unsigned char[GlobelWidth * GlobelHeight]; // for (int nheight = 0; nheight < GlobelHeight; nheight++) // { // for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) // { // inputData[nheight * GlobelWidth + nwidth] = frameImgData[nheight * GlobelWidthstep + nwidth]; // } // } // gaussianFilter(inputData, GlobelWidth, GlobelHeight, gWinSize); // for (int nheight = 0; nheight < GlobelHeight; nheight++) // { // for (int nwidth = 0; nwidth < GlobelWidth; nwidth++) // { // frameImgData[nheight * GlobelWidthstep + nwidth] = inputData[nheight * GlobelWidth + nwidth]; // } // } // delete[] inputData; // } // VibeModelUpdateC1(vbM, frameImgData, MaskImgData); // } // //VibeModelUpdateC1(vbM, greyImgData, MaskImgData); //} // 显示二值图像 /*CvSize a; a.width = GlobelWidth; a.height = GlobelHeight; IplImage *im = cvCreateImage(a, 8, 1); im->imageData = (char*)MaskImgData; cvShowImage("L2", im); cvWaitKey(0);*/ /*{ cv::Mat tmp_image(GlobelHeight, GlobelWidth, cv::CV_8UC3, pRGBIn); cv::imshow("res", tmp_image); cv::waitKey(1); }*/ //get trace VibeModelGetTrace(MaskImgData, frameImgData, pRegionInfo); } /****************************************************************************** * Function: VibeModelDilation * Description: VIBE模型膨胀(如果当前点为前景或者当前点的邻域中有一个为前景,则当前点位前景) * Called By: VibeModelUpdateC3 * Input: inputdata 当前图像前景背景(前景为255 背景为0) width 图像宽度 height 图像高度 * Output: inputdata 膨胀后当前图像前景背景 *******************************************************************************/ void RegionSurveillance::VibeModelDilation(unsigned char* inputdata, int width, int height) { int i, j; //sum = height * width * sizeof(unsigned char); //unsigned char *tmpdata = (unsigned char*) malloc(sum); //memcpy((unsigned char*)tmpdata, (unsigned char*)inputdata, sum); for (i = 1; i < height - 1; i++) { for (j = 1; j < width - 1; j++) { if (inputdata[i * width + j] == 255) { } else { if (inputdata[(i - 1) * width + j - 1] == 255 || inputdata[(i - 1) * width + j] == 255 || inputdata[(i - 1) * width + j + 1] == 255 || inputdata[i * width + j - 1] == 255 || inputdata[i * width + j + 1] == 255 || inputdata[(i + 1) * width + j - 1] == 255 || inputdata[(i + 1) * width + j] == 255 || inputdata[(i + 1) * width + j + 1] == 255) { inputdata[i * width + j] = 250; } } } } for (i = 1; i < height - 1; i++) { for (j = 1; j < width - 1; j++) { if (inputdata[i * width + j] == 250) { inputdata[i * width + j] = 255; } } } } /****************************************************************************** * Function: VibeModelErosion * Description: VIBE模型腐蚀(如果当前点或当前点的某一个邻域中有一个点为背景,则当前为背景) * Called By: VibeModelUpdateC3 * Input: inputdata 当前图像前景背景(前景为255 背景为0) width 图像宽度 height 图像高度 * Output: inputdata 腐蚀后当前图像前景背景 *******************************************************************************/ void RegionSurveillance::VibeModelErosion(unsigned char* inputdata, int width, int height) { int i, j; //sum = height * width * sizeof(unsigned char); //unsigned char *tmpdata = (unsigned char*) malloc(sum); //memcpy((unsigned char*) tmpdata, (unsigned char*) inputdata, sum); for (i = 1; i < height - 1; i++) { for (j = 1; j < width - 1; j++) { if (inputdata[i * width + j] == 0) { } else { if (inputdata[(i - 1) * width + j - 1] == 0 || inputdata[(i - 1) * width + j] == 0 || inputdata[(i - 1) * width + j + 1] == 0 || inputdata[i * width + j - 1] == 0 || inputdata[i * width + j + 1] == 0 || inputdata[(i + 1) * width + j - 1] == 0 || inputdata[(i + 1) * width + j] == 0 || inputdata[(i + 1) * width + j + 1] == 0) { inputdata[i * width + j] = 5; } } } } for (i = 1; i < height - 1; i++) { for (j = 1; j < width - 1; j++) { if (inputdata[i * width + j] == 5) { inputdata[i * width + j] = 0; } } } } void RegionSurveillance::VibeModelDilation2(unsigned char* inputdata,unsigned char *output, int width,int height) { memset(output, 0, sizeof(output[0])*width*height); if (width<32 || height<32 || inputdata==NULL || output==NULL) return; unsigned char *src = inputdata; unsigned char *dst = output; //memcpy(output, inputdata, width*height); for (int i=0; i &ForegroundArray) { std::sort(ForegroundArray.begin(),ForegroundArray.end(), SortByPoint); } /****************************************************************************** * Function: VibeModelGetTrace * Description: * Calls: ExtractContours * Called By: RSDetect * Input: pSourceImg 当前图像前景背景(前景为255 背景为0) pRGBIn 当前图像RGB width 图像宽度 height 图像高度 widthStep 图像RGB step * Output: pRGBIn 将前景描绘过的RGB m_TargetArray m_ptArray 与当前目标匹配成功的所有前景的中心点 m_VectorDirection 当前目标与之前目标的向量 //m_VectorDirectionNormal dx/sqrt(dx^2+dy^2) dy/sqrt(dx^2+dy^2) m_CurRefPoint 目标的中心点位置(不断更新,取5个的平均值) m_LastRefPoint 目标之前的中心点位置(不断更新,取5个的平均值) m_PredictionBasePoint 最后一个匹配点中心位置 m_PredictionPoint 下一帧的预测位置 m_bHaveDirection 当前目标是否已经计算过方向 true是 flase否 m_dwLostFrame 距当前帧未匹配到的数目(用来判断是否目标丢失) m_dwID ID 用来对不同的前景绘图时进行颜色上的区分 m_dwBestMatch 匹配到当前帧的前景序号 m_bCalc 标志目标序列在当前帧中是否匹配到 true匹配到 false未匹配到 m_AlarmState 报警状态 false否 true报警 m_AlarmNum 报警编号 //m_TarBox 目标的外接矩形 *******************************************************************************/ #include void RegionSurveillance::VibeModelGetTrace(unsigned char* pSourceImg, unsigned char* pRGBIn, RegionInfo* pRegionInfo) { //cv::Mat image2(GlobelHeight, GlobelWidth, CV_8UC1, pRGBIn); /* memset(regionAlarm, 0, sizeof(bool) * MAXROINUM); */ vector ForegroundArray; int m_dwFrameDist = 11; int m_dwFrameWnd = 5; int m_MaxDistance = 20; int m_InitMaxDistance =20; int m_dwMaxLost = 100; int m_dwMinFrame = 6; int dwTargetSize = 0; CForeground testTarget; // testForgroundArray 中的testTarget //前景图集合-zhm vector foreContours; // 满足条件的(像素点 面积等条件100)前景外接矩形 if (channel_num == 3) { foreContours = pConExtraction->ExtractContours(pSourceImg, GlobelWidth, GlobelHeight, GlobelWidthstep / 3); } else { //foreContours = pConExtraction->ExtractContours_Canny(pRGBIn, GlobelWidth, GlobelHeight, GlobelWidthstep); //foreContours = pConExtraction->ExtractContours(pSourceImg, GlobelWidth, GlobelHeight, GlobelWidthstep); foreContours = pConExtraction->ExtractContours_PixelSub(pRGBIn, GlobelWidth, GlobelHeight, GlobelWidthstep); } //轨迹匹配-zhm // 进一步在foreContours的基础上对前景外接矩形的面积进行筛选 将满足面积大于300的外接矩形添入ForegroundArray中 int forNum = foreContours.size(); for (int i = 0; i < forNum; i++) { //tmp_Contour = foreContours[i]; testTarget.m_rtConnect.left = foreContours[i].left; testTarget.m_rtConnect.right = foreContours[i].right; testTarget.m_rtConnect.top = foreContours[i].top; testTarget.m_rtConnect.bottom = foreContours[i].bottom; testTarget.m_ptCenter.x = (testTarget.m_rtConnect.left + testTarget.m_rtConnect.right) / 2; testTarget.m_ptCenter.y = (testTarget.m_rtConnect.top + testTarget.m_rtConnect.bottom) / 2; //大于最小过滤面积且小于最大过滤面积 by zl 20160304 int targetArea = abs((testTarget.m_rtConnect.left - testTarget.m_rtConnect.right) * (testTarget.m_rtConnect.top - testTarget.m_rtConnect.bottom)); if ( targetArea > OBJECT_AREA_MIN && targetArea < OBJECT_AREA_MAX) { ForegroundArray.push_back(testTarget); } } if (ForegroundArray.size() > 0) //前景库不空则排序处理 by zl 20160307 { SortForeground(ForegroundArray); /*for (int i = 0; i < ForegroundArray.size(); i++) { printf("i=%d l=%d t=%d r=%d b=%d\n", i, ForegroundArray[i].m_rtConnect.left, ForegroundArray[i].m_rtConnect.top, ForegroundArray[i].m_rtConnect.right, ForegroundArray[i].m_rtConnect.bottom); }*/ MergeNeighborBox(ForegroundArray); /* for (int i = 0; i < ForegroundArray.size(); i++) { printf("i=%d l=%d t=%d r=%d b=%d\n", i, ForegroundArray[i].m_rtConnect.left, ForegroundArray[i].m_rtConnect.top, ForegroundArray[i].m_rtConnect.right, ForegroundArray[i].m_rtConnect.bottom); }*/ DislodgeOverlapBox(ForegroundArray); } //20140305 foreContours.clear(); vector().swap(foreContours); { std::vectortmp = foreContours; foreContours.swap(tmp); } // memory leak for 1 block //判断是否帧内目标丢失,若丢失dwTargetSize自减 vector::size_type countn = 0; int dwStep = GlobelWidthstep; ///////////////////////////////////////////////////////////////////////////////////////// dwTargetSize = m_TargetArray.size(); for (int i = 0; i < dwTargetSize; i++, countn++) { // 若已经超过100帧未出现该前景 则将该前景从m_TargetArray中删除 if (m_TargetArray[i].m_dwLostFrame++ > m_dwMaxLost) { m_TargetArray.erase(m_TargetArray.begin() + countn); dwTargetSize--; i--; countn--; } else { m_TargetArray[i].m_bCalc = false; m_TargetArray[i].m_dwBestMatch = -1; } } // Calculate distance matrix and determine every target's best match int dwForegroundCount = ForegroundArray.size(); //m_TargetArray.clear(); dwTargetSize = m_TargetArray.size(); double * pDistanceMatrix = new double[dwForegroundCount * dwTargetSize]; // 将每一个目标和该帧中的前景进行匹配 for (int i = 0; i < dwTargetSize; i++) { //CMPointDouble directionPre; double Distance = m_TargetArray[i].m_bHaveDirection ? m_MaxDistance : m_InitMaxDistance; for (int j = 0; j < dwForegroundCount; j++) { //directionPre.x = ForegroundArray[j].m_ptCenter.x - m_TargetArray[i].m_CurRefPoint.x; //directionPre.y = ForegroundArray[j].m_ptCenter.y - m_TargetArray[i].m_CurRefPoint.y; pDistanceMatrix[i * dwForegroundCount + j] = sqrt((ForegroundArray[j].m_ptCenter.x - m_TargetArray[i].m_PredictionPoint.x) * (ForegroundArray[j].m_ptCenter.x - m_TargetArray[i].m_PredictionPoint.x) + (ForegroundArray[j].m_ptCenter.y - m_TargetArray[i].m_PredictionPoint.y) * (ForegroundArray[j].m_ptCenter.y - m_TargetArray[i].m_PredictionPoint.y)); /* double directionResult = m_TargetArray[i].m_VectorDirectionNormal.cx * directionPre.x + m_TargetArray[i].m_VectorDirectionNormal.cy * directionPre.y; */ if (pDistanceMatrix[i * dwForegroundCount + j] <= Distance ) //&& directionResult >= 0 { Distance = pDistanceMatrix[i * dwForegroundCount + j]; m_TargetArray[i].m_dwBestMatch = j; m_TargetArray[i].m_TarBox = ForegroundArray[j].m_rtConnect; } } } // no leak after --> //delete []pDistanceMatrix; ///////////////////////////////////////////////////////////////////////////////////////////////////// m_FinalArray.clear(); // Tracking and draw // 对当前帧的每一个前景与目标进行匹配 bool left_flag_c = 1; for (int i = 0; i < dwForegroundCount; i++) { int dwBestMatch = -1; double Distance = m_MaxDistance > m_InitMaxDistance ? m_MaxDistance : m_InitMaxDistance; for (int j = 0; j < dwTargetSize; j++) { if (m_TargetArray[j].m_bHaveDirection) { if (pDistanceMatrix[j * dwForegroundCount + i] <= Distance && pDistanceMatrix[j * dwForegroundCount + i] <= m_MaxDistance) { Distance = pDistanceMatrix[j * dwForegroundCount + i]; dwBestMatch = j; } } else { if (pDistanceMatrix[j * dwForegroundCount + i] <= Distance && pDistanceMatrix[j * dwForegroundCount + i] <= m_InitMaxDistance) { Distance = pDistanceMatrix[j * dwForegroundCount + i]; dwBestMatch = j; } } } //m_TargetArray.clear(); // 如果匹配成功 m_TargetArray[dwBestMatch].m_ptArray.size() !=500??????????????????????不理解为什么不能等于500 if (dwBestMatch >= 0 && m_TargetArray[dwBestMatch].m_dwBestMatch == i && m_TargetArray[dwBestMatch].m_ptArray.size() < 500) { // Find it m_TargetArray[dwBestMatch].m_bCalc = true; //m_TargetArray[dwBestMatch].m_AlarmState = false; //m_TargetArray[dwBestMatch].m_AlarmState1 = false; //m_TargetArray[dwBestMatch].m_AlarmState2 = false; //m_TargetArray[dwBestMatch].m_AlarmState3 = false; //m_TargetArray[dwBestMatch].m_AlarmState4 = false; //m_TargetArray[dwBestMatch].m_AlarmState5 = false; m_TargetArray[dwBestMatch].m_dwLostFrame = 0; m_TargetArray[dwBestMatch].m_ptArray.push_back(ForegroundArray[i].m_ptCenter); // Update current reference point int dwPointCount = m_TargetArray[dwBestMatch].m_ptArray.size(); m_TargetArray[dwBestMatch].m_CurRefPoint.x += (double)ForegroundArray[i].m_ptCenter.x / m_dwFrameWnd; m_TargetArray[dwBestMatch].m_CurRefPoint.y += (double)ForegroundArray[i].m_ptCenter.y / m_dwFrameWnd; if (dwPointCount > m_dwFrameWnd) { m_TargetArray[dwBestMatch].m_CurRefPoint.x -= (double) m_TargetArray[dwBestMatch].m_ptArray[dwPointCount - m_dwFrameWnd - 1].x / m_dwFrameWnd; m_TargetArray[dwBestMatch].m_CurRefPoint.y -= (double) m_TargetArray[dwBestMatch].m_ptArray[dwPointCount - m_dwFrameWnd - 1].y / m_dwFrameWnd; } // Update last reference point // 如果与目标匹配成功的前景达到一定数量 if (dwPointCount > m_dwFrameDist) { // 目标之前的中心点位置(5帧帧平均) m_TargetArray[dwBestMatch].m_LastRefPoint.x += (double) m_TargetArray[dwBestMatch].m_ptArray[dwPointCount - m_dwFrameDist - 1].x / m_dwFrameWnd; m_TargetArray[dwBestMatch].m_LastRefPoint.y += (double) m_TargetArray[dwBestMatch].m_ptArray[dwPointCount - m_dwFrameDist - 1].y / m_dwFrameWnd; if (dwPointCount >= m_dwFrameDist + m_dwFrameWnd) { if (dwPointCount > m_dwFrameDist + m_dwFrameWnd) { m_TargetArray[dwBestMatch].m_LastRefPoint.x -= (double) m_TargetArray[dwBestMatch].m_ptArray[dwPointCount - m_dwFrameDist - m_dwFrameWnd - 1].x / m_dwFrameWnd; m_TargetArray[dwBestMatch].m_LastRefPoint.y -= (double) m_TargetArray[dwBestMatch].m_ptArray[dwPointCount - m_dwFrameDist - m_dwFrameWnd - 1].y / m_dwFrameWnd; } // Calculate direction m_TargetArray[dwBestMatch].m_bHaveDirection = true; m_TargetArray[dwBestMatch].m_PredictionBasePoint = m_TargetArray[dwBestMatch].m_CurRefPoint; m_TargetArray[dwBestMatch].m_VectorDirection.cx = (m_TargetArray[dwBestMatch].m_CurRefPoint.x - m_TargetArray[dwBestMatch].m_LastRefPoint.x) / m_dwFrameDist; m_TargetArray[dwBestMatch].m_VectorDirection.cy = (m_TargetArray[dwBestMatch].m_CurRefPoint.y - m_TargetArray[dwBestMatch].m_LastRefPoint.y) / m_dwFrameDist; /* m_TargetArray[dwBestMatch].m_VectorDirectionNormal.cx = m_TargetArray[dwBestMatch].m_VectorDirection.cx /(sqrt(m_TargetArray[dwBestMatch].m_VectorDirection.cx * m_TargetArray[dwBestMatch].m_VectorDirection.cx + m_TargetArray[dwBestMatch].m_VectorDirection.cy * m_TargetArray[dwBestMatch].m_VectorDirection.cy)); m_TargetArray[dwBestMatch].m_VectorDirectionNormal.cy = m_TargetArray[dwBestMatch].m_VectorDirection.cy /(sqrt(m_TargetArray[dwBestMatch].m_VectorDirection.cx * m_TargetArray[dwBestMatch].m_VectorDirection.cx + m_TargetArray[dwBestMatch].m_VectorDirection.cy * m_TargetArray[dwBestMatch].m_VectorDirection.cy)); */ } } } else { // 检测到新的目标 // New object found CTarget NewTarget; //NewTarget.GetID(); NewTarget.m_dwID= ++dwGlobalID; // GlobalID assigned for target // 新的前景的中心位置 NewTarget.m_ptArray.push_back(ForegroundArray[i].m_ptCenter); m_TargetArray.push_back(NewTarget); NewTarget.m_ptArray.clear(); vector().swap(NewTarget.m_ptArray); { std::vectortmp = NewTarget.m_ptArray; NewTarget.m_ptArray.swap(tmp); } dwBestMatch = m_TargetArray.size() - 1; // Update current reference point //m_TargetArray-m_CurRefPoint当前前景的中心点位置(取五帧的平均数) m_TargetArray[dwBestMatch].m_CurRefPoint.x += (double)ForegroundArray[i].m_ptCenter.x / m_dwFrameWnd; m_TargetArray[dwBestMatch].m_CurRefPoint.y += (double)ForegroundArray[i].m_ptCenter.y / m_dwFrameWnd; m_TargetArray[dwBestMatch].m_TarBox = ForegroundArray[i].m_rtConnect; } MonitoringAlarm(pRGBIn, ForegroundArray[i], dwBestMatch, pRegionInfo); if (left_flag_c == 0) { } else { if (left_flag_now_s ==0 || left_flag_now_w == 0) { left_flag_c = 0; } } //保存最终输出目标 m_FinalArray.push_back(m_TargetArray[dwBestMatch]); } left_flag = left_flag_c; // Release resources delete []pDistanceMatrix; ForegroundArray.clear(); // suxiaoyun //ForegroundArray.swap(vector(0)); //std::vector(ForegroundArray).swap(ForegroundArray); vector().swap(ForegroundArray); { std::vectortmp = ForegroundArray; ForegroundArray.swap(tmp); } /////////////////////////////////////////////////////////////////////////////////////// // Prediction int dwObjectCount = m_TargetArray.size(); // 遍历所有的目标 for (int i=0; i < dwObjectCount; i++) { // 如果该目标在当前帧中没有匹配成功但是当前目标已经计算过方向 if (!m_TargetArray[i].m_bCalc && m_TargetArray[i].m_bHaveDirection) { // Record prediction as current point m_TargetArray[i].m_ptArray.push_back(CMPoint((long) (m_TargetArray[i].m_PredictionPoint.x + 0.5), (long) (m_TargetArray[i].m_PredictionPoint.y + 0.5))); // Update current reference point int dwPointCount = m_TargetArray[i].m_ptArray.size(); m_TargetArray[i].m_CurRefPoint.x += (double) m_TargetArray[i].m_ptArray[dwPointCount - 1].x / m_dwFrameWnd; m_TargetArray[i].m_CurRefPoint.y += (double) m_TargetArray[i].m_ptArray[dwPointCount - 1].y / m_dwFrameWnd; if (dwPointCount > m_dwFrameWnd) { m_TargetArray[i].m_CurRefPoint.x -= (double) m_TargetArray[i].m_ptArray[dwPointCount - m_dwFrameWnd - 1].x / m_dwFrameWnd; m_TargetArray[i].m_CurRefPoint.y -= (double) m_TargetArray[i].m_ptArray[dwPointCount - m_dwFrameWnd - 1].y / m_dwFrameWnd; } // Update last reference point if (dwPointCount > m_dwFrameDist) { m_TargetArray[i].m_LastRefPoint.x += (double) m_TargetArray[i].m_ptArray[dwPointCount - m_dwFrameDist - 1].x / m_dwFrameWnd; m_TargetArray[i].m_LastRefPoint.y += (double) m_TargetArray[i].m_ptArray[dwPointCount - m_dwFrameDist - 1].y / m_dwFrameWnd; if (dwPointCount >= m_dwFrameDist + m_dwFrameWnd) { if (dwPointCount > m_dwFrameDist + m_dwFrameWnd) { m_TargetArray[i].m_LastRefPoint.x -= (double) m_TargetArray[i].m_ptArray[dwPointCount - m_dwFrameDist - m_dwFrameWnd - 1].x / m_dwFrameWnd; m_TargetArray[i].m_LastRefPoint.y -= (double) m_TargetArray[i].m_ptArray[dwPointCount - m_dwFrameDist - m_dwFrameWnd - 1].y / m_dwFrameWnd; } } } } if (m_TargetArray[i].m_bHaveDirection) { // Calculate prediction point m_TargetArray[i].m_PredictionPoint.x = m_TargetArray[i].m_PredictionBasePoint.x + m_TargetArray[i].m_VectorDirection.cx * (m_TargetArray[i].m_dwLostFrame + m_dwFrameWnd / 2 + 1); m_TargetArray[i].m_PredictionPoint.y = m_TargetArray[i].m_PredictionBasePoint.y + m_TargetArray[i].m_VectorDirection.cy * (m_TargetArray[i].m_dwLostFrame + m_dwFrameWnd / 2 + 1); } else { m_TargetArray[i].m_PredictionPoint.x = (double) m_TargetArray[i].m_ptArray[m_TargetArray[i].m_ptArray.size() - 1].x; m_TargetArray[i].m_PredictionPoint.y = (double) m_TargetArray[i].m_ptArray[m_TargetArray[i].m_ptArray.size() - 1].y; } } } /****************************************************************************** * Function: RSRegion * Description: 感兴趣区域设置 * Calls: vibeMask * Called By: main * Input: numROI ROI个数 pRegionInfo ROI区域 iflog true:输出日志 false:不输出日志 * Output: pRegion 10个ROI指针(bool)每个大小为(图像宽*图像高)感兴趣区域值为1 其余为0 //regionAlarm 10个ROI 报警标志(bool) pAlarmInfo 10个ROI 报警标志(int) * Return: 3 1 *******************************************************************************/ void printAlarmType(fstream *file, int style) { switch (style) { case 1: *file<<"进入禁区, "; break; case 2: *file<<"离开禁区, "; break; case 3: *file<<"单向越界, "; break; case 4: *file<<"双向越界, "; break; case 5: *file<<"徘徊, "; break; case 6: *file<<"丢包, "; break; default : break; } } int RegionSurveillance::RSRegion(int numROI, RegionInfo* pRegionInfo, bool iflog) { fstream file;//用于输出日志 if (numROI > MAXROINUM) { return 0; } //自动设置用于确定方向的点 for(int i = 0; i < numROI; i++) { if (iflog) { file.open("log.txt",ios::app); file<> regions; regions.resize(numROI); for (int i = 0; i < numROI; i++) { for (int j = 0; j < pRegionInfo[i].nPointNum; j++) { Point cur_point{ pRegionInfo[i].pROI[j].x, pRegionInfo[i].pROI[j].y}; regions[i].push_back(cur_point); } } pConExtraction->CalMask(regions, GlobelWidth, GlobelHeight); return 1; } void RegionSurveillance::vibeMask(int num, CMPoint *pPointList, bool *pRegion) { if (num == 2) { double s; int i, x, y; int xs, ys; int dx, dy; dx = pPointList[1].x - pPointList[0].x; if (dx < 0) { dx = -dx; } dy = pPointList[1].y - pPointList[0].y; if (dy < 0) { dy = -dy; } if (dy < dx) { //draw according to x-y s = (double) (pPointList[1].y - pPointList[0].y) / (pPointList[1].x - pPointList[0].x); if (pPointList[0].x < pPointList[1].x) { xs = pPointList[0].x; ys = pPointList[0].y; } else { xs = pPointList[1].x; ys = pPointList[1].y; } for (i = 0; i <= dx; i++) { x = i + xs; y = (int) ((double) i * s) + ys; if (x > -1 && x < GlobelWidth && y > -1&& y < GlobelHeight) { pRegion[GlobelWidth * y + x] = 1; } } } else { //draw according to y-x s = (double) (pPointList[1].x - pPointList[0].x) / (pPointList[1].y - pPointList[0].y); if (pPointList[0].y < pPointList[1].y) { xs = pPointList[0].x; ys = pPointList[0].y; } else { xs = pPointList[1].x; ys = pPointList[1].y; } for (i = 0; i <= dy; i++) { y = i + ys; x = (int) ((double) i * s)+xs; if (y > -1 && y < GlobelHeight && x > -1 && x < GlobelWidth) { pRegion[GlobelWidth * y + x] = 1; } } } } else if (num >= 3) { CMPoint LineMin; CMPoint LineMax; for (int k=0; k < num; k++) { int startp = k; int endp = k + 1; if (startp == num - 1) { endp = 0; } if (abs(pPointList[startp].x - pPointList[endp].x) >= abs(pPointList[startp].y - pPointList[endp].y)) { if (pPointList[startp].x < pPointList[endp].x) { LineMin = pPointList[startp]; LineMax = pPointList[endp]; for (int x = LineMin.x; x <= LineMax.x; x++) { int y = (int) (((LineMin.y - LineMax.y) / (double) (LineMin.x - LineMax.x)) * (double) (x - LineMin.x) + 0.5 + (double)LineMin.y); //pRegion[GlobelWidth * y + x] = 1; //原程序存在越界 苏晓芸修改如下 if (y > -1 && y < GlobelHeight && x > -1 && x < GlobelWidth) { pRegion[GlobelWidth * y + x] = 1; } } } else if (pPointList[startp].x > pPointList[endp].x) { LineMin = pPointList[endp]; LineMax = pPointList[startp]; for (int x = LineMin.x; x <= LineMax.x; x++) { int y = (int) (((LineMin.y - LineMax.y) / (double)(LineMin.x - LineMax.x)) * (double)(x - LineMin.x) + 0.5 + (double)LineMin.y); //pRegion[GlobelWidth * y + x] = 1; //原程序存在越界 苏晓芸修改如下 if (y > -1 && y < GlobelHeight && x > -1 && x < GlobelWidth) { pRegion[GlobelWidth * y + x] = 1; } } } else { int YMin = (pPointList[startp].y < pPointList[endp].y)? pPointList[startp].y : pPointList[endp].y; int YMax = (pPointList[startp].y < pPointList[endp].y)? pPointList[endp].y : pPointList[startp].y; for (int i = YMin; i <= YMax; i++) { //pRegion[GlobelWidth * i + pPointList[startp].x] = 1; //原程序存在越界 苏晓芸修改如下 if (i > -1 && i < GlobelHeight && pPointList[startp].x > -1 && pPointList[startp].x < GlobelWidth) { pRegion[GlobelWidth * i + pPointList[startp].x] = 1; } } } } else { if (pPointList[startp].y < pPointList[endp].y) { LineMin = pPointList[startp]; LineMax = pPointList[endp]; for (int y = LineMin.y; y <= LineMax.y; y++) { int x = (int) (((LineMin.x - LineMax.x) / (double) (LineMin.y - LineMax.y)) * (double) (y - LineMin.y) + 0.5 + (double)LineMin.x); //pRegion[GlobelWidth * y + x] = 1; //原程序存在越界 苏晓芸修改如下 if (y > -1 && y < GlobelHeight && x > -1 && x < GlobelWidth) { pRegion[GlobelWidth * y + x] = 1; } } } else if (pPointList[startp].y > pPointList[endp].y) { LineMin = pPointList[endp]; LineMax = pPointList[startp]; for (int y = LineMin.y; y <= LineMax.y; y++) { int x = (int) (((LineMin.x - LineMax.x) / (double) (LineMin.y - LineMax.y)) * (double) (y - LineMin.y) + 0.5 + (double)LineMin.x); //pRegion[GlobelWidth * y + x] = 1; //原程序存在越界 苏晓芸修改如下 if (y > -1 && y < GlobelHeight && x > -1 && x < GlobelWidth) { pRegion[GlobelWidth * y + x] = 1; } } } else { int XMin = (pPointList[startp].x < pPointList[endp].x)? pPointList[startp].x : pPointList[endp].x; int XMax = (pPointList[startp].x < pPointList[endp].x)? pPointList[endp].x : pPointList[startp].x; for (int i = XMin; i <= XMax; i++) { //pRegion[GlobelWidth * pPointList[startp].y + i] = 1; //原程序存在越界 苏晓芸修改如下 if (pPointList[startp].y > -1 && pPointList[startp].y < GlobelHeight && i > -1 && i < GlobelWidth) { pRegion[GlobelWidth * pPointList[startp].y + i] = 1; } } } } } // 修改标记方式 将区域边缘标志置为0 for (int i = 0; i < GlobelHeight; i++) { for (int j = 0; j < GlobelWidth; j++) { if (pRegion[GlobelWidth * i + j] == 0) { pRegion[GlobelWidth * i + j] = 1; } else { pRegion[GlobelWidth * i + j] = 0; } } } CMPoint StartPoint; int SumX = 0; int SumY = 0; for (int k = 0; k < num; k++) { SumX = SumX + pPointList[k].x; SumY = SumY + pPointList[k].y; } StartPoint.x = SumX / num; StartPoint.y = SumY / num; bool *pMaskMap = new bool[GlobelWidth * GlobelHeight]; bool *pMaskMapS = new bool[GlobelWidth * GlobelHeight]; memset(pMaskMap, 0, sizeof(bool) * GlobelWidth * GlobelHeight); memset(pMaskMapS, 0, sizeof(bool) * GlobelWidth * GlobelHeight); pMaskMap[GlobelWidth * StartPoint.y + StartPoint.x] = 1; int msum = 1; while (msum != 0) { msum = 0; for (int i = 0; i < GlobelHeight; i++) { for (int j = 0; j < GlobelWidth; j++) { msum = msum + pMaskMap[GlobelWidth * i + j] - pMaskMapS[GlobelWidth * i + j]; pMaskMapS[GlobelWidth * i + j] = pMaskMap[GlobelWidth * i + j]; } } for (int i = 0; i < GlobelHeight; i++) { for (int j = 0; j < GlobelWidth; j++) { if ((i <= 0) || (i >= GlobelHeight - 1) || (j <= 0) || (j >= GlobelWidth - 1)) { continue; } if (pMaskMapS[GlobelWidth * i + j] == 1) { pMaskMap[GlobelWidth * i + j + 1] = 1; pMaskMap[GlobelWidth * i + j - 1] = 1; pMaskMap[GlobelWidth * (i + 1) + j] = 1; pMaskMap[GlobelWidth * (i - 1) + j] = 1; } } } for (int i = 0; i < GlobelHeight; i++) { for (int j = 0; j < GlobelWidth; j++) { pMaskMap[GlobelWidth * i + j] = pMaskMap[GlobelWidth * i + j] && pRegion[GlobelWidth * i + j]; } } } memcpy(pRegion, pMaskMap, sizeof(bool) * GlobelWidth * GlobelHeight); delete[] pMaskMap; delete[] pMaskMapS; } } int RegionSurveillance::getObjectNum() { return m_FinalArray.size(); } void RegionSurveillance::getObjectInfo(int ObjCount, MS_ObjectInfo* ObjInfo) { int ii; //printf("getObjectInfo: %d\n", ObjCount); for (int i = 0; i < ObjCount; i++) { int dwPointCount = m_FinalArray[i].m_ptArray.size(); ObjInfo[i].curPos = m_FinalArray[i].m_ptArray[dwPointCount - 1]; int temp_dwPointCount = dwPointCount; if (dwPointCount > MAXTRACENUM) { dwPointCount = MAXTRACENUM; } ObjInfo[i].trace.nTraceNum = dwPointCount; for (ii = 0; ii < MAXROINUM; ii++) { ObjInfo[i].pbAlarmState[ii] = false; } for (int j = dwPointCount - 1, j1 = temp_dwPointCount - 1; j >= 0; j--, j1--) { //ObjInfo[i].trace.pObjTrace[j] = Gauss->m_TargetArray[i].m_ptArray[j]; ObjInfo[i].trace.pObjTrace[j] = m_FinalArray[i].m_ptArray[j1]; if (ObjInfo[i].trace.pObjTrace[j].x < 0) { ObjInfo[i].trace.pObjTrace[j].x = 0; } if (ObjInfo[i].trace.pObjTrace[j].x >= GlobelWidth) { ObjInfo[i].trace.pObjTrace[j].x = GlobelWidth - 1; } if (ObjInfo[i].trace.pObjTrace[j].y < 0) { ObjInfo[i].trace.pObjTrace[j].y = 0; } if (ObjInfo[i].trace.pObjTrace[j].y >= GlobelHeight) { ObjInfo[i].trace.pObjTrace[j].y = GlobelHeight - 1; } } for (ii = 0; ii < MAXROINUM; ii++) { ObjInfo[i].pbAlarmState[ii] = m_FinalArray[i].pbAlarmState[ii]; for (int k = 0; k < ALARMTYPENUM; ++k) { ObjInfo[i].pbAlarmType[ii][k] = m_FinalArray[i].pbAlarmType[ii][k]; } } /* int AlarmNum = m_FinalArray[i].m_AlarmNum; if (m_FinalArray[i].m_AlarmState) { ObjInfo[i].pbAlarmState[AlarmNum] = true; } */ // unique ID for current object ObjInfo[i].TarBox = m_FinalArray[i].m_TarBox; //目标外接矩形 ObjInfo[i].UniqueID = m_FinalArray[i].m_dwID; //当前目标的特点ID } } // 将图像转换为灰度图像 void RegionSurveillance::VibeRGBToGray(unsigned char* RgbData, unsigned char* GrayData) { int nHeight, nWidth; int index; for (nHeight = 0; nHeight != GlobelHeight; nHeight++) for (nWidth = 0; nWidth != GlobelWidth; nWidth++) { index = GlobelWidthstep * nHeight + 3 * nWidth; GrayData[GlobelWidthstep * nHeight / 3 + nWidth] = (RgbData[index + 2] * 19595 + RgbData[index + 1] * 38469 + RgbData[index] * 7472) >> 16; } } //pAlarmInfo 1进入禁区 2离开禁区 3单向越界 4双向越界 5徘徊 6丢包 void RegionSurveillance::MonitoringAlarm(unsigned char* pRGBIn, CForeground ForegroundArray_i, int dwBestMatch, RegionInfo* pRegionInfo) { // 目标锁定 //ExternalRectangle(pRGBIn, ForegroundArray_i, dwBestMatch, widthStep, 255, 0, 0); /* int dwStep = widthStep; unsigned char bRed = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 3) * 85 + 85); unsigned char bGreen = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 7) * 36 + 36); unsigned char bBlue = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 13) * 20 + 15); // 前景目标外接矩形描绘 for (int t = ForegroundArray_i.m_rtConnect.left; t <= ForegroundArray_i.m_rtConnect.right; t++) { pRGBIn[ForegroundArray_i.m_rtConnect.top * dwStep + t * 3] = 0; pRGBIn[ForegroundArray_i.m_rtConnect.top * dwStep + t * 3 + 1] = 0; pRGBIn[ForegroundArray_i.m_rtConnect.top * dwStep + t * 3 + 2] = 255; pRGBIn[ForegroundArray_i.m_rtConnect.bottom * dwStep + t * 3] = 0; pRGBIn[ForegroundArray_i.m_rtConnect.bottom * dwStep + t * 3 + 1] = 0; pRGBIn[ForegroundArray_i.m_rtConnect.bottom * dwStep + t * 3 + 2] = 255; } for (int t = ForegroundArray_i.m_rtConnect.top; t < ForegroundArray_i.m_rtConnect.bottom; t++) { pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.left * 3] = 0; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.left * 3 + 1] = 0; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.left * 3 + 2] = 255; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.right * 3] = 0; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.right * 3 + 1] = 0; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.right * 3 + 2] = 255; } */ int a = ForegroundArray_i.m_rtConnect.bottom; int b = ForegroundArray_i.m_rtConnect.top; int c = ForegroundArray_i.m_rtConnect.left; int d = ForegroundArray_i.m_rtConnect.right; // 区域监控 (从1开始 因为适配中行物品遗留,0的位置留给存储人的位置,不是有效位置 -- update by mliu 20201230) for (int ii = 1; ii < m_numROI; ii++) { //if (pAlarmInfo[ii] == 1) //进入禁区 //{ // AccessToRestrictedAreas(pRegion[ii], dwBestMatch,a, b, c, d, ii); // /* // if (m_TargetArray[dwBestMatch].m_AlarmState1 == true && m_TargetArray[dwBestMatch].m_AlarmNum1 == ii) // { // //ExternalRectangle(pRGBIn, ForegroundArray_i, dwBestMatch, widthStep, 0, 0, 255); // } // */ //} //else if (pAlarmInfo[ii] == 2) //离开禁区 //{ // LeaveTheRestrictedAreas(pRegion[ii], dwBestMatch,a, b, c, d, ii); // /* // if (m_TargetArray[dwBestMatch].m_AlarmState2 == true && m_TargetArray[dwBestMatch].m_AlarmNum2 == ii) // { // //ExternalRectangle(pRGBIn, ForegroundArray_i, dwBestMatch, widthStep, 0, 255, 0); // } // */ //} // //else if (pAlarmInfo[ii] == 3) //单向越界 //{ // OneWayCrossBorder(pRegion[ii], dwBestMatch, a, b, c, d, ii, pRegionInfo); // /* // if (m_TargetArray[dwBestMatch].m_AlarmState3 == true && m_TargetArray[dwBestMatch].m_AlarmNum3 == ii) // { // //ExternalRectangle(pRGBIn, ForegroundArray_i, dwBestMatch, widthStep, 0, 255, 0); // } // */ // //} //else if (pAlarmInfo[ii] == 4) //双向越界 //{ // TwoWayCrossBorder(pRegion[ii], dwBestMatch, a, b, c, d, ii); // /* // if (m_TargetArray[dwBestMatch].m_AlarmState4 == true && m_TargetArray[dwBestMatch].m_AlarmNum4 == ii) // { // //ExternalRectangle(pRGBIn, ForegroundArray_i, dwBestMatch, widthStep, 0, 0, 255); // } // */ //} //else if (pAlarmInfo[ii] == 5) //徘徊 //{ // WanderMonitoring(pRegion[ii], dwBestMatch, a, b, c, d, ii, pRegionInfo, pRGBIn); // /* // if (m_TargetArray[dwBestMatch].m_AlarmState5 == true && m_TargetArray[dwBestMatch].m_AlarmNum5 == ii) // { // ExternalRectangle(pRGBIn, ForegroundArray_i, dwBestMatch, widthStep, 0, 0, 255); // } // */ //} if (pAlarmInfo[ii] == 1) //丢包 { StayMonitoring(pRegion[ii], dwBestMatch, a, b, c, d, ii, pRegionInfo, pRGBIn); /* if (m_TargetArray[dwBestMatch].m_AlarmState5 == true && m_TargetArray[dwBestMatch].m_AlarmNum5 == ii) { ExternalRectangle(pRGBIn, ForegroundArray_i, dwBestMatch, widthStep, 0, 0, 255); } */ } else { } } // 轨迹描绘 //Trajectory(pRGBIn, ForegroundArray_i, dwBestMatch, width, height, widthStep); /* int dwStep = widthStep; unsigned char bRed = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 3) * 85 + 85); unsigned char bGreen = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 7) * 36 + 36); unsigned char bBlue = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 13) * 20 + 15); int dwPointNum = m_TargetArray[dwBestMatch].m_ptArray.size(); CMPoint ptLast = m_TargetArray[dwBestMatch].m_ptArray[0]; // 对目标的每一个匹配项进行遍历 for (int l = 1; l < dwPointNum; l++) { ForegroundArray_i.m_ptCenter = m_TargetArray[dwBestMatch].m_ptArray[l]; if (ForegroundArray_i.m_ptCenter == ptLast) { // Draw a point //描绘目标中心点 pRGBIn[ForegroundArray_i.m_ptCenter.y * dwStep + ForegroundArray_i.m_ptCenter.x * 3] = bBlue; pRGBIn[ForegroundArray_i.m_ptCenter.y * dwStep + ForegroundArray_i.m_ptCenter.x * 3 + 1] = bGreen; pRGBIn[ForegroundArray_i.m_ptCenter.y * dwStep + ForegroundArray_i.m_ptCenter.x * 3 + 2] = bRed; } else { // Draw line if (abs(ForegroundArray_i.m_ptCenter.x - ptLast.x) > abs(ForegroundArray_i.m_ptCenter.y - ptLast.y)) { double dk = ((double) ForegroundArray_i.m_ptCenter.y - ptLast.y) / (ForegroundArray_i.m_ptCenter.x - ptLast.x); double b = ForegroundArray_i.m_ptCenter.y - ForegroundArray_i.m_ptCenter.x * dk; int colMin = ForegroundArray_i.m_ptCenter.x; int colMax = ptLast.x; if (colMin > colMax) { int dwTemp = colMin; colMin = colMax; colMax = dwTemp; } for (int col = colMin; col <= colMax; col++) { int row = (int) (dk * col + b + 0.5); row = row < height ? row : height - 1; row = row >= 0 ? row : 0; pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; if (++row < height) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } else if ((row -= 2) >= 0) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } } } else { double dk = ((double) ForegroundArray_i.m_ptCenter.x - ptLast.x) / (ForegroundArray_i.m_ptCenter.y - ptLast.y); double b = ForegroundArray_i.m_ptCenter.x - ForegroundArray_i.m_ptCenter.y * dk; int rowMin = ForegroundArray_i.m_ptCenter.y; int rowMax = ptLast.y; if (rowMin > rowMax) { int dwTemp = rowMin; rowMin = rowMax; rowMax = dwTemp; } for (int row = rowMin; row <= rowMax; row++) { int col = (int) (dk * row + b + 0.5); col = col < width? col : width - 1; col = col >= 0 ? col : 0; pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; if (++col < width) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } else if ((col -= 2) >= 0) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } } } } ptLast = ForegroundArray_i.m_ptCenter; } */ } /* //外接矩形描绘 void RegionSurveillance::ExternalRectangle(unsigned char* pRGBIn, CForeground ForegroundArray_i, int dwBestMatch, int widthStep, int rgb_b, int rgb_g, int rgb_r) { int dwStep = widthStep; // 前景目标外接矩形描绘 for (int t = ForegroundArray_i.m_rtConnect.left; t <= ForegroundArray_i.m_rtConnect.right; t++) { pRGBIn[ForegroundArray_i.m_rtConnect.top * dwStep + t * 3] = rgb_b; pRGBIn[ForegroundArray_i.m_rtConnect.top * dwStep + t * 3 + 1] = rgb_g; pRGBIn[ForegroundArray_i.m_rtConnect.top * dwStep + t * 3 + 2] = rgb_r; pRGBIn[ForegroundArray_i.m_rtConnect.bottom * dwStep + t * 3] = rgb_b; pRGBIn[ForegroundArray_i.m_rtConnect.bottom * dwStep + t * 3 + 1] = rgb_g; pRGBIn[ForegroundArray_i.m_rtConnect.bottom * dwStep + t * 3 + 2] = rgb_r; } for (int t = ForegroundArray_i.m_rtConnect.top; t < ForegroundArray_i.m_rtConnect.bottom; t++) { pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.left * 3] = rgb_b; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.left * 3 + 1] = rgb_g; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.left * 3 + 2] = rgb_r; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.right * 3] = rgb_b; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.right * 3 + 1] = rgb_g; pRGBIn[t * dwStep + ForegroundArray_i.m_rtConnect.right * 3 + 2] = rgb_r; } } void RegionSurveillance::Trajectory(unsigned char* pRGBIn, CForeground ForegroundArray_i, int dwBestMatch, int width, int height, int widthStep) { // 轨迹描绘 int dwStep = widthStep; unsigned char bRed = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 3) * 85 + 85); unsigned char bGreen = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 7) * 36 + 36); unsigned char bBlue = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 13) * 20 + 15); int dwPointNum = m_TargetArray[dwBestMatch].m_ptArray.size(); CMPoint ptLast = m_TargetArray[dwBestMatch].m_ptArray[0]; // 对目标的每一个匹配项进行遍历 for (int l = 1; l < dwPointNum; l++) { ForegroundArray_i.m_ptCenter = m_TargetArray[dwBestMatch].m_ptArray[l]; if (ForegroundArray_i.m_ptCenter == ptLast) { // Draw a point //描绘目标中心点 pRGBIn[ForegroundArray_i.m_ptCenter.y * dwStep + ForegroundArray_i.m_ptCenter.x * 3] = bBlue; pRGBIn[ForegroundArray_i.m_ptCenter.y * dwStep + ForegroundArray_i.m_ptCenter.x * 3 + 1] = bGreen; pRGBIn[ForegroundArray_i.m_ptCenter.y * dwStep + ForegroundArray_i.m_ptCenter.x * 3 + 2] = bRed; } else { // Draw line if (abs(ForegroundArray_i.m_ptCenter.x - ptLast.x) > abs(ForegroundArray_i.m_ptCenter.y - ptLast.y)) { double dk = ((double) ForegroundArray_i.m_ptCenter.y - ptLast.y) / (ForegroundArray_i.m_ptCenter.x - ptLast.x); double b = ForegroundArray_i.m_ptCenter.y - ForegroundArray_i.m_ptCenter.x * dk; int colMin = ForegroundArray_i.m_ptCenter.x; int colMax = ptLast.x; if (colMin > colMax) { int dwTemp = colMin; colMin = colMax; colMax = dwTemp; } for (int col = colMin; col <= colMax; col++) { int row = (int) (dk * col + b + 0.5); row = row < height ? row : height - 1; row = row >= 0 ? row : 0; pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; if (++row < height) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } else if ((row -= 2) >= 0) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } } } else { double dk = ((double) ForegroundArray_i.m_ptCenter.x - ptLast.x) / (ForegroundArray_i.m_ptCenter.y - ptLast.y); double b = ForegroundArray_i.m_ptCenter.x - ForegroundArray_i.m_ptCenter.y * dk; int rowMin = ForegroundArray_i.m_ptCenter.y; int rowMax = ptLast.y; if (rowMin > rowMax) { int dwTemp = rowMin; rowMin = rowMax; rowMax = dwTemp; } for (int row = rowMin; row <= rowMax; row++) { int col = (int) (dk * row + b + 0.5); col = col < width? col : width - 1; col = col >= 0 ? col : 0; pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; if (++col < width) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } else if ((col -= 2) >= 0) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } } } } ptLast = ForegroundArray_i.m_ptCenter; } } */ /****************************************************************************** * Function: RAccessToRestrictedAreas * Description: 进入禁区监测 * Input: pRegion_i 感兴趣区域标记 dwBestMatch 目标索引 ForBottom 当前前景外接矩形纵坐标最小值 ForTop 当前前景外接矩形纵坐标最大值 ForLeft 当前前景外接矩形横坐标最小值 ForRight 当前前景外接矩形横坐标最大值 indexROI ROI 索引 * Output: m_TargetArray 目标信息 *******************************************************************************/ void RegionSurveillance::AccessToRestrictedAreas(bool *pRegion_i, int dwBestMatch, int ForBottom, int ForTop, int ForLeft, int ForRight, int indexROI) { // 目标外接矩形有一个边进入禁区且外接矩形中心点位于禁区内 //if (pRegion_i[GlobelWidth * ForBottom + ForLeft] || // pRegion_i[GlobelWidth * ForTop + ForLeft] || // pRegion_i[GlobelWidth * ForTop + ForRight] || // pRegion_i[GlobelWidth * ForBottom + ForRight]) { //将判断是否进入感兴趣区域改成了矩形中心点的上下左右和中心五个点都进入区域,判定为进入 if (pRegion_i[GlobelWidth * (int) ((ForBottom + ForTop) / 2) + (ForLeft + ForRight) / 2] && \ pRegion_i[GlobelWidth * (int)((ForBottom + ForTop) / 2) + (ForLeft + ForRight) / 2 + 1] && \ pRegion_i[GlobelWidth * (int)((ForBottom + ForTop) / 2) + (ForLeft + ForRight) / 2 - 1] && \ pRegion_i[GlobelWidth * (int)((ForBottom + ForTop) / 2+1) + (ForLeft + ForRight) / 2] &&\ pRegion_i[GlobelWidth * (int)((ForBottom + ForTop) / 2-1) + (ForLeft + ForRight) / 2]) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][0] = 1; return; } } m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][0] = 0; } //离开禁区 void RegionSurveillance::LeaveTheRestrictedAreas(bool *pRegion_i, int dwBestMatch, int ForBottom, int ForTop, int ForLeft, int ForRight, int indexROI) { if (pRegion_i[GlobelWidth * ForBottom + ForLeft] || pRegion_i[GlobelWidth * ForTop + ForLeft] || pRegion_i[GlobelWidth * ForTop + ForRight] || pRegion_i[GlobelWidth * ForBottom + ForRight]) { if (pRegion_i[GlobelWidth * (int) ((ForBottom + ForTop) / 2) + (ForLeft + ForRight) / 2] == 0 && pRegion_i[GlobelWidth * (int)m_TargetArray[dwBestMatch].m_PredictionPoint.y + (int)m_TargetArray[dwBestMatch].m_PredictionPoint.x] == 0) { bool flag = 0; int i; int tar_arr_size = m_TargetArray[dwBestMatch].m_ptArray.size(); i = tar_arr_size - 1; while (i >= 0 && i >= tar_arr_size - (ForRight - ForLeft)/2) { if (pRegion_i[GlobelWidth * (int) (m_TargetArray[dwBestMatch].m_ptArray[i].y) + m_TargetArray[dwBestMatch].m_ptArray[i].x] == 1) { flag = 1; break; } i--; } if (flag == 1) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][1] = 2; return; } } } m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][1] = 0; } //单向越界 //dir: 1 正方向(相对于通常坐标系) 0负方向 void RegionSurveillance::OneWayCrossBorder(bool *pRegion_i, int dwBestMatch, int ForBottom, int ForTop, int ForLeft, int ForRight, int indexROI, RegionInfo* pRegionInfo) { // 只要目标外接矩形有一个点进入区域则报警 int tar_size = m_TargetArray[dwBestMatch].m_ptArray.size(); int xmin = min(ForLeft, ForRight), xmax = max(ForLeft, ForRight), ymin = min(ForBottom, ForTop), ymax = max(ForBottom, ForTop); for (int iy = ymin; iy <= ymax; iy++) { for (int ix = xmin; ix <= xmax; ix++) { if (pRegion_i[GlobelWidth * iy + ix] && tar_size >= 4) { int point_x, point_y; point_x = m_TargetArray[dwBestMatch].m_ptArray[tar_size - 4].x; point_y = m_TargetArray[dwBestMatch].m_ptArray[tar_size - 4].y; // 判断方向 if (indexROI >= 0 && indexROI < m_numROI && pRegionInfo[indexROI].nPointNum >= 2) { if (abs(pRegionInfo[indexROI].pROI[0].x - pRegionInfo[indexROI].pROI[1].x) >= 1) { double k, b; k = (double)(pRegionInfo[indexROI].pROI[0].y - pRegionInfo[indexROI].pROI[1].y) / (pRegionInfo[indexROI].pROI[0].x - pRegionInfo[indexROI].pROI[1].x); b = (double)(pRegionInfo[indexROI].pROI[0].x * pRegionInfo[indexROI].pROI[1].y - pRegionInfo[indexROI].pROI[1].x * pRegionInfo[indexROI].pROI[0].y) / (pRegionInfo[indexROI].pROI[0].x - pRegionInfo[indexROI].pROI[1].x); double dist_c, dist_p; dist_c = fabs(k * m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].x - m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].y + b) / sqrt(k * k + 1.0); dist_p = fabs(k * point_x - point_y + b) / sqrt(k * k + 1.0); if (abs(dist_c - dist_p) < 10) { int pre_index = tar_size - 5; while (pre_index >= 0) { point_x = m_TargetArray[dwBestMatch].m_ptArray[pre_index].x; point_y = m_TargetArray[dwBestMatch].m_ptArray[pre_index].y; dist_p = fabs(k * point_x - point_y + b) / sqrt(k * k + 1.0); pre_index = pre_index - 1; if (abs(dist_c - dist_p) >= 10) { break; } } } if (abs(dist_c - dist_p) < 10) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 0; return; } bool flag_c, flag_p; if (k * m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].x + b >= m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].y) { flag_c = 1; } else { flag_c = 0; } if (k *point_x + b >= point_y) { flag_p = 1; } else { flag_p = 0; } //if (pRegionInfo[indexROI].dir == 1) if (pRegionInfo[indexROI].finaldir == 1) //by zl 20150914 { if (flag_c * flag_p == 1) { if (dist_c <= dist_p) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } else if (flag_c == 0 && flag_p == 1) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } else if (flag_c ==0 && flag_p == 0) { if (dist_p <= dist_c) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } } else { if (flag_c == 0 && flag_p == 0) { if (dist_c <= dist_p) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } else if (flag_c == 1 && flag_p == 0) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } else if (flag_c == 1 && flag_p == 1) { if (dist_p <= dist_c) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } } } else { double k, b; k = 0; b = (double)(pRegionInfo[indexROI].pROI[0].x); double dist_c, dist_p; dist_c = fabs(m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].x - b); dist_p = fabs(point_x - b); if (abs(dist_c - dist_p) < 10) { int pre_index = tar_size - 5; while (pre_index >= 0) { point_x = m_TargetArray[dwBestMatch].m_ptArray[pre_index].x; dist_p = fabs(point_x - b); pre_index = pre_index - 1; if (abs(dist_c - dist_p) >= 10) { break; } } } bool flag_c, flag_p; if (m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].x >= b) { flag_c = 1; } else { flag_c = 0; } if (point_x >= b) { flag_p = 1; } else { flag_p = 0; } if (abs(dist_c - dist_p) < 10) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 0; return; } //if (pRegionInfo[indexROI].dir == 1) if (pRegionInfo[indexROI].finaldir == 1) //by zl 20150914 { if (flag_c * flag_p == 1) { if (dist_c <= dist_p) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } else if (flag_c == 0 && flag_p == 1) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } else if (flag_c == 0 && flag_p == 0) { if (dist_p <= dist_c) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } } else { if (flag_c == 0 && flag_p == 0) { if (dist_c <= dist_p) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } else if (flag_c == 1 && flag_p == 0) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } else if (flag_c == 1 && flag_p == 1) { if (dist_p <= dist_c) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 3; return; } } } } } } } } m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][2] = 0; } //双向越界 void RegionSurveillance::TwoWayCrossBorder(bool *pRegion_i, int dwBestMatch, int ForBottom, int ForTop, int ForLeft, int ForRight, int indexROI) { // 只要目标外接矩形有一个点进入区域则报警 int xmin = min(ForLeft, ForRight), xmax = max(ForLeft, ForRight), ymin = min(ForBottom, ForTop), ymax = max(ForBottom, ForTop); for (int iy = ymin; iy <= ymax; iy++) { for (int ix = xmin; ix <= xmax; ix++) { if (pRegion_i[GlobelWidth * iy + ix]) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][3] = 4; return; } } } m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][3] = 0; } ////双向越界 //void RegionSurveillance::TwoWayCrossBorder(bool *pRegion_i, int dwBestMatch, int ForBottom, int ForTop, int ForLeft, int ForRight, int indexROI) //{ // // 只要目标外接矩形有一个点进入区域则报警 // int xmin = min(ForLeft, ForRight), xmax = max(ForLeft, ForRight), ymin = min(ForBottom, ForTop), ymax= max(ForBottom, ForTop); // for (int iy = ymin; iy <= ymax; iy++) // { // for (int ix = xmin; ix <= xmax; ix++) // { // if (pRegion_i[GlobelWidth * iy + ix]) // { // m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; // m_TargetArray[dwBestMatch].pbAlarmType[indexROI] = 4; // return; // } // } // } // m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; // m_TargetArray[dwBestMatch].pbAlarmType[indexROI] = -1; //} // 监测遗留或移除 0 遗留 1移除 bool RegionSurveillance::detectLeftRemove(unsigned char* pRGBIn, int ForBottom, int ForTop, int ForLeft, int ForRight) { bool flag; int surround_b, surround_t, surround_l, surround_r; int i, j; int temp; if (ForTop > ForBottom) { temp = ForBottom; ForBottom = ForTop; ForTop = temp; } if (ForLeft > ForRight) { temp = ForRight; ForRight = ForLeft; ForLeft = temp; } surround_l = max(0, ForLeft - 15); surround_t = max(0, ForTop - 15); surround_b = min(GlobelHeight - 1, ForBottom + 15); surround_r = min(GlobelHeight - 1, ForRight + 15); double s1[3], s2[3]; int num; s1[0] = 0; s1[1] = 0; s1[2] = 0; num = 0; for (i = ForTop; i <= ForBottom; i++) { for (j = ForLeft; j <= ForRight; j++) { s1[0] += pRGBIn[GlobelWidthstep * i + 3 * j]; s1[1] += pRGBIn[GlobelWidthstep * i + 3 * j + 1]; s1[2] += pRGBIn[GlobelWidthstep * i + 3 * j + 2]; num ++; } } if (num >= 1) { s1[0] /= num; s1[1] /= num; s1[2] /= num; } else { return 1; } double dist1; dist1 = sqrt(s1[0] * s1[0] + s1[1] * s1[1] + s1[2] * s1[2]); s2[0] = 0; s2[1] = 0; s2[2] = 0; num = 0; for (i = surround_t; i <= surround_b; i++) { for (j = surround_l; j <= surround_r; j++) { s2[0] += pRGBIn[GlobelWidthstep * i + 3 * j]; s2[1] += pRGBIn[GlobelWidthstep * i + 3 * j + 1]; s2[2] += pRGBIn[GlobelWidthstep * i + 3 * j + 2]; num ++; } } if (num >= 1) { s2[0] /= num; s2[1] /= num; s2[2] /= num; } else { return 1; } double dist2; dist2 = sqrt(s2[0] * s2[0] + s2[1] * s2[1] + s2[2] * s2[2]); double ratio = 0; if (dist1 >= dist2) { if (fabs(dist1) < 0.0001) { ratio = 1.0; } else { ratio = dist2 / dist1; } } else { if (fabs(dist2) < 0.0001) { ratio = 1.0; } else { ratio = dist1 / dist2; } } if (ratio >= 0.85 && ratio <= 1.0) //相近表示移除 { flag = 1; } else // 否则表示遗留 { flag = 0; } return flag; } bool CTargetFunc (CTarget &a, CTarget &b) { if (a.m_CurRefPoint.x == b.m_CurRefPoint.x && a.m_CurRefPoint.y == b.m_CurRefPoint.y) return true; else return false; } // 徘徊监测 void RegionSurveillance::WanderMonitoring(bool *pRegion_i, int dwBestMatch, int ForBottom, int ForTop, int ForLeft, int ForRight, int indexROI, RegionInfo* pRegionInfo, unsigned char* pRGBIn) { // 目标外接矩形有一个边进入禁区且外接矩形中心点位于禁区内 bool flag = 0; if ((pRegion_i[GlobelWidth * ForBottom + ForLeft] || pRegion_i[GlobelWidth * ForTop + ForLeft] || pRegion_i[GlobelWidth * ForTop + ForRight] || pRegion_i[GlobelWidth * ForBottom + ForRight]) && (pRegion_i[GlobelWidth * (int)((ForBottom + ForTop) / 2) + (ForLeft + ForRight) / 2])&& (indexROI >= 0 && indexROI < m_numROI)) { //cout << dwBestMatch << endl; if (m_TargetArray[dwBestMatch].nFrameCurr == 0) { m_TargetArray[dwBestMatch].nFrameCurr = 1; m_TargetArray[dwBestMatch].lastFrame = 0; } else { if (m_TargetArray[dwBestMatch].lastFrame <= 5) { m_TargetArray[dwBestMatch].nFrameCurr++; m_TargetArray[dwBestMatch].lastFrame = 0; } else { m_TargetArray[dwBestMatch].nFrameCurr = 0; m_TargetArray[dwBestMatch].lastFrame = 0; } } if ((1 == m_TargetArray[dwBestMatch].m_ptArray.size() && m_TargetArray[dwBestMatch].nFrameCurr == 1) && m_TargetArray[dwBestMatch].m_bFirstInWander == true ) //因在徘徊区域内,检测目标对象判定为新对象,将该新对象的nFrameCurr,设置为该区域内最接近的对象的nFrameCurr { double bestDistance = 0; CTarget best; int index = 0; for (auto item : indexInWander) { auto distance = sqrt((m_TargetArray[dwBestMatch].m_CurRefPoint.x - item.m_PredictionPoint.x) * (m_TargetArray[dwBestMatch].m_CurRefPoint.x - item.m_PredictionPoint.x) + (m_TargetArray[dwBestMatch].m_CurRefPoint.y - item.m_PredictionPoint.y) * (m_TargetArray[dwBestMatch].m_CurRefPoint.y - item.m_PredictionPoint.y)); if (0 == bestDistance) { bestDistance = distance; best = item; } else if (bestDistance > distance) { bestDistance = distance; best = item; } ++index; } if (indexInWander.empty()) { } else { auto CTargetFunc = [best](CTarget &a)->bool { if (best.m_dwID == a.m_dwID) return true; else return false; }; m_TargetArray[dwBestMatch].nFrameCurr = best.nFrameCurr; m_TargetArray[dwBestMatch].m_dwID = best.m_dwID; auto iter = std::find_if(indexInWander.begin(), indexInWander.end(), CTargetFunc); if (iter != indexInWander.end()) indexInWander.erase(iter); } } if (m_TargetArray[dwBestMatch].nFrameCurr >= pRegionInfo[indexROI].nFrameNum) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][4] = 5; flag = 1; CTarget best = m_TargetArray[dwBestMatch]; auto CTargetFunc = [best](CTarget &a)->bool { if (best.m_dwID == a.m_dwID) return true; else return false; }; auto iter = std::find_if(indexInWander.begin(), indexInWander.end(), CTargetFunc); if (iter != indexInWander.end()) indexInWander.erase(iter); indexInWander.push_back(m_TargetArray[dwBestMatch]); //cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << dwBestMatch << endl; } else { CTarget best = m_TargetArray[dwBestMatch]; auto CTargetFunc = [best](CTarget &a)->bool { if (best.m_dwID == a.m_dwID) return true; else return false; }; auto iter = std::find_if(indexInWander.begin(), indexInWander.end(), CTargetFunc); if (iter != indexInWander.end()) indexInWander.erase(iter); } m_TargetArray[dwBestMatch].m_bFirstInWander = false; // 判断模板是否进行更新 0 遗留 1移除 left_flag_now_w = detectLeftRemove(pRGBIn, ForBottom, ForTop, ForLeft, ForRight); } else { left_flag_now_w = 1; //cout << dwBestMatch << endl; CTarget best = m_TargetArray[dwBestMatch]; auto CTargetFunc = [best](CTarget &a)->bool { if (best.m_dwID == a.m_dwID) return true; else return false; }; auto iter = std::find_if(indexInWander.begin(), indexInWander.end(), CTargetFunc); if(iter != indexInWander.end()) indexInWander.erase(iter); } if (flag == 0) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][4] = 0; } m_TargetArray[dwBestMatch].lastFrame++; } // 丢包监测 void RegionSurveillance::StayMonitoring(bool *pRegion_i, int dwBestMatch, int ForBottom, int ForTop, int ForLeft, int ForRight, int indexROI, RegionInfo* pRegionInfo, unsigned char* pRGBIn) { // 目标外接矩形有一个边进入禁区且外接矩形中心点位于禁区内 int tar_size = m_TargetArray[dwBestMatch].m_ptArray.size(); int cur_dis; bool flag = 0; /*if (pRegion_i[GlobelWidth * ForBottom + ForLeft] || pRegion_i[GlobelWidth * ForTop + ForLeft] || pRegion_i[GlobelWidth * ForTop + ForRight] || pRegion_i[GlobelWidth * ForBottom + ForRight])*/ { //if (pRegion_i[GlobelWidth * (int) ((ForBottom + ForTop) / 2) + (ForLeft + ForRight) / 2]) { if (indexROI >= 0 && indexROI < m_numROI) { if (m_TargetArray[dwBestMatch].nFrameCurr == 0) { m_TargetArray[dwBestMatch].nFrameCurr = 1; m_TargetArray[dwBestMatch].lastFrame = 0; } else { if (tar_size >= 2) { cur_dis = (m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].x - m_TargetArray[dwBestMatch].m_ptArray[tar_size - 2].x) * (m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].x - m_TargetArray[dwBestMatch].m_ptArray[tar_size - 2].x) + (m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].y - m_TargetArray[dwBestMatch].m_ptArray[tar_size - 2].y) * (m_TargetArray[dwBestMatch].m_ptArray[tar_size - 1].y - m_TargetArray[dwBestMatch].m_ptArray[tar_size - 2].y); } else { cur_dis = 0; } if (m_TargetArray[dwBestMatch].lastFrame <= 5 && cur_dis <= tar_size * tar_size) { m_TargetArray[dwBestMatch].nFrameCurr++; m_TargetArray[dwBestMatch].lastFrame = 0; } else { m_TargetArray[dwBestMatch].nFrameCurr = 0; m_TargetArray[dwBestMatch].lastFrame = 0; } } if (m_TargetArray[dwBestMatch].nFrameCurr >= pRegionInfo[indexROI].nFrameNum) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = true; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][5] = 6; flag = 1; } } } // 判断模板是否进行更新 0 遗留 1移除 left_flag_now_s = detectLeftRemove(pRGBIn, ForBottom, ForTop, ForLeft, ForRight); } /*else { left_flag_now_s = 1; }*/ if (flag == 0) { m_TargetArray[dwBestMatch].pbAlarmState[indexROI] = false; m_TargetArray[dwBestMatch].pbAlarmType[indexROI][5] = 0; } m_TargetArray[dwBestMatch].lastFrame++; } void RegionSurveillance::RSrelease() { if (pConExtraction) { delete pConExtraction; pConExtraction = NULL; } for (int i = 0; i < MAXROINUM; i++) { if (pRegion[i] !=NULL) { delete[] pRegion[i]; } } if (pRegion != NULL) { delete[] pRegion; pRegion = NULL; } if (pAlarmInfo != NULL) { delete[] pAlarmInfo; pAlarmInfo = NULL; } // 释放m_TargetArray int i; for (i = 0; i < (int)m_TargetArray.size(); i++) { m_TargetArray[i].m_ptArray.clear(); vector().swap(m_TargetArray[i].m_ptArray); { std::vectortmp = m_TargetArray[i].m_ptArray; m_TargetArray[i].m_ptArray.swap(tmp); } } m_TargetArray.clear(); m_FinalArray.clear(); //m_TargetArray.swap(vector(0)); //m_FinalArray.swap(vector(0)); if (MaskImgData != NULL) { free(MaskImgData); MaskImgData = NULL; } if (greyImgData != NULL) { free(greyImgData); greyImgData = NULL; } if (vbM->bg_samples != NULL) { free(vbM->bg_samples); vbM->bg_samples = NULL; } if (vbM != NULL) { free(vbM); vbM = NULL; } FreeRand(); FreeRandNeighbor(); if(maskImg) { delete [] maskImg; maskImg = NULL; } if(VBPARAM) delete VBPARAM; VBPARAM = NULL; } void RegionSurveillance::VibeModelFree(VibeModel_t *model) { free(model->bg_samples); if (model != NULL) { free(model); model = NULL; } FreeRand(); FreeRandNeighbor(); } //{ // CvSize a; // //a.width = GlobelWidth; // //a.height = GlobelHeight; // //IplImage *im = cvCreateImage(a, 8, 1); // //im->imageData = (char*)image2.data; // //IplImage *img_3 = cvCreateImage(cvGetSize(im), 8, 3); //创建3通道图像 // //cvCvtColor(im, img_3, CV_GRAY2BGR);//单通道转3通道 // IplImage *img_3; // img_3 = &IplImage(image2); // for (int i = 0; i < ForegroundArray.size(); i++) // { // //cvRectangle(img_3, CvPoint(foreContours[i].left, foreContours[i].top), // // CvPoint(foreContours[i].right, foreContours[i].bottom), CV_RGB(0, 255, 0), 2); //绿色画框 // cvRectangle(img_3, CvPoint(ForegroundArray[i].m_rtConnect.left, ForegroundArray[i].m_rtConnect.top), // CvPoint(ForegroundArray[i].m_rtConnect.right, ForegroundArray[i].m_rtConnect.bottom), CV_RGB(0, 255, 0), 2); //绿色画框 // } // a.width = GlobelWidth / 2; // a.height = GlobelHeight / 2; // IplImage *desc = cvCreateImage(a, img_3->depth, img_3->nChannels); // cvResize(img_3, desc, CV_INTER_CUBIC); // cvShowImage("L2", img_3); // cvWaitKey(1); //} /* // Draw it int dwPointNum = m_TargetArray[dwBestMatch].m_ptArray.size(); if (dwPointNum >= m_dwMinFrame) { unsigned char bRed = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 3) * 85 + 85); unsigned char bGreen = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 7) * 36 + 36); unsigned char bBlue = (unsigned char) ((m_TargetArray[dwBestMatch].m_dwID % 13) * 20 + 15); // Draw rectangle //横线 // 目标外接矩形 红色 for (int t = ForegroundArray[i].m_rtConnect.left; t <= ForegroundArray[i].m_rtConnect.right; t++) { pRGBIn[ForegroundArray[i].m_rtConnect.top * dwStep + t * 3] = 0; pRGBIn[ForegroundArray[i].m_rtConnect.top * dwStep + t * 3 + 1] = 0; pRGBIn[ForegroundArray[i].m_rtConnect.top * dwStep + t * 3 + 2] = 255; pRGBIn[ForegroundArray[i].m_rtConnect.bottom * dwStep + t * 3] = 0; pRGBIn[ForegroundArray[i].m_rtConnect.bottom * dwStep + t * 3 + 1] = 0; pRGBIn[ForegroundArray[i].m_rtConnect.bottom * dwStep + t * 3 + 2] = 255; } for (int t = ForegroundArray[i].m_rtConnect.top; t < ForegroundArray[i].m_rtConnect.bottom; t++) { pRGBIn[t * dwStep + ForegroundArray[i].m_rtConnect.left * 3] = 0; pRGBIn[t * dwStep + ForegroundArray[i].m_rtConnect.left * 3 + 1] = 0; pRGBIn[t * dwStep + ForegroundArray[i].m_rtConnect.left * 3 + 2] = 255; pRGBIn[t * dwStep + ForegroundArray[i].m_rtConnect.right * 3] = 0; pRGBIn[t * dwStep + ForegroundArray[i].m_rtConnect.right * 3 + 1] = 0; pRGBIn[t * dwStep + ForegroundArray[i].m_rtConnect.right * 3 + 2] = 255; } //----------------------------- int a = ForegroundArray[i].m_rtConnect.bottom; int b = ForegroundArray[i].m_rtConnect.top; int c = ForegroundArray[i].m_rtConnect.left; int d = ForegroundArray[i].m_rtConnect.right; // ROI 监控 for (int ii = 0; ii < m_numROI; ii++) { // 目标外接矩形进行区域且目标中心点在区域内,则报警 if (pAlarmInfo[ii] == 1) //禁止区域 { if (pRegion[ii][GlobelWidth * a + c] || pRegion[ii][GlobelWidth * b + c] || pRegion[ii][GlobelWidth * b + d] || pRegion[ii][GlobelWidth * a + d]) { if (pRegion[ii][GlobelWidth * (int) ((a + b) / 2) + (c + d) / 2]) { //printf("alarm 1!\n"); m_TargetArray[dwBestMatch].m_AlarmState = true; m_TargetArray[dwBestMatch].m_AlarmNum = ii; //printf("%d",m_TargetArray[dwBestMatch].m_AlarmNum ); } } } // 只要目标外接矩形有一个点进入区域则报警 if (pAlarmInfo[ii] == 2) //拌线 { int xmin = min(c, d), xmax = max(c, d), ymin = min(a, b), ymax = max(a, b); for (int iy = ymin; iy <= ymax; iy++) { for (int ix = xmin; ix <= xmax; ix++) { if (pRegion[ii][GlobelWidth * iy + ix]) { m_TargetArray[dwBestMatch].m_AlarmState = true; m_TargetArray[dwBestMatch].m_AlarmNum = ii; break; } } } } // 只要目标外接矩形进入区域中,且面积大于ROI区域面积的一半同时外接矩形中心点在区域内,则报警 if (pAlarmInfo[ii] == 3) //遗留检测 { int TotalArea = 0; if (TotalArea == 0) { for (int ai = 0; ai < GlobelHeight * GlobelWidth; ai++) { if (pRegion[ii][ai] == 1) { TotalArea++; } } } if (pRegion[ii][GlobelWidth * a + c] || pRegion[ii][GlobelWidth * b + c] || pRegion[ii][GlobelWidth * b + d] || pRegion[ii][GlobelWidth * a + d]) { if (abs(a - b) * abs(c - d) >= (TotalArea / 2) && (pRegion[ii][GlobelWidth * (int) ((a + b) / 2) + (c + d) / 2])) { //printf("alarm 3!\n"); m_TargetArray[dwBestMatch].m_AlarmState = true; m_TargetArray[dwBestMatch].m_AlarmNum = ii; } } } } //保存最终输出目标 m_FinalArray.push_back(m_TargetArray[dwBestMatch]); CMPoint ptLast = m_TargetArray[dwBestMatch].m_ptArray[0]; // 对目标的每一个匹配项进行遍历 for (int l = 1; l < dwPointNum; l++) { ForegroundArray[i].m_ptCenter = m_TargetArray[dwBestMatch].m_ptArray[l]; if (ForegroundArray[i].m_ptCenter == ptLast) { // Draw a point //描绘目标中心点 pRGBIn[ForegroundArray[i].m_ptCenter.y * dwStep + ForegroundArray[i].m_ptCenter.x * 3] = bBlue; pRGBIn[ForegroundArray[i].m_ptCenter.y * dwStep + ForegroundArray[i].m_ptCenter.x * 3 + 1] = bGreen; pRGBIn[ForegroundArray[i].m_ptCenter.y * dwStep + ForegroundArray[i].m_ptCenter.x * 3 + 2] = bRed; } else { // Draw line if (abs(ForegroundArray[i].m_ptCenter.x - ptLast.x) > abs(ForegroundArray[i].m_ptCenter.y - ptLast.y)) { double dk = ((double) ForegroundArray[i].m_ptCenter.y - ptLast.y) / (ForegroundArray[i].m_ptCenter.x - ptLast.x); double b = ForegroundArray[i].m_ptCenter.y - ForegroundArray[i].m_ptCenter.x * dk; int colMin = ForegroundArray[i].m_ptCenter.x; int colMax = ptLast.x; if (colMin > colMax) { int dwTemp = colMin; colMin = colMax; colMax = dwTemp; } for (int col = colMin; col <= colMax; col++) { int row = (int) (dk * col + b + 0.5); row = row < height ? row : height - 1; row = row >= 0 ? row : 0; pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; if (++row < height) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } else if ((row -= 2) >= 0) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } } } else { double dk = ((double) ForegroundArray[i].m_ptCenter.x - ptLast.x) / (ForegroundArray[i].m_ptCenter.y - ptLast.y); double b = ForegroundArray[i].m_ptCenter.x - ForegroundArray[i].m_ptCenter.y * dk; int rowMin = ForegroundArray[i].m_ptCenter.y; int rowMax = ptLast.y; if (rowMin > rowMax) { int dwTemp = rowMin; rowMin = rowMax; rowMax = dwTemp; } for (int row = rowMin; row <= rowMax; row++) { int col = (int) (dk * row + b + 0.5); col = col < width? col : width - 1; col = col >= 0 ? col : 0; pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; if (++col < width) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } else if ((col -= 2) >= 0) { pRGBIn[row * dwStep + col * 3] = bBlue; pRGBIn[row * dwStep + col * 3 + 1] = bGreen; pRGBIn[row * dwStep + col * 3 + 2] = bRed; } } } } ptLast = ForegroundArray[i].m_ptCenter; } } // draw it and judge area function */