// This file is part of Motion Watch. // Motion Watch is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Motion Watch is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #include "mo_detect.h" bool imgDiff(const Mat &prev, const Mat &next, shared_t *share) { auto ret = false; detLog("img_diff() -- start()", share); if (prev.empty()) detLog("prev_frame is empty -- Borken frame from the camera assumed.", share); if (next.empty()) detLog("next_frame is empty -- EOF assumed.", share); if (!prev.empty() && !next.empty()) { Mat diff; absdiff(prev, next, diff); threshold(diff, diff, share->pixThresh, 255, THRESH_BINARY); auto diffScore = countNonZero(diff); detLog("diff_score: " + to_string(diffScore), share); ret = diffScore >= share->imgThresh; } detLog("img_diff() -- finished()", share); return ret; } Mat frameFF(VideoCapture *cap, int gap) { Mat ret; if (gap == 0) gap = 1; for (int i = 0; i < gap; ++i) { cap->grab(); } cap->retrieve(ret); if (!ret.empty()) { cvtColor(ret, ret, COLOR_BGR2GRAY); } return ret; } void wrOut(const string &buffFile, const Mat &vidThumb, shared_t *share) { detLog("wr_out() -- start()", share); detLog("buff_file: " + buffFile, share); auto dayStr = genTimeStr("%Y-%m-%d"); auto timStr = genTimeStr("%H%M%S"); auto outDir = cleanDir(share->outDir) + "/" + dayStr; if (!exists(outDir)) { enforceMaxDays(share->outDir, share); } auto vidOut = genDstFile(outDir, timStr.c_str(), "." + share->vidExt); auto imgOut = genDstFile(outDir, timStr.c_str(), ".jpg"); detLog("write_out_vid: " + vidOut, share); detLog("write_out_img: " + imgOut, share); enforceMaxClips(outDir, share); copy_file(buffFile.c_str(), vidOut.c_str()); remove(buffFile.c_str()); imwrite(imgOut.c_str(), vidThumb); genHTMLvid(vidOut, share); genHTMLul(outDir, share->camName + ": " + dayStr, share); genHTMLul(share->outDir, share->camName, share); detLog("wr_out() -- finished()", share); } bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share) { detLog("mo_detect() -- start()", share); detLog("buff_file: " + buffFile, share); auto mod = false; VideoCapture capture(buffFile.c_str(), CAP_FFMPEG); if (capture.isOpened()) { Mat prev; Mat next; auto frameCount = capture.get(CAP_PROP_FRAME_COUNT); auto frameGaps = frameCount / share->frameGap; detLog("frame_count: " + to_string(frameCount), share); detLog("frame_gaps: " + to_string(frameGaps), share); for (auto i = 0; i < frameGaps; i++) { if (prev.empty()) prev = frameFF(&capture, 1); else prev = next.clone(); next = frameFF(&capture, share->frameGap); if (imgDiff(prev, next, share)) { resize(next, vidThumb, Size(720, 480), INTER_LINEAR); mod = true; break; } } } else { detLog("failed to open the buff file for reading. check permissions and/or opencv's video-io support (gstreamer/ffmpeg).", share); } capture.release(); detLog("mo_detect() -- finished()", share); return mod; }