v3.0.t4
I'm going to test a move away from opencv's videoio module. Videoio simply refuses to open any video file even with FFMPEG builtin. I tested old v2.2 code and even that failed on a fresh install of ubuntu sever so this tells me an update on opencv's side broke something. This issue is not new and frankly I'm tired of chasing it. I'm giving QT's QMediaPlayer a try to see how it works out. Will still need opencv for the absdiff and threshold functions, otherwise I would have dropped the API altogeather. Now that the app has QT::Multimedia, QT6 is now the minimum version it will support. CMakeList.txt and the setup script updated accordingly.
This commit is contained in:
parent
40ef014e0f
commit
496bac7d7e
|
@ -13,8 +13,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||
|
||||
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Multimedia REQUIRED)
|
||||
find_package(OpenCV REQUIRED)
|
||||
|
||||
add_executable(mow
|
||||
|
@ -31,4 +31,4 @@ add_executable(mow
|
|||
src/camera.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(mow Qt${QT_VERSION_MAJOR}::Core ${OpenCV_LIBS})
|
||||
target_link_libraries(mow Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Multimedia ${OpenCV_LIBS})
|
||||
|
|
24
setup.sh
24
setup.sh
|
@ -1,24 +1,4 @@
|
|||
#!/bin/sh
|
||||
apt update -y
|
||||
apt install -y pkg-config
|
||||
apt install -y cmake
|
||||
apt install -y make
|
||||
apt install -y g++
|
||||
apt install -y wget
|
||||
apt install -y unzip
|
||||
apt install -y git
|
||||
apt install -y ffmpeg
|
||||
apt install -y libavcodec-dev
|
||||
apt install -y libavformat-dev
|
||||
apt install -y libavutil-dev
|
||||
apt install -y libswscale-dev
|
||||
apt install -y libgstreamer1.0-dev
|
||||
apt install -y x264
|
||||
apt install -y libx264-dev
|
||||
apt install -y libilmbase-dev
|
||||
apt install -y libopencv-dev
|
||||
apt install -y qtbase5-dev
|
||||
apt install -y qtchooser
|
||||
apt install -y qt5-qmake
|
||||
apt install -y qtbase5-dev-tools
|
||||
apt install -y apache2
|
||||
apt install -y pkg-config cmake make g++ wget unzip git
|
||||
apt install -y ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libgstreamer1.0-dev x264 libx264-dev libilmbase-dev libopencv-dev qt6-base-dev qtchooser qmake6 qt6-base-dev-tools qt6-multimedia-dev apache2
|
||||
|
|
|
@ -19,6 +19,7 @@ Camera::Camera(QObject *parent) : QObject(parent)
|
|||
shared.camName.clear();
|
||||
|
||||
shared.retCode = 0;
|
||||
shared.maxScore = 0;
|
||||
shared.pixThresh = 50;
|
||||
shared.imgThresh = 800;
|
||||
shared.maxEvents = 40;
|
||||
|
@ -240,7 +241,8 @@ bool EventLoop::exec()
|
|||
if (wrOutVod(event))
|
||||
{
|
||||
genHTMLvod(event.evName);
|
||||
imwrite(QString("events/" + event.evName + ".jpg").toUtf8().data(), event.thumbnail);
|
||||
|
||||
event.thumbnail.save(QString("events/" + event.evName + ".jpg"));
|
||||
}
|
||||
|
||||
shared->recList.removeFirst();
|
||||
|
@ -317,13 +319,19 @@ DetectLoop::DetectLoop(shared_t *sharedRes, QThread *thr, QObject *parent) : Loo
|
|||
heartBeat = 0;
|
||||
evId = 0;
|
||||
pcId = 0;
|
||||
player = new QMediaPlayer(this);
|
||||
frameAnalyzer = new MoDetect(shared, this);
|
||||
|
||||
player->setVideoSink(frameAnalyzer);
|
||||
|
||||
connect(player, &QMediaPlayer::errorOccurred, this, &DetectLoop::playError);
|
||||
}
|
||||
|
||||
void DetectLoop::init()
|
||||
{
|
||||
thread()->sleep(1);
|
||||
|
||||
resetTimers(); Loop::init();
|
||||
resetTimers();
|
||||
}
|
||||
|
||||
void DetectLoop::resetTimers()
|
||||
|
@ -357,7 +365,8 @@ void DetectLoop::timerEvent(QTimerEvent *event)
|
|||
|
||||
shared->curEvent.srcPaths.clear();
|
||||
shared->curEvent.evName.clear();
|
||||
shared->curEvent.thumbnail.release();
|
||||
|
||||
shared->curEvent.thumbnail = QImage();
|
||||
|
||||
shared->maxScore = 0;
|
||||
}
|
||||
|
@ -380,6 +389,31 @@ void DetectLoop::timerEvent(QTimerEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void DetectLoop::resetDetect()
|
||||
{
|
||||
if (player->playbackState() != QMediaPlayer::PlayingState)
|
||||
{
|
||||
frameAnalyzer->stop();
|
||||
|
||||
exec();
|
||||
}
|
||||
}
|
||||
|
||||
void DetectLoop::playError(QMediaPlayer::Error error, const QString &errorString)
|
||||
{
|
||||
Q_UNUSED(error)
|
||||
|
||||
detLog("err: media player error - " + errorString, shared);
|
||||
resetDetect();
|
||||
}
|
||||
|
||||
void DetectLoop::playStateChanged(QMediaPlayer::PlaybackState newState)
|
||||
{
|
||||
Q_UNUSED(newState)
|
||||
|
||||
resetDetect();
|
||||
}
|
||||
|
||||
bool DetectLoop::exec()
|
||||
{
|
||||
QFile fileIn("stream.m3u8");
|
||||
|
@ -429,12 +463,9 @@ bool DetectLoop::exec()
|
|||
{
|
||||
prevTs = tsPath;
|
||||
|
||||
if (moDetect(tsPath, thread(), shared))
|
||||
{
|
||||
shared->curEvent.srcPaths.append(tsPath);
|
||||
|
||||
shared->skipCmd = true;
|
||||
}
|
||||
player->setSource(QUrl::fromLocalFile(tsPath));
|
||||
frameAnalyzer->play(tsPath);
|
||||
player->play();
|
||||
}
|
||||
|
||||
return Loop::exec();
|
||||
|
|
|
@ -117,13 +117,18 @@ private:
|
|||
int pcId;
|
||||
int evId;
|
||||
QString prevTs;
|
||||
QMediaPlayer *player;
|
||||
MoDetect *frameAnalyzer;
|
||||
|
||||
void resetTimers();
|
||||
void resetDetect();
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private slots:
|
||||
|
||||
void init();
|
||||
void playError(QMediaPlayer::Error error, const QString &errorString);
|
||||
void playStateChanged(QMediaPlayer::PlaybackState newState);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include <QFile>
|
||||
#include <QDateTime>
|
||||
#include <QThread>
|
||||
#include <QMediaPlayer>
|
||||
#include <QVideoSink>
|
||||
#include <QVideoFrame>
|
||||
#include <QImage>
|
||||
|
||||
#include <opencv4/opencv2/opencv.hpp>
|
||||
#include <opencv4/opencv2/videoio.hpp>
|
||||
|
@ -31,7 +35,7 @@
|
|||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
#define APP_VER "3.0.t3"
|
||||
#define APP_VER "3.0.t4"
|
||||
#define APP_NAME "Motion Watch"
|
||||
#define APP_BIN "mow"
|
||||
#define REC_LOG_NAME "rec_log_lines.html"
|
||||
|
@ -42,7 +46,7 @@ struct evt_t
|
|||
{
|
||||
QString evName;
|
||||
QStringList srcPaths;
|
||||
Mat thumbnail;
|
||||
QImage thumbnail;
|
||||
};
|
||||
|
||||
struct shared_t
|
||||
|
|
|
@ -12,93 +12,70 @@
|
|||
|
||||
#include "mo_detect.h"
|
||||
|
||||
bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share)
|
||||
MoDetect::MoDetect(shared_t *share, QObject *parent) : QVideoSink(parent)
|
||||
{
|
||||
Mat prevGray;
|
||||
Mat nextGray;
|
||||
shared = share;
|
||||
|
||||
cvtColor(prev, prevGray, COLOR_BGR2GRAY);
|
||||
cvtColor(next, nextGray, COLOR_BGR2GRAY);
|
||||
|
||||
Mat diff;
|
||||
|
||||
absdiff(prevGray, nextGray, diff);
|
||||
threshold(diff, diff, share->pixThresh, 255, THRESH_BINARY);
|
||||
|
||||
score = countNonZero(diff);
|
||||
|
||||
detLog("diff_score: " + QString::number(score) + " thresh: " + QString::number(share->imgThresh), share);
|
||||
|
||||
return score >= share->imgThresh;
|
||||
connect(this, &MoDetect::videoFrameChanged, this, &MoDetect::newFrame);
|
||||
}
|
||||
|
||||
bool moDetect(const QString &buffFile, QThread *thr, shared_t *share)
|
||||
void MoDetect::stop()
|
||||
{
|
||||
baseImg = QImage(); gap = 0; shared->maxScore = 0;
|
||||
}
|
||||
|
||||
void MoDetect::play(const QString &path)
|
||||
{
|
||||
filePath = path;
|
||||
}
|
||||
|
||||
void MoDetect::newFrame()
|
||||
{
|
||||
if (!baseImg.isNull())
|
||||
{
|
||||
baseImg = videoFrame().toImage().convertToFormat(QImage::Format_Grayscale8);
|
||||
}
|
||||
else if (shared->frameGap > gap)
|
||||
{
|
||||
gap++;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nextImg = videoFrame().toImage();
|
||||
auto nextImgGray = nextImg.convertToFormat(QImage::Format_Grayscale8);
|
||||
auto score = 0;
|
||||
auto mod = false;
|
||||
|
||||
detLog("stream_clip: " + buffFile, share);
|
||||
|
||||
VideoCapture capture;
|
||||
|
||||
if (!capture.open(buffFile.toUtf8().data(), CAP_FFMPEG))
|
||||
if (diff(baseImg, nextImgGray, &score))
|
||||
{
|
||||
thr->usleep(500);
|
||||
shared->skipCmd = true;
|
||||
|
||||
capture.open(buffFile.toUtf8().data(), CAP_FFMPEG);
|
||||
}
|
||||
|
||||
if (capture.isOpened())
|
||||
if (!shared->curEvent.srcPaths.contains(filePath))
|
||||
{
|
||||
Mat prev;
|
||||
Mat next;
|
||||
shared->curEvent.srcPaths.append(filePath);
|
||||
|
||||
int fps = capture.get(cv::CAP_PROP_FPS);
|
||||
|
||||
for (auto gap = 0, frm = fps; capture.grab(); ++gap, ++frm)
|
||||
if (shared->maxScore <= score)
|
||||
{
|
||||
if (frm == fps) thr->sleep(1); frm = 1;
|
||||
shared->maxScore = score;
|
||||
|
||||
if (prev.empty())
|
||||
shared->curEvent.thumbnail = nextImg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MoDetect::diff(QImage &base, QImage &next, int *score)
|
||||
{
|
||||
capture.retrieve(prev);
|
||||
}
|
||||
else if (gap == (share->frameGap - 1))
|
||||
{
|
||||
capture.retrieve(next);
|
||||
Mat baseMat = Mat(base.height(), base.width(), CV_8U, base.bits(), base.bytesPerLine());
|
||||
Mat nextMat = Mat(next.height(), next.width(), CV_8U, next.bits(), next.bytesPerLine());
|
||||
Mat diffMat;
|
||||
|
||||
if (!next.empty())
|
||||
{
|
||||
if (imgDiff(prev, next, score, share))
|
||||
{
|
||||
mod = true;
|
||||
absdiff(baseMat, nextMat, diffMat);
|
||||
threshold(diffMat, diffMat, shared->pixThresh, 255, THRESH_BINARY);
|
||||
|
||||
if (share->maxScore <= score)
|
||||
{
|
||||
share->maxScore = score;
|
||||
*score = countNonZero(diffMat);
|
||||
|
||||
resize(next, share->curEvent.thumbnail, Size(720, 480), INTER_LINEAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
detLog("diff_score: " + QString::number(*score) + " thresh: " + QString::number(shared->imgThresh), shared);
|
||||
|
||||
prev = next.clone();
|
||||
gap = 0;
|
||||
|
||||
next.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
capture.grab();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
detLog("err: failed to open: " + buffFile + " after 500 msecs. giving up.", share);
|
||||
}
|
||||
|
||||
capture.release();
|
||||
|
||||
return mod;
|
||||
return *score >= shared->imgThresh;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,29 @@
|
|||
#include "common.h"
|
||||
#include "logger.h"
|
||||
|
||||
bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share);
|
||||
bool moDetect(const QString &buffFile, QThread *thr, shared_t *share);
|
||||
class MoDetect : public QVideoSink
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
QImage baseImg;
|
||||
QString filePath;
|
||||
shared_t *shared;
|
||||
int gap;
|
||||
|
||||
bool diff(QImage &base, QImage &next, int *score);
|
||||
|
||||
private slots:
|
||||
|
||||
void newFrame();
|
||||
|
||||
public:
|
||||
|
||||
void play(const QString &path);
|
||||
void stop();
|
||||
|
||||
explicit MoDetect(shared_t *share, QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // MO_DETECT_H
|
||||
|
|
Loading…
Reference in New Issue
Block a user