提交 6a6c53a2 authored 作者: blu's avatar blu

motion detect: new alg

上级 2ea0fac0
...@@ -85,7 +85,7 @@ private: ...@@ -85,7 +85,7 @@ private:
long long packetTsDelta = 0; long long packetTsDelta = 0;
float pps = 0, imgScalor = 1; float pps = 0, imgScalor = 1;
int pktLag = 0; int pktLag = 0;
int fps = 18; int fps = 0;
uint64_t pktCnt = 0; uint64_t pktCnt = 0;
// //
...@@ -550,13 +550,13 @@ private: ...@@ -550,13 +550,13 @@ private:
} }
bool proc = false; bool proc = false;
if(pktCnt % (this->fps / detPara.fpsProc + 1) == 0) { if(this->fps != 0 && pktCnt % (int(this->fps / detPara.fpsProc)) == 0) {
proc = true; proc = true;
} }
if(!proc) { if(!proc) {
if(pktCnt %18 == 0) if(pktCnt % 60 == 0)
spdlog::info("{} pps {}, lag {}, skip processing", this->selfId, this->pps, this->pktLag); spdlog::info("{} pps {}, fps {}, lag {}, skip processing", this->selfId, this->pps, this->fps, this->pktLag);
} }
else { else {
if(detect) { if(detect) {
...@@ -585,8 +585,10 @@ private: ...@@ -585,8 +585,10 @@ private:
{ {
static bool first = true; static bool first = true;
static cv::Mat avg; static cv::Mat avg;
static double _area = 0;
static int frameProcessed = 0;
vector<vector<cv::Point> > cnts; vector<vector<cv::Point> > cnts;
cv::Mat origin, gray, thresh; cv::Mat origin;
avcvhelpers::frame2mat(format, pFrame, origin); avcvhelpers::frame2mat(format, pFrame, origin);
// check region // check region
auto w = origin.size().width; auto w = origin.size().width;
...@@ -605,10 +607,10 @@ private: ...@@ -605,10 +607,10 @@ private:
//imgScalor = w * h / (FRAME_SIZE * FRAME_SIZE * 1.0); //imgScalor = w * h / (FRAME_SIZE * FRAME_SIZE * 1.0);
// cv::resize(origin, gray, cv::Size(FRAME_SIZE,FRAME_SIZE)); // cv::resize(origin, gray, cv::Size(FRAME_SIZE,FRAME_SIZE));
gray = origin.clone(); cv::Mat gray;
cv::cvtColor(gray, thresh, cv::COLOR_BGR2GRAY); cv::cvtColor(origin, gray, cv::COLOR_BGR2GRAY);
float fent = avcvhelpers::getEntropy(thresh); // float fent = avcvhelpers::getEntropy(thresh);
cv::GaussianBlur(thresh, gray, cv::Size(21, 21), cv::THRESH_BINARY); cv::GaussianBlur(gray, gray, cv::Size(21, 21), cv::THRESH_BINARY);
if(first) { if(first) {
// avg = cv::Mat::zeros(gray.size(), CV_32FC3); // avg = cv::Mat::zeros(gray.size(), CV_32FC3);
avg.release(); avg.release();
...@@ -619,22 +621,21 @@ private: ...@@ -619,22 +621,21 @@ private:
} }
#ifdef DEBUG #ifdef DEBUG
matShow3 = gray.clone(); matShow3 = avg;
matShow2 = origin; matShow2 = origin;
#endif #endif
// packetTm = chrono::system_clock::now(); // packetTm = chrono::system_clock::now();
packetTm = packetTs; packetTm = packetTs;
// TODO: AVG // TODO: AVG
// cv::accumulateWeighted(gray, avg, 0.5); // cv::accumulateWeighted(gray, avg, 0.5);
cv::absdiff(gray, avg, thresh); cv::Mat diff;
avg.release(); cv::absdiff(gray, avg, diff);
avg = gray.clone(); // if(!detect || fent < detPara.entropy) {
// return;
if(!detect || fent < detPara.entropy) { // }
return;
}
cv::threshold(thresh, gray, detPara.thre, 255, cv::THRESH_BINARY); cv::Mat thresh;
cv::threshold(diff, thresh, detPara.thre, 255, cv::THRESH_BINARY);
//cv::dilate(gray, thresh, cv::Mat(), cv::Point(-1,-1), 2); //cv::dilate(gray, thresh, cv::Mat(), cv::Point(-1,-1), 2);
#ifdef DEBUG #ifdef DEBUG
...@@ -643,14 +644,14 @@ private: ...@@ -643,14 +644,14 @@ private:
cv::findContours(thresh, cnts, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); cv::findContours(thresh, cnts, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
bool hasEvent = false; bool hasEvent = false;
int evtCnt = 0; static int evtCnt = 0;
int i = 0; int i = 0;
double area = (double)(detPara.area * imgScalor); double area = (double)(detPara.area * imgScalor);
if(area < 10) { if(area < 10) {
area = 10; area = 10;
} }
for(; i < cnts.size(); i++) { for(; i < cnts.size(); i++) {
auto _area = cv::contourArea(cnts[i]); _area = cv::contourArea(cnts[i]);
if(_area < area) { if(_area < area) {
// nothing // nothing
} }
...@@ -661,11 +662,14 @@ private: ...@@ -661,11 +662,14 @@ private:
#ifdef DEBUG #ifdef DEBUG
cv::putText(origin, "motion detected", cv::Point(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0,0,255),2); cv::putText(origin, "motion detected", cv::Point(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(0,0,255),2);
#endif #endif
spdlog::info("{} motion detected: idx {}, area: {}", selfId, i, _area); //spdlog::info("{} motion detected: idx {}, area: {}", selfId, i, _area);
break; break;
} }
} //end for } //end for
avg.release();
avg = gray.clone();
frameProcessed++;
spdlog::debug("{} contours {} area {}, thresh {} hasEvent {}", selfId, cnts.size(), hasEvent? cv::contourArea(cnts[i]):0, detPara.area, hasEvent); spdlog::debug("{} contours {} area {}, thresh {} hasEvent {}", selfId, cnts.size(), hasEvent? cv::contourArea(cnts[i]):0, detPara.area, hasEvent);
// business logic for event // business logic for event
...@@ -674,38 +678,43 @@ private: ...@@ -674,38 +678,43 @@ private:
long long dura = 0; long long dura = 0;
if(evtStartTmLast != 0) { if(evtStartTmLast != 0) {
dura = packetTm - evtStartTmLast; dura = packetTm - evtStartTmLast;
} }else{
switch(evtState) {
case NONE: {
if(hasEvent) {
evtState = PRE;
spdlog::info("{} state: NONE->PRE ({}, {})", selfId, dura, evtCnt);
evtStartTmOrig = packetTm;
evtStartTmLast = packetTm; evtStartTmLast = packetTm;
return;
} }
break; switch(evtState) {
} case NONE:
case PRE: { case PRE:
if(dura >= detPara.pre) { if(dura >= detPara.pre) {
if(evtCnt < detPara.fpsProc * dura/2) { auto thr = frameProcessed/2;
spdlog::info("state: PRE->NONE ({}, {})", dura, evtCnt); if(evtCnt <= thr) {
if(evtState == PRE) {
spdlog::info("{} state: PRE->NONE ({}, {}, {}, {}, {}, {})", selfId, this->fps, dura, frameProcessed, evtCnt, thr, _area);
evtState = NONE; evtState = NONE;
evtStartTmOrig = packetTm; evtStartTmOrig = packetTm - detPara.pre;
}else{ }else{
evtState = IN; spdlog::info("state: NONE->NONE ({}, {}, {}, {}, {}, {})", this->fps, dura, frameProcessed, evtCnt, thr, _area);
}
}else{
if(evtState == PRE) {
json p; json p;
spdlog::info("{} state: PRE->IN ({}, {})", selfId, dura, evtCnt); evtState = IN;
spdlog::info("{} state: PRE->IN ({}, {}, {}, {}, {}, {})", selfId, this->fps, dura, frameProcessed, evtCnt, thr, _area);
makeEvent(EV_MSG_EVENT_MOTION_START, evtStartTmOrig); makeEvent(EV_MSG_EVENT_MOTION_START, evtStartTmOrig);
auto tmp = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count(); auto tmp = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
packetTsDelta = tmp - packetTm; packetTsDelta = tmp - packetTm;
spdlog::info("{} packet ts delta: {}", selfId, packetTsDelta); spdlog::info("{} packet ts delta: {}", selfId, packetTsDelta);
}else{
evtState = PRE;
spdlog::info("{} state: NONE->PRE ({}, {}, {}, {}, {}, {})", selfId, this->fps, dura, frameProcessed, evtCnt, thr, _area);
evtStartTmOrig = packetTm;
}
} }
evtCnt = 0; evtCnt = 0;
frameProcessed = 0;
evtStartTmLast = packetTm; evtStartTmLast = packetTm;
} }
break; break;
}
case IN: { case IN: {
if( packetTm - evtStartTmOrig > 60 *detPara.maxDuration ) { if( packetTm - evtStartTmOrig > 60 *detPara.maxDuration ) {
evtStartTmOrig = packetTm; evtStartTmOrig = packetTm;
...@@ -714,30 +723,35 @@ private: ...@@ -714,30 +723,35 @@ private:
spdlog::warn("{} event video continued over {} minutes, force segmenting and continue", devSn, detPara.maxDuration); spdlog::warn("{} event video continued over {} minutes, force segmenting and continue", devSn, detPara.maxDuration);
spdlog::debug("{} state: IN->IN ({}, {})",selfId, dura, evtCnt); spdlog::debug("{} state: IN->IN ({}, {})",selfId, dura, evtCnt);
evtCnt = 0; evtCnt = 0;
frameProcessed = 0;
evtStartTmLast = packetTm; evtStartTmLast = packetTm;
}else if(dura >= detPara.post/2){ }else if(dura >= detPara.post/2){
if(evtCnt < detPara.fpsProc * dura/5){ auto thr = frameProcessed/5;
if(evtCnt <= thr){
evtState = POST; evtState = POST;
spdlog::info("{} state: IN->POST ({}, {})", selfId, dura, evtCnt); spdlog::info("{} state: IN->POST ({}, {}, {}, {}, {}, {})", selfId, this->fps, dura, frameProcessed, evtCnt, thr, _area);
}else{ }else{
spdlog::debug("{} state: IN->IN ({}, {})", selfId, dura, evtCnt); spdlog::info("{} state: IN->IN ({}, {}, {}, {}, {}, {})", selfId, this->fps, dura, frameProcessed, evtCnt, thr, _area);
} }
evtCnt = 0; evtCnt = 0;
frameProcessed = 0;
evtStartTmLast = packetTm; evtStartTmLast = packetTm;
} }
break; break;
} }
case POST: { case POST: {
if(dura >= detPara.post/2){ if(dura >= detPara.post/2){
if(evtCnt < detPara.fpsProc * dura/5){ auto thr = frameProcessed/5;
spdlog::info("state: POST->NONE ({}, {})", dura, evtCnt); if(evtCnt <= thr){
spdlog::info("{} state: POST->NONE ({}, {}, {}, {}, {}, {})",selfId, this->fps, dura, frameProcessed, evtCnt, thr, _area);
evtState = NONE; evtState = NONE;
makeEvent(EV_MSG_EVENT_MOTION_END, packetTs); makeEvent(EV_MSG_EVENT_MOTION_END, packetTs);
}else{ }else{
spdlog::info("state: POST->IN ({}, {})", dura, evtCnt); spdlog::info("{} state: POST->IN ({}, {}, {}, {}, {}, {})",selfId, this->fps, dura, frameProcessed, evtCnt, thr, _area);
evtState = IN; evtState = IN;
} }
evtCnt = 0; evtCnt = 0;
frameProcessed = 0;
evtStartTmLast = packetTm; evtStartTmLast = packetTm;
} }
break; break;
...@@ -851,28 +865,32 @@ protected: ...@@ -851,28 +865,32 @@ protected:
static int _fpsDetectCnt = 0; static int _fpsDetectCnt = 0;
static auto _pts = packet.pts; static auto _pts = packet.pts;
if(pAVFormatInput->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){ if(pAVFormatInput->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && this->fps == 0){
static auto num = pAVFormatInput->streams[packet.stream_index]->time_base.num; // static auto num = pAVFormatInput->streams[packet.stream_index]->time_base.num;
static auto den = pAVFormatInput->streams[packet.stream_index]->time_base.den; // static auto den = pAVFormatInput->streams[packet.stream_index]->time_base.den;
_fpsDetectCnt++; // _fpsDetectCnt++;
if(_fpsDetectCnt < 20){ // if(_fpsDetectCnt < 20){
if(_fpsDetectCnt == 1) { // if(_fpsDetectCnt == 1) {
_pts = packet.pts; // _pts = packet.pts;
} // }
} // }
else{ // else{
_pts = packet.pts - _pts; // _pts = packet.pts - _pts;
auto ts = _pts * 1.0* num/den; // auto ts = _pts * 1.0* num/den;
this->fps = int(20/ts); // this->fps = int(20/ts)+5;
if(this->fps <=5) { // if(this->fps <=5) {
this->fps = 18; // this->fps = 18;
} // }
spdlog::info("{} calc fps in 20 frame: ts: {}, fps: {}", selfId, ts, this->fps); // spdlog::debug("{} calc fps in 20 frame: ts: {}, fps: {}", selfId, ts, this->fps);
_fpsDetectCnt = 0; // _fpsDetectCnt = 0;
_pts = packet.pts; // _pts = packet.pts;
} // }
auto _fps = av_q2d(pAVFormatInput->streams[packet.stream_index]->r_frame_rate);
this->fps = this->fps > _fps? this->fps:_fps;
} }
if(pktCnt % EV_LOG_PACKET_CNT == 0) { if(pktCnt % EV_LOG_PACKET_CNT == 0) {
spdlog::info("{} seq: {}, pts: {}, dts: {}, idx: {}", selfId, pktCnt, packet.pts, packet.dts, packet.stream_index); spdlog::info("{} seq: {}, pts: {}, dts: {}, idx: {}", selfId, pktCnt, packet.pts, packet.dts, packet.stream_index);
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论