#include "FuncIllegalInvasion.h" #include "GlobalVariable.h" #include "GlobalConfig.h" #include "FromRedis.h" #include "FromWebAPI.h" #include "UniversalFunc.h" RoomIllegalInvasionInfo::RoomIllegalInvasionInfo(const RoomIllegalInvasionInfo& o) { isAlarm = o.isAlarm; RoomID = o.RoomID; RoomType = o.RoomType; numMaxFace = o.numMaxFace; numMaxPerson = o.numMaxPerson; strBoxList = o.strBoxList; strMessage = o.strMessage; strImage = o.strImage; CameraID = o.CameraID; } RoomIllegalInvasionInfo& RoomIllegalInvasionInfo::operator=(const RoomIllegalInvasionInfo& o) { if(this != &o) { isAlarm = o.isAlarm; RoomID = o.RoomID; RoomType = o.RoomType; numMaxFace = o.numMaxFace; numMaxPerson = o.numMaxPerson; strBoxList = o.strBoxList; strMessage = o.strMessage; strImage = o.strImage; CameraID = o.CameraID; } return *this; } /* 添加房间 */ void ListRoomIll::addRoom(int RoomID, Enum_RoomType RoomType) { auto p = findRoom(RoomID, RoomType); if(p == nullptr) { RoomIllegalInvasionInfo ill; ill.RoomID = RoomID; ill.RoomType = RoomType; listRoomIll.push_back(ill); } } /* 查找是否有相同的房间 */ RoomIllegalInvasionInfo* ListRoomIll::findRoom(int RoomID, Enum_RoomType RoomType) { for(auto& it : listRoomIll) { if(it.RoomID == RoomID && it.RoomType == RoomType) { return ⁢ } } return nullptr; } IllegalInvasionInfo::IllegalInvasionInfo(const IllegalInvasionInfo& other) { isInsertEQM = other.isInsertEQM; PKID = other.PKID; CameraID = other.CameraID; RoomID = other.RoomID; ChannelID = other.ChannelID; RoomType = other.RoomType; FirstTime = other.FirstTime; strActionDec = other.strActionDec; strImageInfo = other.strImageInfo; } IllegalInvasionInfo& IllegalInvasionInfo::operator=(const IllegalInvasionInfo& other) { if(this != &other) { isInsertEQM = other.isInsertEQM; PKID = other.PKID; CameraID = other.CameraID; RoomID = other.RoomID; ChannelID = other.ChannelID; RoomType = other.RoomType; FirstTime = other.FirstTime; strActionDec = other.strActionDec; strImageInfo = other.strImageInfo; } return *this; } /* 添加信息 */ void ListIllegalInvasionInfo::addIllInfo(IllegalInvasionInfo& info) { if(findIllInfo(info) == nullptr) { listIll.push_back(info); } } /* 查找相同的信息 */ IllegalInvasionInfo* ListIllegalInvasionInfo::findIllInfo(IllegalInvasionInfo& info) { for(auto& it : listIll) { if(it.RoomID == info.RoomID && it.RoomType == info.RoomType) { return ⁢ } } return nullptr; } IllegalInvasionInfo* ListIllegalInvasionInfo::findIllInfo(int roomID, Enum_RoomType roomType) { for(auto& it : listIll) { if(it.RoomID == roomID && it.RoomType == roomType) { return ⁢ } } return nullptr; } /* 删除报警信息 */ void ListIllegalInvasionInfo::deleteIllInfo(IllegalInvasionInfo& info) { for(auto it = listIll.begin(); it != listIll.end();) { if(it->RoomID == info.RoomID && it->RoomType == info.RoomType) { it = listIll.erase(it); }else { ++it; } } } void ListIllegalInvasionInfo::deleteIllInfo(int roomID, Enum_RoomType roomType) { for(auto it = listIll.begin(); it != listIll.end();) { if(it->RoomID == roomID && it->RoomType == roomType) { it = listIll.erase(it); }else { ++it; } } } /* =================================================================================== * 功能类:FuncIllegalInvasion * =================================================================================== */ FuncIllegalInvasion::FuncIllegalInvasion() { m_logger = spdlog::get("SPAServer"); if(m_logger == nullptr) { SPDLOG_ERROR("SPAServer logger is nullptr"); return; } m_pListAlarm = std::make_shared>(); m_pListIllInfo = std::make_shared(); } FuncIllegalInvasion::~FuncIllegalInvasion() { if(m_pListAlarm != nullptr) { m_pListAlarm.reset(); m_pListAlarm = nullptr; } if(m_pListIllInfo != nullptr) { m_pListIllInfo.reset(); m_pListIllInfo = nullptr; } } /* 是否报警 */ bool FuncIllegalInvasion::isAlarm(const std::list& listPersion) { for(const auto& it : listPersion) { if(it.PersonID == "-1") { return true; } } return false; } /* 线程功能 */ void FuncIllegalInvasion::task() { std::string strFaceActionID; /* 人脸识别的Action */ std::string strCountActionID; /* 人员计数的Action */ while (GThreadInfo.getRunning()) { /* 更新线程信息 */ GThreadInfo.updateFuncInfo(m_funcThreadInfo); if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP) { break; } /* 判断是否在检测时间段内 */ if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime)) { std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS)); continue; } /* 更新算法ActionID */ { g_actionList.mutexRW.lockForRead(); strFaceActionID = g_actionList.ActFace; strCountActionID = g_actionList.ActPersonNumber; g_actionList.mutexRW.unlock(); } /* 读取Redis数据 */ m_pListAlarm->clear(); for(const auto& RoomInfo : m_funcThreadInfo.listRoomCamActInfo) { for(const auto& it : RoomInfo.mapCameraAction) { for(const auto& act : it.second) { std::string strKey = std::to_string(it.first) + ":" + act; std::string strRetValue; if(!m_fromRedis->getRedisString(strKey, strRetValue)) { SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey); std::this_thread::sleep_for(std::chrono::milliseconds(100)); continue; } /* 解析数据 */ AlarmInfo alarmInfo; // parseRedisData(strRetValue, alarmInfo); parseRedisBaseData(strRetValue, alarmInfo); parseRedisBBoxesData(strRetValue, alarmInfo); /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */ if(isEventTimeVaild(alarmInfo.EventTime)) { SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime); std::this_thread::sleep_for(std::chrono::milliseconds(100)); continue; } m_pListAlarm->push_back(alarmInfo); } } } /* 找出房间的个数,按照房间进行判断 */ ListRoomIll listRoomIll; for(auto& it : m_funcThreadInfo.listRoomCamActInfo) { listRoomIll.addRoom(it.RoomID, it.RoomType); } /* 根据房间解析人脸识别的非法入侵,检测到了非法人脸,就可以直接报警了 */ for(auto& room : listRoomIll.getData()) { for(const auto& alarm : *m_pListAlarm) { if(room.RoomID != alarm.RoomID) { continue; } /* 统计这个房间内《人脸算法》检测到的最大人员数 */ if(alarm.ActionID == strFaceActionID) { if(alarm.listPersonInfo.size() > room.numMaxFace) { room.numMaxFace = alarm.listPersonInfo.size(); room.strBoxList = alarm.listBbox; room.listPersonInfo = alarm.listPersonInfo; } } /* 判断有没有非法入侵人员 */ if(isAlarm(alarm.listPersonInfo)) { room.isAlarm = true; room.strMessage = "人员非法入侵(未知人员)"; if( !alarm.ImageInfo.empty() ) { room.strImage = alarm.ImageInfo; } room.CameraID = alarm.DeviceID; } } } /* 判断《人脸算法》识别到的数目和《人员计数算法》识别到的人数是否相等,如果上面报警了,这里就不用检测了 */ for(auto& room : listRoomIll.getData()) { if(room.isAlarm) { continue; } /* 这个房间的人脸算法没有识别到非法入侵 */ for(const auto& alarm : *m_pListAlarm) { if(room.RoomID != alarm.RoomID) { continue; } /* 人员计数 */ if(alarm.ActionID == strCountActionID) { /* 统计这个房间内《人员计数算法》检测到的最大人员数 */ if(alarm.listPersonInfo.size() > room.numMaxPerson) { room.numMaxPerson = alarm.listPersonInfo.size(); room.strBoxList = alarm.listBbox; if(!alarm.ImageInfo.empty()) { room.strImage = alarm.ImageInfo; } room.CameraID = alarm.DeviceID; } } } /* 判断人数是否一致 */ if(room.numMaxFace != room.numMaxPerson) { room.strMessage = fmt::format("非法入侵(人员计数 {} 和人脸数 {} 不一致)", room.numMaxPerson, room.numMaxFace); room.isAlarm = true; } } /* 将非法入侵的信息存储到数组缓存中,等待报警结束后判断是否需要写入EQM数据库 */ for(auto& room : listRoomIll.getData()) { auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType); if(room.isAlarm) { /* 正在报警,检查缓存中是否有这个报警信息 */ if(pIll == nullptr) { IllegalInvasionInfo info; info.ChannelID = m_funcThreadInfo.ChannelID; info.CameraID = room.CameraID; info.RoomID = room.RoomID; info.RoomType = room.RoomType; info.strActionDec = room.strMessage; info.strImageInfo = room.strImage; info.FirstTime = QDateTime::currentDateTime();; m_pListIllInfo->addIllInfo(info); } } else { /* 没有报警,检查是否是报警结束了,是否符合写入数据库的条件 */ QDateTime currTime = QDateTime::currentDateTime(); int secs = currTime.toSecsSinceEpoch() - pIll->FirstTime.toSecsSinceEpoch(); if(secs >= GConfig.AppBadMan_Time) { if(!pIll->strImageInfo.empty()) { /* 超过非法入侵的时间,写入数据库 */ AlarmInfo ai; ai.ChannelID = m_funcThreadInfo.ChannelID; ai.RoomID = pIll->RoomID; ai.ActionID = g_actionList.ActPersonNumber; ai.ActionDes = pIll->strActionDec; ai.ImageInfo = pIll->strImageInfo; ai.StartTime = pIll->FirstTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(); ai.EndTime = currTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(); ai.EventTime = pIll->FirstTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(); ai.listPersonInfo = room.listPersonInfo; ai.listBbox = room.strBoxList; bool insertRet = m_fromWebAPI->insertAlarmInfo(ai); if(insertRet) { std::string actionName = g_actionList.getActionName(ai.ActionID); SPDLOG_LOGGER_INFO(m_logger, "☆ 新增报警信息,频道[{}],房间[{}],摄像头[{}],{},{},有{}个区域,有{}个人脸,{}", pIll->ChannelID, pIll->RoomID, pIll->CameraID, actionName, ai.ActionDes, ai.listBbox.size(), ai.FaceIDList.size(), ai.ImageInfo); } } else { SPDLOG_LOGGER_WARN(m_logger, "× 取消新增报警信息,因为没有图片,频道[{}],房间[{}],摄像头[{}],{},{},有{}个区域,有{}个人脸", pIll->ChannelID, pIll->RoomID, pIll->CameraID, pIll->strActionDec, pIll->strImageInfo, room.strBoxList.size(), room.listPersonInfo.size()); } /* 删除这个非法入侵信息 */ m_pListIllInfo->deleteIllInfo(*pIll); } } } std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS)); } }