#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; listBBox = o.listBBox; 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; listBBox = o.listBBox; 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_pListIllInfo = std::make_shared(); } FuncIllegalInvasion::~FuncIllegalInvasion() { 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()) { std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS())); /* 更新线程信息 */ GThreadInfo.updateFuncInfo(m_funcThreadInfo); if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP) { break; } /* 判断是否在检测时间段内 */ if(!isInDetectTime(m_periodInfo)) { continue; } /* 更新算法ActionID */ { GVariable.mutexRW.lockForRead(); strFaceActionID = GVariable.ActFaceIdentify(); strCountActionID = GVariable.ActPersonCount(); GVariable.mutexRW.unlock(); } /* ----------------------------------------------------------------------- * 读取Redis数据 * ----------------------------------------------------------------------- */ readRedisData(m_listSrcAlarm); /* 找出房间的个数,按照房间进行判断 */ ListRoomIll listRoomIll; for(auto& it : m_funcThreadInfo.listRoomCamActInfo) { listRoomIll.addRoom(it.RoomID, it.RoomType); } /* ----------------------------------------------------------------------- * 处理读取到的数据 * ----------------------------------------------------------------------- */ /* 根据房间解析人脸识别的非法入侵,检测到了非法人脸,就可以直接报警了 */ for(auto& room : listRoomIll.getData()) { /* 对获取到的数据挨个判断 */ for(const auto& alarm : m_listSrcAlarm.listAlarmInfo) { if(room.RoomID != alarm->RoomID) { continue; } /* 统计这个房间内《人脸算法》检测到的最大人员数 */ if(alarm->ActionID == strFaceActionID) { if(alarm->listPersonInfo.size() > room.numMaxFace) { room.numMaxFace = alarm->listPersonInfo.size(); room.listBBox = 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_listSrcAlarm.listAlarmInfo) { if(room.RoomID != alarm->RoomID) { continue; } /* 人员计数 */ if(alarm->ActionID == strCountActionID) { /* 统计这个房间内《人员计数算法》检测到的最大人员数 */ if(alarm->listBbox.size() > room.numMaxPerson) { room.numMaxPerson = alarm->listBbox.size(); room.listBBox = 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()) { if(room.isAlarm) { auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType); /* 正在报警,检查缓存中是否有这个报警信息 */ 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 { auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType); if(pIll == nullptr) { /* 没有报警,继续下一个房间 */ continue; } /* 没有报警,检查是否是报警结束了,是否符合写入数据库的条件 */ QDateTime currTime = QDateTime::currentDateTime(); int secs = currTime.toSecsSinceEpoch() - pIll->FirstTime.toSecsSinceEpoch(); if(secs >= GVariable.AppIllInvasion_Time) { if(!pIll->strImageInfo.empty()) { /* 超过非法入侵的时间,写入数据库 */ AlarmInfo ai; ai.ChannelID = m_funcThreadInfo.ChannelID; ai.RoomID = pIll->RoomID; ai.ActionID = GVariable.ActPersonCount(); ai.ActionDes = pIll->strActionDec; ai.ImageInfo = pIll->strImageInfo; ai.StartTime = pIll->FirstTime; ai.EndTime = currTime; ai.EventTime = pIll->FirstTime; ai.listPersonInfo = room.listPersonInfo; ai.listBbox = room.listBBox; bool insertRet = m_fromWebAPI->insertAlarmInfo(ai); if(insertRet) { std::string actionName = GVariable.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.listBBox.size(), room.listPersonInfo.size()); } /* 删除这个非法入侵信息 */ m_pListIllInfo->deleteIllInfo(*pIll); } } } } m_listSrcAlarm.clearAlarmInfo(); } /* 读取Redis数据 */ // void FuncIllegalInvasion::readRedisData() // { // m_listSrcAlarm.clearAlarmInfo(); // /* 读取Redis数据 */ // for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo) // { // for(const auto& cam : roomInfo.mapCameraAction) // { // for(const auto act : cam.second) // { // /* 读取Redis数据 */ // std::string strKey = std::to_string(cam.first) + ":" + act; // std::string strRetValue; // // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey); // if(!m_fromRedis->getRedisString(strKey, strRetValue)) // { // // SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey); // std::this_thread::sleep_for(std::chrono::milliseconds(10)); // continue; // } // /* 解析数据,先设置基础数据 */ // AlarmInfo newAlarmInfo; // newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID; // newAlarmInfo.appFunction = m_funcThreadInfo.appFunction; // newAlarmInfo.RoomID = roomInfo.RoomID; // newAlarmInfo.DeviceID = cam.first; // newAlarmInfo.ActionID = act; // parseRedisBaseData(strRetValue, newAlarmInfo); // parseRedisBBoxesData(strRetValue, newAlarmInfo); // /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */ // if(!isEventTimeVaild(newAlarmInfo.EventTime)) // { // /* 事件时间超过600秒,可能是超脑挂了 */ // SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString()); // std::this_thread::sleep_for(std::chrono::milliseconds(100)); // continue; // } // m_listSrcAlarm.addAlarmInfo(newAlarmInfo); // SPDLOG_LOGGER_DEBUG(m_logger, "报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}", // strKey, roomInfo.RoomID, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), // newAlarmInfo.listBbox.size(), newAlarmInfo.listPersonInfo.size()); // } // } // } // }