//#include "stdafx.h" #include "RegionAssist.h" #include "MSRegionSurveilance.h" #include "left_over_det.h" #include "cv.h" #include "highgui.h" //using namespace cv; using namespace std; #define LINE_PIXEL 2 /************************************************************************/ /* 函数: DrawArrow() */ /* 作用: 绘制箭头 */ /* 参数: src:图像;pStart&pEnd:箭头两个端点;len:箭头两翼的长短; */ /* alpha为箭头两翼展开的幅度 */ /* 返回: 无 */ /************************************************************************/ void DrawArrow(IplImage * src, cv::Point pStart, cv::Point pEnd, int len, int alpha) { const double PI = 3.1415926; cv::Point arrow; //计算 θ 角(最简单的一种情况在下面图示中已经展示,关键在于 atan2 函数,详情见下面) double angle = atan2((double)(pStart.y - pEnd.y), (double)(pStart.x - pEnd.x)); cvLine(src, pStart, pEnd, cvScalar(0, 127, 0), 2); //黄色线 //计算箭角边的另一端的端点位置(上面的还是下面的要看箭头的指向,也就是pStart和pEnd的位置) arrow.x = pEnd.x + len * cos(angle + PI * alpha / 180); arrow.y = pEnd.y + len * sin(angle + PI * alpha / 180); cvLine(src, pEnd, arrow, cvScalar(0, 127, 0), 2); arrow.x = pEnd.x + len * cos(angle - PI * alpha / 180); arrow.y = pEnd.y + len * sin(angle - PI * alpha / 180); cvLine(src, pEnd, arrow, cvScalar(0, 127, 0), 2); } /************************************************************************/ /* 函数: get_ArrowDir() */ /* 作用: 获取方向和用于绘制箭头的两个端点; */ /* 参数: frame:图像(获取宽和高,用于防止越界); */ /* pROI0&pROI1:拌线两个端点; */ /* dir:确定单向警报方向的坐标点; */ /* pStart&pEnd:箭头两个端点; */ /* 返回: 1:正方向;0:负方向 */ /************************************************************************/ //int get_ArrowDir(IplImage *frame, CMPoint pROI0, CMPoint pROI1, CMPoint dir, Point &pStart, Point &pEnd) //{ // float k1, k2; //k1为原线段的斜率 // // if (pROI0.x != pROI1.x) //若不为一根垂直线 // { // k1 = (float)(pROI0.y - pROI1.y) / (float)(pROI0.x - pROI1.x); // if (k1 != 0) //若不为一根平行线 // { // k2 = -1 / k1; // //过线段一端画垂线 // pStart.x = pROI0.x; // pStart.y = pROI0.y; // if (pStart.x > dir.x) // pEnd.x = pStart.x - 20; //箭头长为20 // else // pEnd.x = pStart.x + 20; // pEnd.y = (pEnd.x - pStart.x) * k2 + pStart.y; // // ////过线段中点画垂线 // //pStart.x = (pROI0.x + pROI1.x) / 2; // //pStart.y = (pROI0.y + pROI1.y) / 2; // //pEnd.x = dir.x; // //pEnd.y = (pEnd.x - pStart.x) * k2 + pStart.y; // // } // else //若为水平线 // { // //过线段一端画垂线 // pStart.x = pROI0.x; // pStart.y = pROI0.y; // pEnd.x = pStart.x + 20; // pEnd.y = dir.y; // ////过线段中点画垂线 // //pStart.x = (pROI0.x + pROI1.x) / 2; // //pStart.y = pROI0.y; // //pEnd.x = pStart.x; // //pEnd.y = dir.y; // } // // } // else //若为垂直线 // { // //过线段一端画垂线 // pStart.y = pROI0.y; // pStart.x = pROI0.x; // pEnd.y = pStart.y; // pEnd.x = dir.x + 20; // ////过线段中点画垂线 // //pStart.y = (pROI0.y + pROI1.y) / 2; // //pStart.x = pROI0.x; // //pEnd.y = pStart.y; // //pEnd.x = dir.x; // } // //防止越界 // pEnd.x = pEnd.x >= 0 ? pEnd.x : 0; // pEnd.x = pEnd.x <= frame->width ? pEnd.x : frame->width; // pEnd.y = pEnd.y >= 0 ? pEnd.y : 0; // pEnd.y = pEnd.y <= frame->height ? pEnd.y : frame->height; // // 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; // } //} //画线 void DrawLine(unsigned char* pRGBIn, int widthStep, const sy_point & p_roi, const sy_point & dir_point) { int disX = abs(dir_point.x_ - p_roi.x_); int disY = abs(dir_point.y_ - p_roi.y_); if (disX >= disY) { if (p_roi.x_ != dir_point.x_) { sy_point p_roi_src = p_roi.x_ < dir_point.x_ ? p_roi : dir_point; sy_point p_roi_des = p_roi.x_ >= dir_point.x_ ? p_roi : dir_point; double tan = (double)(p_roi_des.y_ - p_roi_src.y_) / (double)(p_roi_des.x_ - p_roi_src.x_); for (unsigned int i = p_roi_src.x_; i <= p_roi_des.x_; ++i) { pRGBIn[(p_roi_src.y_ + (int)(tan * (i - p_roi_src.x_)))* widthStep + i * 3] = 0; pRGBIn[(p_roi_src.y_ + (int)(tan * (i - p_roi_src.x_)))* widthStep + i * 3 + 1] = 0; pRGBIn[(p_roi_src.y_ + (int)(tan * (i - p_roi_src.x_)))* widthStep + i * 3 + 2] = 0; } } else { pRGBIn[p_roi.x_* widthStep + p_roi.y_ * 3] = 0; pRGBIn[p_roi.x_* widthStep + p_roi.y_ * 3+1] = 0; pRGBIn[p_roi.x_* widthStep + p_roi.y_ * 3+2] = 0; } } else { if (p_roi.x_ != dir_point.x_) { sy_point p_roi_src = p_roi.y_ < dir_point.y_ ? p_roi : dir_point; sy_point p_roi_des = p_roi.y_ >= dir_point.y_ ? p_roi : dir_point; double cot = (double)(p_roi_des.x_ - p_roi_src.x_) / (double)(p_roi_des.y_ - p_roi_src.y_); for (unsigned int i = p_roi_src.y_; i <= p_roi_des.y_; ++i) { pRGBIn[i* widthStep + (int)(p_roi_src.x_ + cot *(i - p_roi_src.y_)) * 3] = 0; pRGBIn[i* widthStep + (int)(p_roi_src.x_ + cot *(i - p_roi_src.y_)) * 3 + 1] = 0; pRGBIn[i* widthStep + (int)(p_roi_src.x_ + cot *(i - p_roi_src.y_)) * 3 + 2] = 0; } } else { sy_point p_roi_src = p_roi.y_ < dir_point.y_ ? p_roi : dir_point; sy_point p_roi_des = p_roi.y_ >= dir_point.y_ ? p_roi : dir_point; for (unsigned int i = p_roi_src.y_; i <= p_roi_des.y_; ++i) { pRGBIn[i* widthStep + (int)(p_roi_src.x_) * 3] = 0; pRGBIn[i* widthStep + (int)(p_roi_src.x_) * 3 + 1] = 0; pRGBIn[i* widthStep + (int)(p_roi_src.x_) * 3 + 2] = 0; } } } } ////描绘区域 //void DrawRegion(unsigned char* pRGBIn, region_info* pRegionInfo, int numROI, int widthStep) //{ // for (int i = 0; i < numROI; ++i) // { // for (int j = 0; j <= pRegionInfo[i].point_num-1; ++j) // { // if (j < pRegionInfo[i].point_num - 1) // { // DrawLine(pRGBIn, widthStep, pRegionInfo[i].p_roi[j], pRegionInfo[i].p_roi[j + 1]); // } // else if (j = pRegionInfo[i].point_num - 1) // { // DrawLine(pRGBIn, widthStep, pRegionInfo[i].p_roi[j], pRegionInfo[i].p_roi[0]); // } // } // } //} //外接矩形描绘 void ExternalRectangle(unsigned char* pRGBIn, ms_object_info *ObjInfo, int ObjCount, int widthStep, int numROI) { int dwStep = widthStep; int i; // 前景目标外接矩形描绘 for (i = 0; i < ObjCount; i++) { //根据颜色区分报警情况 int alarm_flag = 0; for (int ii = 0; ii < numROI; ii++) { if (ObjInfo[i].pb_alarm_state == true) { //alarm_flag = 1; alarm_flag = ObjInfo[i].pb_alarm_type; break; } } // 无报警 蓝色 if (alarm_flag == 0) { for (int t = ObjInfo[i].tar_box.left_; t <= ObjInfo[i].tar_box.left_+ ObjInfo[i].tar_box.width_; t++) { pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3] = 255; pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3 + 2] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ ) * dwStep + t * 3] = 255; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ ) * dwStep + t * 3 + 1] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ ) * dwStep + t * 3 + 2] = 0; } for (int t = ObjInfo[i].tar_box.top_; t < ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_; t++) { pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3] = 255; pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3 + 1] = 0; pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3 + 2] = 0; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3] = 255; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3 + 1] = 0; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3 + 2] = 0; } } // else { //报警 进入禁区 红色 if (alarm_flag==1) { for (int t = ObjInfo[i].tar_box.left_; t <= ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_; t++) { pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3] = 0; pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3 + 1] = 0; pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3 + 2] = 255; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_) * dwStep + t * 3] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_) * dwStep + t * 3 + 1] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_) * dwStep + t * 3 + 2] = 255; } for (int t = ObjInfo[i].tar_box.top_; t < ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_; t++) { pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3] = 0; pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3 + 1] = 0; pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3 + 2] = 255; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3] = 0; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3 + 1] = 0; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3 + 2] = 255; } } //黄色 离开禁区 else if (alarm_flag ==2) { for (int t = ObjInfo[i].tar_box.left_; t <= ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_; t++) { pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3] = 0; pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3 + 1] = 255; pRGBIn[ObjInfo[i].tar_box.top_ * dwStep + t * 3 + 2] = 255; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_) * dwStep + t * 3] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_) * dwStep + t * 3 + 1] = 255; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_) * dwStep + t * 3 + 2] = 255; } for (int t = ObjInfo[i].tar_box.top_; t < (ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_); t++) { pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3] = 0; pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3 + 1] = 255; pRGBIn[t * dwStep + ObjInfo[i].tar_box.left_ * 3 + 2] = 255; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3] = 0; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3 + 1] = 255; pRGBIn[t * dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_) * 3 + 2] = 255; } } } } } //外接矩形描绘 void ExternalRectangle(unsigned char* pRGBIn, int width, int height, ms_object_info *ObjInfo, int ObjCount, int widthStep, int numROI) { int dwStep = widthStep; int i; // 前景目标外接矩形描绘 for (i = 0; i < ObjCount; i++) { //根据颜色区分报警情况 int alarm_flag = 0; for (int ii = 0; ii < numROI; ii++) { if (ObjInfo[i].pb_alarm_state == true) { alarm_flag = 1; //alarm_flag = ObjInfo[i].pb_alarm_type[ii]; break; } } if ((ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_) > height - LINE_PIXEL) { continue; } if ((ObjInfo[i].tar_box.width_ + ObjInfo[i].tar_box.left_) > width - LINE_PIXEL) { continue; } // 无报警 蓝色 if (alarm_flag == 0) { /*for (int t = ObjInfo[i].tar_box.left_; t <= ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_; t++) { for (int j = 0; j < LINE_PIXEL; ++j) { pRGBIn[(ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3] = 255; pRGBIn[(ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 1] = 0; pRGBIn[(ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 2] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3] = 255; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 1] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 2] = 0; } } for (int t = ObjInfo[i].tar_box.top_; t < ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_; t++) { for (int j = 0; j < LINE_PIXEL; ++j) { pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + j) * 3] = 255; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + j) * 3 + 1] = 0; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + j) * 3 + 2] = 0; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_ + j) * 3] = 255; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_ + j) * 3 + 1] = 0; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_ + j) * 3 + 2] = 0; } }*/ } else { for (int t = ObjInfo[i].tar_box.left_; t <= ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_; t++) { for (int j = 0; j < LINE_PIXEL; ++j) { pRGBIn[(ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3] = 0; pRGBIn[(ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 1] = 0; pRGBIn[(ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 2] = 255; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 1] = 0; pRGBIn[(ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_ + j) * dwStep + t * 3 + 2] = 255; } } for (int t = ObjInfo[i].tar_box.top_; t < ObjInfo[i].tar_box.height_ + ObjInfo[i].tar_box.top_; t++) { for (int j = 0; j < LINE_PIXEL; ++j) { pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + j) * 3] = 0; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + j) * 3 + 1] = 0; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + j) * 3 + 2] = 255; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_ + j) * 3] = 0; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_ + j) * 3 + 1] = 0; pRGBIn[(t)* dwStep + (ObjInfo[i].tar_box.left_ + ObjInfo[i].tar_box.width_ + j) * 3 + 2] = 255; } } } } } // 轨迹描绘 void Trajectory(unsigned char* pRGBIn, ms_object_info *ObjInfo, int ObjCount, int width, int height, int widthStep) { // 轨迹描绘 int dwStep = widthStep; int i; for (i = 0; i < ObjCount; i++) { unsigned char bRed = (unsigned char)((ObjInfo[i].unique_id % 3) * 85 + 85); unsigned char bGreen = (unsigned char)((ObjInfo[i].unique_id % 7) * 36 + 36); unsigned char bBlue = (unsigned char)((ObjInfo[i].unique_id % 13) * 20 + 15); int dwPointNum = ObjInfo[i].trace.trace_num; sy_point ptLast = ObjInfo[i].trace.obj_trace[0]; // 对目标的每一个匹配项进行遍历 for (int l = 1; l < dwPointNum; l++) { if (ObjInfo[i].trace.obj_trace[l].x_ == ptLast.x_ && ObjInfo[i].trace.obj_trace[l].y_ == ptLast.y_) { // Draw a point //描绘目标中心点 pRGBIn[ObjInfo[i].trace.obj_trace[l].y_ * dwStep + ObjInfo[i].trace.obj_trace[l].x_ * 3] = bBlue; pRGBIn[ObjInfo[i].trace.obj_trace[l].y_ * dwStep + ObjInfo[i].trace.obj_trace[l].x_ * 3 + 1] = bGreen; pRGBIn[ObjInfo[i].trace.obj_trace[l].y_ * dwStep + ObjInfo[i].trace.obj_trace[l].x_ * 3 + 2] = bRed; } else { // Draw line if (abs(ObjInfo[i].trace.obj_trace[l].x_ - ptLast.x_) > abs(ObjInfo[i].trace.obj_trace[l].y_ - ptLast.y_)) { double dk = ((double)ObjInfo[i].trace.obj_trace[l].y_ - ptLast.y_) / (ObjInfo[i].trace.obj_trace[l].x_ - ptLast.x_); double b = ObjInfo[i].trace.obj_trace[l].y_ - ObjInfo[i].trace.obj_trace[l].x_ * dk; int colMin = ObjInfo[i].trace.obj_trace[l].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)ObjInfo[i].trace.obj_trace[l].x_ - ptLast.x_) / (ObjInfo[i].trace.obj_trace[l].y_ - ptLast.y_); double b = ObjInfo[i].trace.obj_trace[l].x_ - ObjInfo[i].trace.obj_trace[l].y_ * dk; int rowMin = ObjInfo[i].trace.obj_trace[l].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 = ObjInfo[i].trace.obj_trace[l]; } } }