JustMotion/src/mo_detect.cpp
Maurice ONeal 5d12855fad v1.4.t1
added object detection code base on yolov5 machine vision model. also
added a stat file so motion and object detection values can be monitored
in real time if used with the 'watch' command.
2022-09-27 18:10:04 -04:00

133 lines
3.9 KiB
C++

// 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;
}
void secDiff(Mat imgA, Mat imgB, int rows, int cols, int rowOffs, int colOffs, Rect *block, bool *mod, shared_t *share)
{
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;
if (pnts >= share->blockThresh)
{
share->stat[ST_PIXDIFF] = to_string(pnts);
share->stat[ST_BLOCK_POS_X] = to_string(colOffs);
share->stat[ST_BLOCK_POS_Y] = to_string(rowOffs);
share->stat[ST_BLOCK_LEN_X] = to_string(cols);
share->stat[ST_BLOCK_LEN_Y] = to_string(rows);
block->x = colOffs;
block->y = rowOffs;
block->height = rows;
block->width = cols;
*mod = true; return;
}
}
}
}
}
bool imgDiff(Mat prev, Mat next, Rect *block, shared_t *share)
{
auto numOfXBlocks = prev.cols / share->blockX;
auto numOfYBlocks = prev.rows / share->blockY;
auto moInBlock = false;
vector<thread> threads;
for (auto x = 0; (x < numOfXBlocks) && !moInBlock; x += share->blockX)
{
for (auto y = 0; (y < numOfYBlocks) && !moInBlock; y += share->blockY)
{
threads.push_back(thread(secDiff, prev, next, share->blockY, share->blockX, y, x, block, &moInBlock, share));
}
}
for (auto &&thr : threads)
{
thr.join();
}
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;
share->stat = vector<string>(ST_LEN, string("0"));
while (capPair(prev, next, capture, share))
{
if (imgDiff(toGray(prev), toGray(next), block, share))
{
*img = next;
mod = true; break;
}
}
ofstream file(string(cleanDir(share->buffDir) + "/stat").c_str());
file << "pix_diff: " << share->stat[ST_PIXDIFF] << endl;
file << "block_pos_x: " << share->stat[ST_BLOCK_POS_X] << endl;
file << "block_pos_y: " << share->stat[ST_BLOCK_POS_Y] << endl;
file << "block_siz_x: " << share->stat[ST_BLOCK_LEN_X] << endl;
file << "block_siz_y: " << share->stat[ST_BLOCK_LEN_Y] << endl;
file << "--object_dection:" << endl;
file << " confidence: " << share->stat[ST_CONFIDENCE] << endl;
file << " class_score: " << share->stat[ST_CLASS_SCORE] << endl;
file.close();
}
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;
}