From c054356541ea4e5f26dd598909b03148e640f862 Mon Sep 17 00:00:00 2001 From: Maurice ONeal Date: Thu, 14 Jul 2022 10:19:37 -0400 Subject: [PATCH] Changed post motion detection conditioning The app will now count the amount of secs to record post motion detection instead of the amount of frames. Split the main loop timer with the motion timer in separate threads to make that happen. The parameter was added to the config file. Recording fps is now adjustable. --- README.md | 14 +++--- src/main.cpp | 138 +++++++++++++++++++-------------------------------- 2 files changed, 58 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 3e5da20..5af4b67 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ detection_stream = rtsp://1.2.3.4:554/h264cif output_dir = /path/to/footage/directory # this is the output directory that will be used to store recorded footage # from the camera. the file naming convention uses date codes. it creates -# a subfolder for the date if it needs to and then stores the video file +# a sub-folder for the date if it needs to and then stores the video file # using the time. # diff_threshold = 210 @@ -68,14 +68,12 @@ pixel_size = 3 # this is the pixel size of the detected object or movement. this can # prevent false positives due small moves in grass/plants or insects. # -frames_post_motion = 60 -# this is the amount frames to capture after motion was detected. +secs_post_motion = 3 +# this is the minimum amount of seconds to capture after motion was +# detected. # -minimum_recording_frames = 90 -# this is the minimum amount of frames needed before video footage is -# recorded to storage. this prevents video files that are too small to -# be of any use and reduces clutter. warning: setting this value too -# high could cause the application to use too much memory. +recording_fps = 25 +# recording fps to use when recording footage to storage. # section_size = 100 # detection frames are read in y axis sections and then runs gray level diff --git a/src/main.cpp b/src/main.cpp index c248ba6..db619bf 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,13 +27,13 @@ struct shared_t string conf; bool wrRunning; bool ffRunning; - int motion; + bool motion; + int fps; int secs; int thrWithMotion; int thresh; int pixSize; int postMoIncr; - int minRecFrames; int sectionSize; int retCode; @@ -81,7 +81,7 @@ bool createDirTree(const string &full_path) void vidCap(shared_t *share) { - if (share->buff.size() >= share->minRecFrames) + if (!share->buff.empty()) { share->wrRunning = true; @@ -104,7 +104,7 @@ void vidCap(shared_t *share) VideoWriter writer; - writer.open(dstPath, codec, 30.0, share->buff[0].size(), true); + writer.open(dstPath, codec, (double) share->fps, share->buff[0].size(), true); if (!writer.isOpened()) { @@ -205,11 +205,11 @@ bool grayDiff(Mat imgA, Mat imgB, shared_t *share) return share->thrWithMotion != 0; } -void timer(shared_t *share) +void loopTimer(shared_t *share) { sleep(share->secs); - if (share->motion == 0) + if (!share->motion) { share->ffRunning = false; } @@ -220,6 +220,13 @@ void timer(shared_t *share) } } +void motionTimer(shared_t *share) +{ + sleep(share->postMoIncr); + + share->motion = false; +} + Mat toGray(const Mat &src) { Mat ret; @@ -238,11 +245,11 @@ void moDetect(shared_t *share) while (share->ffRunning) { - if (share->motion == 0) dCap >> dFrame; + if (!share->motion) dCap >> dFrame; rCap >> rFrame; - if (dFrame.empty() && (share->motion == 0)) + if (dFrame.empty() && (!share->motion)) { // broken frames returned from the cameras i've tested this with would cause // the entire capture connection to drop, hence why this bit of code is here @@ -254,11 +261,9 @@ void moDetect(shared_t *share) { rCap.open(share->recordUrl, CAP_FFMPEG); } - else if (share->motion > 0) + else if (share->motion) { share->buff.push_back(rFrame.clone()); - - share->motion -= 1; } else if (dPrev.empty() || rPrev.empty()) { @@ -270,7 +275,9 @@ void moDetect(shared_t *share) share->buff.push_back(rPrev); share->buff.push_back(rFrame.clone()); - share->motion += share->postMoIncr; + share->motion = true; + + thread(motionTimer, share); rPrev.release(); dPrev.release(); @@ -303,7 +310,7 @@ string parseForParam(const string &arg, int argc, char** argv, bool argOnly) } else { - return string("true") + return string("true"); } } } @@ -311,19 +318,28 @@ string parseForParam(const string &arg, int argc, char** argv, bool argOnly) return string(); } +void rdLine(const string ¶m, const string &line, string *value) +{ + if (line.rfind(param.c_str(), 0) == 0) + { + *value = line.substr(param.size()); + + cout << param << *value << endl; + } +} + +void rdLine(const string ¶m, const string &line, int *value) +{ + if (line.rfind(param.c_str(), 0) == 0) + { + *value = strtol(line.substr(param.size()).c_str(), NULL, 10); + + cout << param << *value << endl; + } +} + bool rdConf(shared_t *share) { - // recording_stream - // detection_stream - // output_dir - // diff_threshold - // post_cmd - // duration - // pixel_size - // frames_post_motion - // minimum_recording_frames - // section_size - auto ret = false; share->retCode = ENOENT; @@ -344,66 +360,16 @@ bool rdConf(shared_t *share) if (line.rfind("#", 0) != 0) { - if (line.rfind("recording_stream = ", 0) == 0) - { - share->recordUrl = line.substr(19); - - cout << "recording_stream = " << share->recordUrl << endl; - } - else if (line.rfind("detection_stream = ", 0) == 0) - { - share->detectUrl = line.substr(19); - - cout << "detection_stream = " << share->detectUrl << endl; - } - else if (line.rfind("output_dir = ", 0) == 0) - { - share->outDir = line.substr(13); - - cout << "output_dir = " << share->outDir << endl; - } - else if (line.rfind("post_cmd = ", 0) == 0) - { - share->postCmd = line.substr(11); - - cout << "post_cmd = " << share->postCmd << endl; - } - else if (line.rfind("diff_threshold = ", 0) == 0) - { - share->thresh = strtol(line.substr(17).c_str(), NULL, 10); - - cout << "diff_threshold = " << share->thresh << endl; - } - else if (line.rfind("duration = ", 0) == 0) - { - share->secs = strtol(line.substr(11).c_str(), NULL, 10); - - cout << "duration = " << share->secs << endl; - } - else if (line.rfind("pixel_size = ", 0) == 0) - { - share->pixSize = strtol(line.substr(13).c_str(), NULL, 10); - - cout << "pixel_size = " << share->pixSize << endl; - } - else if (line.rfind("frames_post_motion = ", 0) == 0) - { - share->postMoIncr = strtol(line.substr(21).c_str(), NULL, 10); - - cout << "frames_post_motion = " << share->postMoIncr << endl; - } - else if (line.rfind("minimum_recording_frames = ", 0) == 0) - { - share->minRecFrames = strtol(line.substr(27).c_str(), NULL, 10); - - cout << "minimum_recording_frames = " << share->minRecFrames << endl; - } - else if (line.rfind("section_size = ", 0) == 0) - { - share->sectionSize = strtol(line.substr(15).c_str(), NULL, 10); - - cout << "section_size = " << share->sectionSize << endl; - } + rdLine("recording_stream = ", line, &share->recordUrl); + rdLine("detection_stream = ", line, &share->detectUrl); + rdLine("output_dir = ", line, &share->outDir); + rdLine("post_cmd = ", line, &share->postCmd); + rdLine("diff_threshold = ", line, &share->thresh); + rdLine("duration = ", line, &share->secs); + rdLine("pixel_size = ", line, &share->pixSize); + rdLine("secs_post_motion = ", line, &share->postMoIncr); + rdLine("section_size = ", line, &share->sectionSize); + rdLine("recording_fps = ", line, &share->fps); } } while(!line.empty()); @@ -441,14 +407,14 @@ int main(int argc, char** argv) else { sharedRes.retCode = 0; - sharedRes.motion = 0; + sharedRes.motion = false; sharedRes.wrRunning = false; while (rdConf(&sharedRes)) { sharedRes.ffRunning = true; - thread th1(timer, &sharedRes); + thread th1(loopTimer, &sharedRes); thread th2(moDetect, &sharedRes); // Wait for the threads to finish