JustMotion/src/mo_detect.cpp

143 lines
3.7 KiB
C++
Raw Normal View History

// 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 -- this should never happen (opencv to blame).", 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());
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(1280, 720), 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;
}