Compare commits
No commits in common. "01a11741c780113becbea2ce5cec8a27bbe5a1bc" and "42814ab8ca10d4ce098531524f38d7a2df5d24fa" have entirely different histories.
01a11741c7
...
42814ab8ca
|
@ -3,5 +3,5 @@ project( MotionWatch )
|
||||||
find_package( OpenCV REQUIRED )
|
find_package( OpenCV REQUIRED )
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread")
|
||||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||||
add_executable( mow src/main.cpp src/common.cpp src/mo_detect.cpp )
|
add_executable( mow src/main.cpp src/common.cpp src/mo_detect.cpp src/obj_detect.cpp )
|
||||||
target_link_libraries( mow ${OpenCV_LIBS} )
|
target_link_libraries( mow ${OpenCV_LIBS} )
|
||||||
|
|
21
README.md
21
README.md
|
@ -45,15 +45,20 @@ buff_dir = /tmp/ramdisk/cam_name
|
||||||
# recommend to use a ramdisk tempfs for this since this directory is used
|
# recommend to use a ramdisk tempfs for this since this directory is used
|
||||||
# for lots of writes.
|
# for lots of writes.
|
||||||
#
|
#
|
||||||
consec_threshold = 512
|
color_threshold = 8
|
||||||
# motion is detected by comparing each frame in the camera feed for
|
# the color levels in each pixel of the camera stream can range from 0-255.
|
||||||
# differences in the pixels. this value determine how many consecutive
|
# in an ideal world the color differences in between frames should be 0 if
|
||||||
# pixels need to different or how large the suspect object in motion
|
# there is no motion but must cameras can't do this. the threshold value
|
||||||
# needs to be.
|
# here is used to filter if the pixels are truly different.
|
||||||
#
|
#
|
||||||
block_threshold = 1024
|
block_threshold = 3456
|
||||||
# this value tells the application how many "lines" of pixels need to
|
# this application detects motion by loading frames from the camera and
|
||||||
# exceed consec_threshold before being considered motion.
|
# 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_x = 64
|
block_x = 64
|
||||||
# this is the x coordinate size or horizontal size of a block of pixels
|
# this is the x coordinate size or horizontal size of a block of pixels
|
||||||
|
|
80
etc/classes.txt
Normal file
80
etc/classes.txt
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
person
|
||||||
|
bicycle
|
||||||
|
car
|
||||||
|
motorbike
|
||||||
|
aeroplane
|
||||||
|
bus
|
||||||
|
train
|
||||||
|
truck
|
||||||
|
boat
|
||||||
|
traffic light
|
||||||
|
fire hydrant
|
||||||
|
stop sign
|
||||||
|
parking meter
|
||||||
|
bench
|
||||||
|
bird
|
||||||
|
cat
|
||||||
|
dog
|
||||||
|
horse
|
||||||
|
sheep
|
||||||
|
cow
|
||||||
|
elephant
|
||||||
|
bear
|
||||||
|
zebra
|
||||||
|
giraffe
|
||||||
|
backpack
|
||||||
|
umbrella
|
||||||
|
handbag
|
||||||
|
tie
|
||||||
|
suitcase
|
||||||
|
frisbee
|
||||||
|
skis
|
||||||
|
snowboard
|
||||||
|
sports ball
|
||||||
|
kite
|
||||||
|
baseball bat
|
||||||
|
baseball glove
|
||||||
|
skateboard
|
||||||
|
surfboard
|
||||||
|
tennis racket
|
||||||
|
bottle
|
||||||
|
wine glass
|
||||||
|
cup
|
||||||
|
fork
|
||||||
|
knife
|
||||||
|
spoon
|
||||||
|
bowl
|
||||||
|
banana
|
||||||
|
apple
|
||||||
|
sandwich
|
||||||
|
orange
|
||||||
|
broccoli
|
||||||
|
carrot
|
||||||
|
hot dog
|
||||||
|
pizza
|
||||||
|
donut
|
||||||
|
cake
|
||||||
|
chair
|
||||||
|
sofa
|
||||||
|
pottedplant
|
||||||
|
bed
|
||||||
|
diningtable
|
||||||
|
toilet
|
||||||
|
tvmonitor
|
||||||
|
laptop
|
||||||
|
mouse
|
||||||
|
remote
|
||||||
|
keyboard
|
||||||
|
cell phone
|
||||||
|
microwave
|
||||||
|
oven
|
||||||
|
toaster
|
||||||
|
sink
|
||||||
|
refrigerator
|
||||||
|
book
|
||||||
|
clock
|
||||||
|
vase
|
||||||
|
scissors
|
||||||
|
teddy bear
|
||||||
|
hair drier
|
||||||
|
toothbrush
|
BIN
etc/yolov5s.onnx
Normal file
BIN
etc/yolov5s.onnx
Normal file
Binary file not shown.
|
@ -1,3 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
mkdir -p /etc/mow
|
||||||
|
cp ./etc/yolov5s.onnx /etc/mow/yolov5s.onnx
|
||||||
|
cp ./etc/classes.txt /etc/mow/classes.txt
|
||||||
cp ./.build-mow/mow /usr/bin/mow
|
cp ./.build-mow/mow /usr/bin/mow
|
||||||
|
|
|
@ -140,6 +140,18 @@ string genDstFile(const string &dirOut, const char *fmt, const string &ext)
|
||||||
return cleanDir(dirOut) + string("/") + genTimeStr(fmt) + ext;
|
return cleanDir(dirOut) + string("/") + genTimeStr(fmt) + ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string genTmpFile(const string &dirOut, const string &ext, shared_t *share)
|
||||||
|
{
|
||||||
|
createDirTree(cleanDir(dirOut));
|
||||||
|
|
||||||
|
if (share->tmpId == 9999999)
|
||||||
|
{
|
||||||
|
share->tmpId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleanDir(dirOut) + string("/") + to_string(share->tmpId++) + ext;
|
||||||
|
}
|
||||||
|
|
||||||
Mat toGray(const Mat &src)
|
Mat toGray(const Mat &src)
|
||||||
{
|
{
|
||||||
Mat ret;
|
Mat ret;
|
||||||
|
@ -169,6 +181,21 @@ void rdLine(const string ¶m, const string &line, int *value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<string> loadClassList()
|
||||||
|
{
|
||||||
|
vector<string> ret;
|
||||||
|
|
||||||
|
ifstream ifs("/etc/mow/classes.txt");
|
||||||
|
string line;
|
||||||
|
|
||||||
|
while (getline(ifs, line))
|
||||||
|
{
|
||||||
|
ret.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool rdConf(shared_t *share)
|
bool rdConf(shared_t *share)
|
||||||
{
|
{
|
||||||
ifstream varFile(share->conf.c_str());
|
ifstream varFile(share->conf.c_str());
|
||||||
|
@ -188,15 +215,20 @@ bool rdConf(shared_t *share)
|
||||||
share->postCmd.clear();
|
share->postCmd.clear();
|
||||||
share->buffDir.clear();
|
share->buffDir.clear();
|
||||||
|
|
||||||
share->consecThresh = 512;
|
share->colorThresh = 5;
|
||||||
share->secs = 60;
|
share->secs = 60;
|
||||||
share->blockX = 32;
|
share->blockX = 32;
|
||||||
share->blockY = 32;
|
share->blockY = 32;
|
||||||
share->blockThresh = 1024;
|
share->blockThresh = 900;
|
||||||
share->maxDays = 5;
|
share->maxDays = 5;
|
||||||
share->vidExt = "mp4";
|
share->vidExt = "mp4";
|
||||||
share->recLoopWait = false;
|
share->recLoopWait = false;
|
||||||
share->skipCmd = false;
|
share->skipCmd = false;
|
||||||
|
share->network = dnn::readNet("/etc/mow/yolov5s.onnx");
|
||||||
|
share->classNames = loadClassList();
|
||||||
|
|
||||||
|
share->network.setPreferableBackend(dnn::DNN_BACKEND_OPENCV);
|
||||||
|
share->network.setPreferableTarget(dnn::DNN_TARGET_CPU);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -207,7 +239,7 @@ bool rdConf(shared_t *share)
|
||||||
rdLine("recording_stream = ", line, &share->recordUrl);
|
rdLine("recording_stream = ", line, &share->recordUrl);
|
||||||
rdLine("output_dir = ", line, &share->outDir);
|
rdLine("output_dir = ", line, &share->outDir);
|
||||||
rdLine("post_cmd = ", line, &share->postCmd);
|
rdLine("post_cmd = ", line, &share->postCmd);
|
||||||
rdLine("consec_threshold = ", line, &share->consecThresh);
|
rdLine("color_threshold = ", line, &share->colorThresh);
|
||||||
rdLine("duration = ", line, &share->secs);
|
rdLine("duration = ", line, &share->secs);
|
||||||
rdLine("buff_dir = ", line, &share->buffDir);
|
rdLine("buff_dir = ", line, &share->buffDir);
|
||||||
rdLine("block_x = ", line, &share->blockX);
|
rdLine("block_x = ", line, &share->blockX);
|
||||||
|
@ -234,9 +266,6 @@ bool rdConf(shared_t *share)
|
||||||
|
|
||||||
new thread(enforceMaxDays, share);
|
new thread(enforceMaxDays, share);
|
||||||
|
|
||||||
createDirTree(cleanDir(share->buffDir));
|
|
||||||
system(string("touch " + cleanDir(share->buffDir) + "/stat").c_str());
|
|
||||||
|
|
||||||
share->retCode = 0;
|
share->retCode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,10 +336,10 @@ string parseForParam(const string &arg, int argc, char** argv, bool argOnly)
|
||||||
|
|
||||||
void statOut(shared_t *share)
|
void statOut(shared_t *share)
|
||||||
{
|
{
|
||||||
system(string("touch " + cleanDir(share->buffDir) + "/stat").c_str());
|
createDirTree(cleanDir(share->buffDir));
|
||||||
|
|
||||||
auto path = string(cleanDir(share->buffDir) + "/stat");
|
auto path = string(cleanDir(share->buffDir) + "/stat");
|
||||||
auto fd = open(path.c_str(), fstream::out | fstream::trunc);
|
auto fd = open(path.c_str(), O_WRONLY);
|
||||||
|
|
||||||
write(fd, share->stat.c_str(), share->stat.size() + 1);
|
write(fd, share->stat.c_str(), share->stat.size() + 1);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
44
src/common.h
44
src/common.h
|
@ -37,29 +37,36 @@ using namespace std;
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
|
|
||||||
#define BUF_SZ 10
|
#define BUF_SZ 10
|
||||||
#define APP_VER "1.5"
|
#define APP_VER "1.4.t7"
|
||||||
|
|
||||||
struct shared_t
|
struct shared_t
|
||||||
{
|
{
|
||||||
string stat;
|
vector<string> classNames;
|
||||||
string recordUrl;
|
dnn::Net network;
|
||||||
string outDir;
|
string stat;
|
||||||
string postCmd;
|
string recordUrl;
|
||||||
string conf;
|
string outDir;
|
||||||
string buffDir;
|
string postCmd;
|
||||||
string vidExt;
|
string conf;
|
||||||
bool init;
|
string buffDir;
|
||||||
bool recLoopWait;
|
string concatTxtTmp;
|
||||||
bool skipCmd;
|
string concatShTmp;
|
||||||
int consecThresh;
|
string createShTmp;
|
||||||
int secs;
|
string vidExt;
|
||||||
int blockThresh;
|
bool init;
|
||||||
int blockX;
|
bool recLoopWait;
|
||||||
int blockY;
|
bool skipCmd;
|
||||||
int maxDays;
|
int tmpId;
|
||||||
int retCode;
|
int colorThresh;
|
||||||
|
int secs;
|
||||||
|
int blockThresh;
|
||||||
|
int blockX;
|
||||||
|
int blockY;
|
||||||
|
int maxDays;
|
||||||
|
int retCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
string genTmpFile(const string &dirOut, const string &ext, shared_t *share);
|
||||||
string genDstFile(const string &dirOut, const char *fmt, const string &ext);
|
string genDstFile(const string &dirOut, const char *fmt, const string &ext);
|
||||||
string genTimeStr(const char *fmt);
|
string genTimeStr(const char *fmt);
|
||||||
string cleanDir(const string &path);
|
string cleanDir(const string &path);
|
||||||
|
@ -77,5 +84,6 @@ bool rdConf(shared_t *share);
|
||||||
bool capPair(Mat &prev, Mat &next, VideoCapture &capture, shared_t *share);
|
bool capPair(Mat &prev, Mat &next, VideoCapture &capture, shared_t *share);
|
||||||
Mat toGray(const Mat &src);
|
Mat toGray(const Mat &src);
|
||||||
vector<string> lsFilesInDir(const string &path, const string &ext);
|
vector<string> lsFilesInDir(const string &path, const string &ext);
|
||||||
|
vector<string> loadClassList();
|
||||||
|
|
||||||
#endif // COMMON_H
|
#endif // COMMON_H
|
||||||
|
|
18
src/main.cpp
18
src/main.cpp
|
@ -11,6 +11,7 @@
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
#include "mo_detect.h"
|
#include "mo_detect.h"
|
||||||
|
#include "obj_detect.h"
|
||||||
|
|
||||||
void detectLoop(shared_t *share)
|
void detectLoop(shared_t *share)
|
||||||
{
|
{
|
||||||
|
@ -22,15 +23,25 @@ void detectLoop(shared_t *share)
|
||||||
|
|
||||||
if ((bufFiles.size() >= 2) || (share->recLoopWait && !bufFiles.empty()))
|
if ((bufFiles.size() >= 2) || (share->recLoopWait && !bufFiles.empty()))
|
||||||
{
|
{
|
||||||
|
Rect blockArea;
|
||||||
|
Mat blockImg;
|
||||||
|
|
||||||
auto fullPath = cleanDir(share->buffDir) + "/" + bufFiles[0];
|
auto fullPath = cleanDir(share->buffDir) + "/" + bufFiles[0];
|
||||||
|
|
||||||
share->stat.clear();
|
share->stat.clear();
|
||||||
|
|
||||||
if (moDetect(fullPath, share))
|
if (moDetect(fullPath, &blockArea, &blockImg, share))
|
||||||
{
|
{
|
||||||
share->skipCmd = true;
|
if (objectInImage(blockImg, blockArea, share))
|
||||||
|
{
|
||||||
|
share->skipCmd = true;
|
||||||
|
|
||||||
wrOut(fullPath, share);
|
wrOut(fullPath, share);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remove(fullPath.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -97,6 +108,7 @@ int main(int argc, char** argv)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sharedRes.retCode = 0;
|
sharedRes.retCode = 0;
|
||||||
|
sharedRes.tmpId = 0;
|
||||||
sharedRes.recLoopWait = false;
|
sharedRes.recLoopWait = false;
|
||||||
sharedRes.skipCmd = false;
|
sharedRes.skipCmd = false;
|
||||||
sharedRes.init = true;
|
sharedRes.init = true;
|
||||||
|
|
|
@ -14,30 +14,33 @@
|
||||||
|
|
||||||
bool pixDiff(const uchar &pixA, const uchar &pixB, shared_t *share)
|
bool pixDiff(const uchar &pixA, const uchar &pixB, shared_t *share)
|
||||||
{
|
{
|
||||||
if (pixA > pixB) return true;
|
auto diff = 0;
|
||||||
if (pixB > pixA) return true;
|
|
||||||
|
|
||||||
return false;
|
if (pixA > pixB) diff = pixA - pixB;
|
||||||
|
if (pixB > pixA) diff = pixB - pixA;
|
||||||
|
|
||||||
|
if (diff < share->colorThresh)
|
||||||
|
{
|
||||||
|
diff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void secDiff(const Mat &imgA, const Mat &imgB, int id, int rows, int cols, int rowOffs, int colOffs, vector<sec_t> *results, mutex *secMutex, shared_t *share)
|
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)
|
||||||
{
|
{
|
||||||
auto diff = 0;
|
|
||||||
auto pnts = 0;
|
auto pnts = 0;
|
||||||
|
|
||||||
for (auto y = rowOffs; y < (rowOffs + rows); y++)
|
for (auto y = rowOffs; y < rows; y++)
|
||||||
{
|
{
|
||||||
for (auto x = colOffs; x < (colOffs + cols); x++)
|
for (auto x = colOffs; x < cols; x++)
|
||||||
{
|
{
|
||||||
auto pixA = imgA.at<uchar>(Point(x, y));
|
auto pixA = imgA.at<uchar>(Point(x, y));
|
||||||
auto pixB = imgB.at<uchar>(Point(x, y));
|
auto pixB = imgB.at<uchar>(Point(x, y));
|
||||||
|
|
||||||
if (pixDiff(pixA, pixB, share)) pnts += 1;
|
if (pixDiff(pixA, pixB, share))
|
||||||
else pnts = 0;
|
|
||||||
|
|
||||||
if (pnts >= share->consecThresh)
|
|
||||||
{
|
{
|
||||||
diff += 1;
|
pnts += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,28 +51,27 @@ void secDiff(const Mat &imgA, const Mat &imgB, int id, int rows, int cols, int r
|
||||||
res.y = rowOffs;
|
res.y = rowOffs;
|
||||||
res.xSize = cols;
|
res.xSize = cols;
|
||||||
res.ySize = rows;
|
res.ySize = rows;
|
||||||
res.pixDiff = diff;
|
res.pixDiff = pnts;
|
||||||
res.id = id;
|
|
||||||
|
|
||||||
lock_guard<mutex> guard(*secMutex);
|
lock_guard<mutex> guard(*secMutex);
|
||||||
|
|
||||||
results->push_back(res);
|
results->push_back(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool imgDiff(const Mat &prev, const Mat &next, shared_t *share)
|
bool imgDiff(const Mat &prev, const Mat &next, Rect *block, shared_t *share)
|
||||||
{
|
{
|
||||||
|
auto moInBlock = false;
|
||||||
|
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
vector<sec_t> results;
|
vector<sec_t> results;
|
||||||
mutex secMutex;
|
mutex secMutex;
|
||||||
|
|
||||||
auto id = 0;
|
|
||||||
|
|
||||||
for (auto x = 0; x < prev.cols; x += share->blockX)
|
for (auto x = 0; x < prev.cols; x += share->blockX)
|
||||||
{
|
{
|
||||||
// spawn all of the block motion detection threads.
|
// spawn all of the block motion detection threads.
|
||||||
for (auto y = 0; y < prev.rows; y += share->blockY, id += 1)
|
for (auto y = 0; y < prev.rows; y += share->blockY)
|
||||||
{
|
{
|
||||||
threads.push_back(thread(secDiff, prev, next, id, share->blockY, share->blockX, y, x, &results, &secMutex, share));
|
threads.push_back(thread(secDiff, prev, next, share->blockY, share->blockX, y, x, &results, &secMutex, share));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +91,12 @@ bool imgDiff(const Mat &prev, const Mat &next, shared_t *share)
|
||||||
auto x = results[i].x;
|
auto x = results[i].x;
|
||||||
auto y = results[i].y;
|
auto y = results[i].y;
|
||||||
auto diff = results[i].pixDiff;
|
auto diff = results[i].pixDiff;
|
||||||
auto id = results[i].id;
|
|
||||||
|
|
||||||
if (diff > 0)
|
share->stat += string("block_thread:")
|
||||||
{
|
+ " x=" + to_string(x)
|
||||||
share->stat += string("block_thread:") + " id=" + to_string(id) + " diff=" + to_string(diff) + "\n";
|
+ " y=" + to_string(y)
|
||||||
}
|
+ " pixdiff=" + to_string(diff)
|
||||||
|
+ "\n";
|
||||||
|
|
||||||
if ((results[i].pixDiff >= share->blockThresh) && (results[i].pixDiff > maxPixDiff))
|
if ((results[i].pixDiff >= share->blockThresh) && (results[i].pixDiff > maxPixDiff))
|
||||||
{
|
{
|
||||||
|
@ -103,10 +105,25 @@ bool imgDiff(const Mat &prev, const Mat &next, shared_t *share)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxPixDiff >= share->blockThresh;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return moInBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool moDetect(const string &buffFile, shared_t *share)
|
bool moDetect(const string &buffFile, Rect *block, Mat *img, shared_t *share)
|
||||||
{
|
{
|
||||||
auto mod = false;
|
auto mod = false;
|
||||||
|
|
||||||
|
@ -117,10 +134,15 @@ bool moDetect(const string &buffFile, shared_t *share)
|
||||||
Mat prev;
|
Mat prev;
|
||||||
Mat next;
|
Mat next;
|
||||||
|
|
||||||
while (capPair(prev, next, capture, share))
|
share->stat += "motion_detection-- clip_file - " + buffFile + "\n";
|
||||||
|
|
||||||
|
for (auto i = 0; capPair(prev, next, capture, share); ++i)
|
||||||
{
|
{
|
||||||
if (imgDiff(toGray(prev), toGray(next), share))
|
share->stat += "frame_pair-- " + to_string(i) + "\n";
|
||||||
|
|
||||||
|
if (imgDiff(toGray(prev), toGray(next), block, share))
|
||||||
{
|
{
|
||||||
|
*img = next;
|
||||||
mod = true; break;
|
mod = true; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
struct sec_t
|
struct sec_t
|
||||||
{
|
{
|
||||||
int id;
|
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int xSize;
|
int xSize;
|
||||||
|
@ -25,9 +24,9 @@ struct sec_t
|
||||||
int pixDiff;
|
int pixDiff;
|
||||||
};
|
};
|
||||||
|
|
||||||
void secDiff(const Mat &imgA, const Mat &imgB, int id, int rows, int cols, int rowOffs, int colOffs, vector<sec_t> *results, mutex *secMutex, shared_t *share);
|
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);
|
||||||
bool pixDiff(const uchar &pixA, const uchar &pixB, shared_t *share);
|
bool pixDiff(const uchar &pixA, const uchar &pixB, shared_t *share);
|
||||||
bool imgDiff(const Mat &prev, const Mat &next, shared_t *share);
|
bool imgDiff(const Mat &prev, const Mat &next, Rect *block, shared_t *share);
|
||||||
bool moDetect(const string &buffFile, shared_t *share);
|
bool moDetect(const string &buffFile, Rect *block, Mat *img, shared_t *share);
|
||||||
|
|
||||||
#endif // MO_DETECT_H
|
#endif // MO_DETECT_H
|
||||||
|
|
64
src/obj_detect.cpp
Normal file
64
src/obj_detect.cpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// 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 objectInImage(const Mat &src, const Rect &area, shared_t *share)
|
||||||
|
{
|
||||||
|
// reference: https://github.com/doleron/yolov5-opencv-cpp-python/blob/main/cpp/yolo.cpp
|
||||||
|
Mat blockImage(src, area);
|
||||||
|
Mat blob;
|
||||||
|
|
||||||
|
dnn::blobFromImage(blockImage, blob, 1./255., Size(area.width, area.height), cv::Scalar(), true, false);
|
||||||
|
|
||||||
|
share->network.setInput(blob);
|
||||||
|
|
||||||
|
vector<Mat> outputs;
|
||||||
|
|
||||||
|
share->network.forward(outputs, share->network.getUnconnectedOutLayersNames());
|
||||||
|
|
||||||
|
float *data = (float *)outputs[0].data;
|
||||||
|
|
||||||
|
share->stat += "object_detection---\n";
|
||||||
|
share->stat += " outputs_size=" + to_string(outputs.size()) + " looking_for_objects...\n";
|
||||||
|
|
||||||
|
for (int i = 0; i < 25200; ++i)
|
||||||
|
{
|
||||||
|
// confidence level data[4];
|
||||||
|
if (data[4] >= 0.4)
|
||||||
|
{
|
||||||
|
float *classesScores = data + 5;
|
||||||
|
|
||||||
|
Mat scores(1, share->classNames.size(), CV_32FC1, classesScores);
|
||||||
|
Point classId;
|
||||||
|
double maxClassScore;
|
||||||
|
|
||||||
|
minMaxLoc(scores, 0, &maxClassScore, 0, &classId);
|
||||||
|
|
||||||
|
share->stat += " potential_object[confidence_level]=" + to_string(data[4]) + "\n";
|
||||||
|
share->stat += " potential_object[class_score]=" + to_string(maxClassScore) + "\n";
|
||||||
|
|
||||||
|
if (maxClassScore > 0.2)
|
||||||
|
{
|
||||||
|
share->stat += " object_confirmed\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data += 85;
|
||||||
|
}
|
||||||
|
|
||||||
|
share->stat += " no_objects_found\n";
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
20
src/obj_detect.h
Normal file
20
src/obj_detect.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#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 objectInImage(const Mat &image, const Rect &area, shared_t *share);
|
||||||
|
|
||||||
|
#endif // OBJ_DETECT_H
|
Loading…
Reference in New Issue
Block a user