2022-09-22 20:57:46 -04:00
|
|
|
// 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 pixDiff(const uchar &pixA, const uchar &pixB, shared_t *share)
|
|
|
|
{
|
|
|
|
auto diff = 0;
|
|
|
|
|
|
|
|
if (pixA > pixB) diff = pixA - pixB;
|
|
|
|
if (pixB > pixA) diff = pixB - pixA;
|
|
|
|
|
|
|
|
if (diff < share->colorThresh)
|
|
|
|
{
|
|
|
|
diff = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return diff != 0;
|
|
|
|
}
|
|
|
|
|
2022-09-30 16:18:39 -04:00
|
|
|
void secDiff(const Mat &imgA, const Mat &imgB, int rows, int cols, int rowOffs, int colOffs, vector<sec_t> *results, mutex *secMutex, shared_t *share)
|
2022-09-22 20:57:46 -04:00
|
|
|
{
|
|
|
|
auto pnts = 0;
|
|
|
|
|
|
|
|
for (auto y = rowOffs; y < rows; y++)
|
|
|
|
{
|
|
|
|
for (auto x = colOffs; x < cols; x++)
|
|
|
|
{
|
|
|
|
auto pixA = imgA.at<uchar>(Point(x, y));
|
|
|
|
auto pixB = imgB.at<uchar>(Point(x, y));
|
|
|
|
|
|
|
|
if (pixDiff(pixA, pixB, share))
|
|
|
|
{
|
|
|
|
pnts += 1;
|
2022-09-29 11:37:10 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-22 20:57:46 -04:00
|
|
|
|
2022-09-29 11:37:10 -04:00
|
|
|
struct sec_t res;
|
2022-09-27 18:10:04 -04:00
|
|
|
|
2022-09-29 11:37:10 -04:00
|
|
|
res.x = colOffs;
|
|
|
|
res.y = rowOffs;
|
|
|
|
res.xSize = cols;
|
|
|
|
res.ySize = rows;
|
|
|
|
res.pixDiff = pnts;
|
2022-09-22 20:57:46 -04:00
|
|
|
|
2022-09-29 11:37:10 -04:00
|
|
|
lock_guard<mutex> guard(*secMutex);
|
2022-09-22 20:57:46 -04:00
|
|
|
|
2022-09-29 11:37:10 -04:00
|
|
|
results->push_back(res);
|
2022-09-22 20:57:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool imgDiff(Mat prev, Mat next, Rect *block, shared_t *share)
|
|
|
|
{
|
2022-09-30 16:18:39 -04:00
|
|
|
auto moInBlock = false;
|
2022-09-22 20:57:46 -04:00
|
|
|
|
|
|
|
vector<thread> threads;
|
2022-09-29 11:37:10 -04:00
|
|
|
vector<sec_t> results;
|
|
|
|
mutex secMutex;
|
2022-09-22 20:57:46 -04:00
|
|
|
|
2022-09-30 16:18:39 -04:00
|
|
|
for (auto x = 0; x < prev.cols; x += share->blockX)
|
2022-09-22 20:57:46 -04:00
|
|
|
{
|
2022-09-29 11:37:10 -04:00
|
|
|
// spawn all of the block motion detection threads.
|
2022-09-30 16:18:39 -04:00
|
|
|
for (auto y = 0; y < prev.rows; y += share->blockY)
|
2022-09-22 20:57:46 -04:00
|
|
|
{
|
2022-09-29 11:37:10 -04:00
|
|
|
threads.push_back(thread(secDiff, prev, next, share->blockY, share->blockX, y, x, &results, &secMutex, share));
|
2022-09-22 20:57:46 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto &&thr : threads)
|
|
|
|
{
|
2022-09-29 11:37:10 -04:00
|
|
|
// wait for all of the threads to finish.
|
2022-09-22 20:57:46 -04:00
|
|
|
thr.join();
|
|
|
|
}
|
|
|
|
|
2022-09-29 11:37:10 -04:00
|
|
|
auto maxPixDiff = 0;
|
|
|
|
auto blockPick = 0;
|
|
|
|
|
|
|
|
for (auto i = 0; i < results.size(); ++i)
|
|
|
|
{
|
|
|
|
// out of all of the results returned form the threads, pick
|
|
|
|
// the block with the highest amount of pixDiff.
|
2022-09-29 14:52:42 -04:00
|
|
|
auto x = results[i].x;
|
|
|
|
auto y = results[i].y;
|
2022-09-30 16:18:39 -04:00
|
|
|
auto xSz = results[i].xSize;
|
|
|
|
auto ySz = results[i].ySize;
|
2022-09-29 14:52:42 -04:00
|
|
|
auto diff = results[i].pixDiff;
|
|
|
|
|
2022-09-30 16:18:39 -04:00
|
|
|
share->stat += "block_thread:"
|
|
|
|
+ string(" x=") + to_string(x)
|
|
|
|
+ " y=" + to_string(y)
|
|
|
|
+ " x_len=" + to_string(xSz)
|
|
|
|
+ " y_len=" + to_string(ySz)
|
|
|
|
+ " pixdiff=" + to_string(diff) + "\n";
|
2022-09-29 11:37:10 -04:00
|
|
|
|
|
|
|
if ((results[i].pixDiff >= share->blockThresh) && (results[i].pixDiff > maxPixDiff))
|
|
|
|
{
|
|
|
|
maxPixDiff = results[i].pixDiff;
|
|
|
|
blockPick = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxPixDiff >= share->blockThresh)
|
|
|
|
{
|
|
|
|
// return true on this function with the block with the
|
|
|
|
// high pixDiff value which should be at or exceeds
|
|
|
|
// the block_threshold set by the conf file.
|
|
|
|
auto res = results[blockPick];
|
|
|
|
|
|
|
|
block->x = res.x;
|
|
|
|
block->y = res.y;
|
|
|
|
block->height = res.ySize;
|
|
|
|
block->width = res.xSize;
|
|
|
|
|
|
|
|
moInBlock = true;
|
|
|
|
}
|
|
|
|
|
2022-09-22 20:57:46 -04:00
|
|
|
return moInBlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool moDetect(const string &buffFile, Rect *block, Mat *img, shared_t *share)
|
|
|
|
{
|
|
|
|
auto mod = false;
|
|
|
|
|
|
|
|
VideoCapture capture(buffFile.c_str(), CAP_FFMPEG);
|
|
|
|
|
|
|
|
if (capture.isOpened())
|
|
|
|
{
|
|
|
|
Mat prev;
|
|
|
|
Mat next;
|
|
|
|
|
2022-09-30 16:18:39 -04:00
|
|
|
share->stat += "motion_detection -- clip_file - " + buffFile + "\n";
|
|
|
|
|
|
|
|
for (auto i = 0; capPair(prev, next, capture, share); ++i)
|
2022-09-22 20:57:46 -04:00
|
|
|
{
|
2022-09-30 16:18:39 -04:00
|
|
|
share->stat += "frame_pair-- " + to_string(i) + "\n";
|
|
|
|
|
2022-09-22 20:57:46 -04:00
|
|
|
if (imgDiff(toGray(prev), toGray(next), block, share))
|
|
|
|
{
|
|
|
|
*img = next;
|
|
|
|
mod = true; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cerr << "err: Could not open buff file: " << buffFile << " for reading. check formatting/permissions." << endl;
|
|
|
|
cerr << " Also check if opencv was compiled with FFMPEG encoding enabled." << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mod;
|
|
|
|
}
|