diff --git a/CMakeLists.txt b/CMakeLists.txt index 32b6446..3b58453 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,5 +3,5 @@ project( MotionWatch ) find_package( OpenCV REQUIRED ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread") include_directories( ${OpenCV_INCLUDE_DIRS} ) -add_executable( mow src/main.cpp src/common.cpp src/mo_detect.cpp src/obj_detect.cpp ) +add_executable( mow src/main.cpp src/common.cpp src/mo_detect.cpp ) target_link_libraries( mow ${OpenCV_LIBS} ) diff --git a/README.md b/README.md index 3dad1aa..01c49c7 100644 --- a/README.md +++ b/README.md @@ -45,20 +45,15 @@ buff_dir = /tmp/ramdisk/cam_name # recommend to use a ramdisk tempfs for this since this directory is used # for lots of writes. # -color_threshold = 8 -# the color levels in each pixel of the camera stream can range from 0-255. -# in an ideal world the color differences in between frames should be 0 if -# there is no motion but must cameras can't do this. the threshold value -# here is used to filter if the pixels are truly different. +consec_threshold = 512 +# motion is detected by comparing each frame in the camera feed for +# differences in the pixels. this value determine how many consecutive +# pixels need to different or how large the suspect object in motion +# needs to be. # -block_threshold = 3456 -# this application detects motion by loading frames from the camera and -# then compare the pixels of each back to back frame for any significant -# differences between the pixels based on color_threshold. it loads the -# pixels of each frame in blocks. the size of the blocks are adjustable -# below. it counts how many pixels are different in the block and this is -# used to tell if the footage has motion if the different pixel count -# exceeds it. +block_threshold = 1024 +# this value tells the application how many "lines" of pixels need to +# exceed consec_threshold before being considered motion. # block_x = 64 # this is the x coordinate size or horizontal size of a block of pixels diff --git a/src/common.cpp b/src/common.cpp index b6ad38e..2cd5c61 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -188,11 +188,11 @@ bool rdConf(shared_t *share) share->postCmd.clear(); share->buffDir.clear(); - share->colorThresh = 5; + share->consecThresh = 512; share->secs = 60; share->blockX = 32; share->blockY = 32; - share->blockThresh = 900; + share->blockThresh = 1024; share->maxDays = 5; share->vidExt = "mp4"; share->recLoopWait = false; @@ -207,7 +207,7 @@ bool rdConf(shared_t *share) rdLine("recording_stream = ", line, &share->recordUrl); rdLine("output_dir = ", line, &share->outDir); rdLine("post_cmd = ", line, &share->postCmd); - rdLine("color_threshold = ", line, &share->colorThresh); + rdLine("consec_threshold = ", line, &share->consecThresh); rdLine("duration = ", line, &share->secs); rdLine("buff_dir = ", line, &share->buffDir); rdLine("block_x = ", line, &share->blockX); @@ -310,7 +310,7 @@ void statOut(shared_t *share) system(string("touch " + cleanDir(share->buffDir) + "/stat").c_str()); auto path = string(cleanDir(share->buffDir) + "/stat"); - auto fd = open(path.c_str(), O_WRONLY); + auto fd = open(path.c_str(), fstream::out | fstream::trunc); write(fd, share->stat.c_str(), share->stat.size() + 1); close(fd); diff --git a/src/common.h b/src/common.h index 1dbdc87..f6b5111 100644 --- a/src/common.h +++ b/src/common.h @@ -37,7 +37,7 @@ using namespace std; using namespace std::filesystem; #define BUF_SZ 10 -#define APP_VER "1.4.t9" +#define APP_VER "1.4.t11" struct shared_t { @@ -51,7 +51,7 @@ struct shared_t bool init; bool recLoopWait; bool skipCmd; - int colorThresh; + int consecThresh; int secs; int blockThresh; int blockX; diff --git a/src/mo_detect.cpp b/src/mo_detect.cpp index 83b5ba2..7d7ac4b 100644 --- a/src/mo_detect.cpp +++ b/src/mo_detect.cpp @@ -23,6 +23,7 @@ bool pixDiff(const uchar &pixA, const uchar &pixB, shared_t *share) void secDiff(const Mat &imgA, const Mat &imgB, int id, int rows, int cols, int rowOffs, int colOffs, vector *results, mutex *secMutex, shared_t *share) { auto diff = 0; + auto pnts = 0; for (auto y = rowOffs; y < (rowOffs + rows); y++) { @@ -31,13 +32,16 @@ void secDiff(const Mat &imgA, const Mat &imgB, int id, int rows, int cols, int r auto pixA = imgA.at(Point(x, y)); auto pixB = imgB.at(Point(x, y)); - if (pixDiff(pixA, pixB, share)) diff += 1; - else diff -= 1; + if (pixDiff(pixA, pixB, share)) pnts += 1; + else pnts = 0; + + if (pnts >= share->consecThresh) + { + diff += 1; + } } } - if (diff < 0) diff = 0; - struct sec_t res; res.x = colOffs; @@ -87,8 +91,11 @@ bool imgDiff(const Mat &prev, const Mat &next, shared_t *share) auto diff = results[i].pixDiff; auto id = results[i].id; - share->stat += string("block_thread:") + " id=" + to_string(id) + " diff=" + to_string(diff) + "\n"; - + if (diff > 0) + { + share->stat += string("block_thread:") + " id=" + to_string(id) + " diff=" + to_string(diff) + "\n"; + } + if ((results[i].pixDiff >= share->blockThresh) && (results[i].pixDiff > maxPixDiff)) { maxPixDiff = results[i].pixDiff; diff --git a/src/obj_detect.cpp b/src/obj_detect.cpp deleted file mode 100644 index c485161..0000000 --- a/src/obj_detect.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// 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 "obj_detect.h" - -bool objectFlowInImage(const Mat &inPrev, const Mat &inNext, const Rect &area, shared_t *share) -{ - Mat prev(inPrev, area); - Mat next(inNext, area); - - // optical flow calculations are used to detect motion. - // reference: https://docs.opencv.org/3.4/d4/dee/tutorial_optical_flow.html - vector p0, p1; - vector status; - vector err; - - auto criteria = TermCriteria((TermCriteria::COUNT) + (TermCriteria::EPS), 10, 0.03); - - // distance is basically 0.0578% of the total pixel area of the - // frames. this value is used later below. - auto thresh = ((double) 0.0578 / (double) 100) * (area.height * area.width); - auto count = 0; - - goodFeaturesToTrack(prev, p0, 100, 0.3, 7, Mat(), 7, false, 0.04); - calcOpticalFlowPyrLK(prev, next, p0, p1, status, err, Size(10, 10), 2, criteria); - - share->stat += " object_flow_detection-- block-" + to_string(area.x) + "x" + to_string(area.y) + "\n"; - - for(uint i = 0; i < p0.size(); i++) - { - // select good points - if(status[i] == 1) - { - auto dis = norm(p0[i] - p1[i]); - - if (dis > thresh) - { - // any points that moved 0.0578% or more of the total pixel - // area can be considered an object in motion. - - share->stat += " obj_move_greater_than=" + to_string(thresh) + "\n"; - share->stat += " obj_move_distance=" + to_string(dis) + "\n"; - - return true; - } - } - } - - share->stat += " no_object_flow_detected\n"; - - return false; -} diff --git a/src/obj_detect.h b/src/obj_detect.h deleted file mode 100644 index 456f3d8..0000000 --- a/src/obj_detect.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef OBJ_DETECT_H -#define OBJ_DETECT_H - -// 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 "common.h" - -bool objectFlowInImage(const Mat &inPrev, const Mat &inNext, const Rect &area, shared_t *share); - -#endif // OBJ_DETECT_H