Skip to content

Commit

Permalink
Now requires OpenCV 4.0.1 and CoreLibrary linked as static lib instea…
Browse files Browse the repository at this point in the history
…d of as dynamics lib.

Also rebuilt tested using Qt 5.12/Qt Creator 4.8.
  • Loading branch information
Unknown committed Jan 1, 2019
1 parent 4bcb9e6 commit fedf5bd
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 111 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Copyright (C) 2018 Duncan Crutchley.
## Background ##
I started this project shortly after buying and installing some RTSP compatible IP security cameras at my house. The software that came with the cameras was adequate but not great; relying on ActiveX and Internet Explorer. Instead this project provides a native application to view and record up to 4 cameras' streams. Currently, this application does not give you any control over the IP cameras' on-board settings.

## Key Features (Current Version 1.1.5.0) ##
## Key Features (Current Version 1.1.6.0) ##
* Clean and intuitive UI, hopefully!
* Multi-threaded.
* Cross-platform (Windows and Linux).
Expand Down Expand Up @@ -66,20 +66,20 @@ Taken from release 1.1.5.0.
[pic09]: https://github.com/dac1976/IP-Freely/blob/master/Images/pic09.png "Motion region setup."

## Build Requirements ##
This application has been developed in Qt Creator and tested for use in Windows 10 and Linux (Ubuntu 17.10). In Windows it is recommended to use the MSVC2015 64bit tool chain from within Qt Creator to build and test the code. In Linux the code has been tested with GCC 7.2.0 but other C++11 compilers should be fine, such as Clang.
This application has been developed in Qt Creator and tested for use in Windows 10 and Linux (Ubuntu 17.10+ or Manjaro 17+). In Windows it is recommended to use the MSVC2015 or MSVC 2017 64bit tool chain from within Qt Creator to build and test the code. In Linux the code has been tested with GCC 7.2.0+ but other C++1y compilers should be fine, such as Clang.

The project supplied for the application is for Qt Creator and will work in Linux and Windows. This project can be customized to suit the user's own environment and paths.
The project supplied for the application is for Qt Creator and will work in Linux and Windows. This project can be customized to suit the user's own environment and paths. I will mainly maintain the Linux version.

You may use this code within other supported development and build environments but it is up to the user to create the required projects or makefiles for those environments. This should be fairly easy by referring to the Qt project (.pro) file.

This library requires some third-party open source libraries for it to compile and function. These are as follows:
* Boost (tested with 1.65.1 and 1.66.0 but newest version recommended): http://www.boost.org/
* Boost (tested with 1.65.1 to 1.68.0 but newest version recommended): http://www.boost.org/
* Cereal (tested with 1.2.2 but newest version recommended): http://uscilab.github.io/cereal/
* Loki: http://loki-lib.sourceforge.net/
* CoreLibrary (requires with 1.4.6.0 but newest version recommended): https://github.com/dac1976/CoreLibrary
* Qt Framework (tested with 5.10 and 5.10.1 but should work with any 5.X version): http://www.qt.io
* CoreLibrary (requires with 1.4.6.0 and greater): https://github.com/dac1976/CoreLibrary
* Qt Framework (tested with 5.10 to 5.12 but should work with any 5.X version): http://www.qt.io
* Single Application: https://github.com/itay-grudev/SingleApplication
* OpenCV (tested with 3.4.0 but other 3.X versions should work): https://opencv.org/releases.html
* OpenCV (now requires 4.0.1): https://opencv.org/releases.html

Please note that some of these libraries themselves require other dependencies, so please refer to their documentation.

Expand Down
16 changes: 8 additions & 8 deletions Source/IpFreely.pro
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ TEMPLATE = app
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

CONFIG += core_lib_dll
CONFIG += core_lib c++14

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
Expand Down Expand Up @@ -68,13 +68,13 @@ else {
QMAKE_CXXFLAGS += -std=c++14

# Set version info for library.
VERSION = 1.1.5
VERSION = 1.1.6

INCLUDEPATH += /usr/local/include \
/home/duncan/projects/ThirdParty \
/home/duncan/projects/ThirdParty/singleapplication
INCLUDEPATH += /usr/include/opencv4 \
/mnt/Data/projects/ThirdParty \
/mnt/Data/projects/ThirdParty/singleapplication

LIBS += -L/usr/local/lib \
LIBS += -L/usr/lib \
-lopencv_core \
-lopencv_imgcodecs \
-lopencv_imgproc \
Expand All @@ -83,10 +83,10 @@ else {
#-lopencv_highgui

SOURCES += \
/home/duncan/projects/ThirdParty/singleapplication/singleapplication.cpp
/mnt/Data/projects/ThirdParty/singleapplication/singleapplication.cpp

HEADERS += \
/home/duncan/projects/ThirdParty/singleapplication/singleapplication.h
/mnt/Data/projects/ThirdParty/singleapplication/singleapplication.h
}

SOURCES += \
Expand Down
8 changes: 4 additions & 4 deletions Source/IpFreely.rc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
IDI_ICON1 ICON DISCARDABLE "IpFreely.ico"

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,5,0
PRODUCTVERSION 1,1,5,0
FILEVERSION 1,1,6,0
PRODUCTVERSION 1,1,6,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
Expand All @@ -25,11 +25,11 @@ VS_VERSION_INFO VERSIONINFO
BEGIN
VALUE "CompanyName", "~\0"
VALUE "FileDescription", "IP Freely (IP/Web camera stream viewer and recorder)\0"
VALUE "FileVersion", "1.1.5.0\0"
VALUE "FileVersion", "1.1.6.0\0"
VALUE "LegalCopyright", "Copyright 2018 Duncan Crutchley\0"
VALUE "OriginalFilename", "IpFreely\0"
VALUE "ProductName", "IpFreely\0"
VALUE "ProductVersion", "1.1.5.0\0"
VALUE "ProductVersion", "1.1.6.0\0"
END
END
BLOCK "VarFileInfo"
Expand Down
9 changes: 3 additions & 6 deletions Source/IpFreelyDiskSpaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <QStorageInfo>
#include <sstream>
#include <algorithm>
#include <boost/throw_exception.hpp>
#include <boost/exception/all.hpp>
#include <boost/filesystem.hpp>
#include "Threads/EventThread.h"
#include "DebugLog/DebugLogging.h"
Expand Down Expand Up @@ -101,8 +101,7 @@ void IpFreelyDiskSpaceManager::CheckUsedDiskSpace()
if (percentUsed > m_maxPercentUsedSpace)
{
DEBUG_MESSAGE_EX_INFO("Percentage disk space used is too great ("
<< percentUsed
<< "%), will attempt to delete oldest data.");
<< percentUsed << "%), will attempt to delete oldest data.");

if (!DeleteOldestRecording())
{
Expand All @@ -121,9 +120,7 @@ void IpFreelyDiskSpaceManager::CheckNumDaysDataStored()
while (m_subDirs.size() > static_cast<size_t>(m_maxNumDaysToStore))
{
DEBUG_MESSAGE_EX_INFO("Too many days data found on disk. Expected: "
<< m_maxNumDaysToStore
<< " but found: "
<< m_subDirs.size()
<< m_maxNumDaysToStore << " but found: " << m_subDirs.size()
<< ". Will attempt to delete oldest data.");

if (!DeleteOldestRecording())
Expand Down
25 changes: 10 additions & 15 deletions Source/IpFreelyMotionDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ void IpFreelyMotionDetector::InitialiseFrames()
m_prevGreyFrame = *m_originalFrame;
}

cv::cvtColor(m_prevGreyFrame, m_prevGreyFrame, CV_BGR2GRAY);
cv::cvtColor(m_prevGreyFrame, m_prevGreyFrame, cv::COLOR_BGR2GRAY);

if (m_cameraDetails.shrinkVideoFrames)
{
Expand All @@ -199,7 +199,7 @@ void IpFreelyMotionDetector::InitialiseFrames()
m_currentGreyFrame = *m_originalFrame;
}

cv::cvtColor(m_currentGreyFrame, m_currentGreyFrame, CV_BGR2GRAY);
cv::cvtColor(m_currentGreyFrame, m_currentGreyFrame, cv::COLOR_BGR2GRAY);
}

void IpFreelyMotionDetector::UpdateNextFrame()
Expand All @@ -218,7 +218,7 @@ void IpFreelyMotionDetector::UpdateNextFrame()
m_nextGreyFrame = *m_originalFrame;
}

cv::cvtColor(m_nextGreyFrame, m_nextGreyFrame, CV_BGR2GRAY);
cv::cvtColor(m_nextGreyFrame, m_nextGreyFrame, cv::COLOR_BGR2GRAY);
}

bool IpFreelyMotionDetector::DetectMotion()
Expand All @@ -240,7 +240,8 @@ bool IpFreelyMotionDetector::DetectMotion()
cv::absdiff(m_prevGreyFrame, m_nextGreyFrame, diff1);
cv::absdiff(m_nextGreyFrame, m_currentGreyFrame, diff2);
cv::bitwise_and(diff1, diff2, motion);
cv::threshold(motion, motion, m_cameraDetails.pixelThreshold, DIFF_MAX_VALUE, CV_THRESH_BINARY);
cv::threshold(
motion, motion, m_cameraDetails.pixelThreshold, DIFF_MAX_VALUE, cv::THRESH_BINARY);
cv::erode(motion, motion, m_erosionKernel);

// Now work out the std dev of the motion frame.
Expand Down Expand Up @@ -431,15 +432,10 @@ bool IpFreelyMotionDetector::CheckForIntersections()
motionIntersection = true;

DEBUG_MESSAGE_EX_INFO("Motion detector intersection found for camera stream URL: "
<< m_cameraDetails.streamUrl
<< ", region details: L = "
<< region.first.first
<< ", T = "
<< region.first.second
<< ", W = "
<< region.second.first
<< ", H = "
<< region.second.second);
<< m_cameraDetails.streamUrl << ", region details: L = "
<< region.first.first << ", T = " << region.first.second
<< ", W = " << region.second.first
<< ", H = " << region.second.second);

break;
}
Expand Down Expand Up @@ -523,8 +519,7 @@ void IpFreelyMotionDetector::CreateCaptureObjects()

DEBUG_MESSAGE_EX_INFO(
"Motion detector file duration reached for current video file, camera stream URL: "
<< m_cameraDetails.streamUrl
<< ", file writer being closed.");
<< m_cameraDetails.streamUrl << ", file writer being closed.");

m_videoWriter.release();
SetWritingStream(false);
Expand Down
66 changes: 33 additions & 33 deletions Source/IpFreelyMotionDetector.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include <string>
#include <memory>
#include <ctime>
#include <opencv/cv.hpp>
#include <opencv2/opencv.hpp>
#include "Threads/MessageQueueThread.h"
#include "IpFreelyCameraDatabase.h"

Expand Down Expand Up @@ -98,40 +98,40 @@ class IpFreelyMotionDetector final
bool CheckForIntersections();
void RotateFrames();
static int MessageDecoder(video_frame_t const& msg);
bool MessageHandler(video_frame_t& msg);
void CreateCaptureObjects();
void WriteVideoFrame();
void SetWritingStream(bool const writing) noexcept;
bool MessageHandler(video_frame_t& msg);
void CreateCaptureObjects();
void WriteVideoFrame();
void SetWritingStream(bool const writing) noexcept;

private:
mutable std::mutex m_motionMutex{};
mutable std::mutex m_writingMutex{};
mutable std::mutex m_fpsMutex{};
std::string m_name{"cam"};
IpCamera m_cameraDetails{};
std::string m_saveFolderPath{};
double m_requiredFileDurationSecs{0.0};
double m_fps{25.0};
int m_originalWidth{0};
int m_originalHeight{0};
unsigned int m_updatePeriodMillisecs{40};
cv::Mat m_erosionKernel{};
cv::Scalar m_rectangleColor{0, 255, 0};
video_frame_t m_originalFrame;
size_t m_holdOffFrameCountLimit{0};
size_t m_holdOffFrameCount{0};
double m_motionFrameScalar{1.0};
int m_minImageChangeArea{0};
size_t m_imageChangesThreshold{0};
bool m_initialiseFrames{true};
cv::Mat m_prevGreyFrame{};
cv::Mat m_currentGreyFrame{};
cv::Mat m_nextGreyFrame{};
cv::Rect m_motionBoundingRect{0, 0, 0, 0};
double m_fileDurationSecs{0.0};
time_t m_currentTime{};
cv::Ptr<cv::VideoWriter> m_videoWriter{};
bool m_writingStream{false};
mutable std::mutex m_motionMutex{};
mutable std::mutex m_writingMutex{};
mutable std::mutex m_fpsMutex{};
std::string m_name{"cam"};
IpCamera m_cameraDetails{};
std::string m_saveFolderPath{};
double m_requiredFileDurationSecs{0.0};
double m_fps{25.0};
int m_originalWidth{0};
int m_originalHeight{0};
unsigned int m_updatePeriodMillisecs{40};
cv::Mat m_erosionKernel{};
cv::Scalar m_rectangleColor{0, 255, 0};
video_frame_t m_originalFrame;
size_t m_holdOffFrameCountLimit{0};
size_t m_holdOffFrameCount{0};
double m_motionFrameScalar{1.0};
int m_minImageChangeArea{0};
size_t m_imageChangesThreshold{0};
bool m_initialiseFrames{true};
cv::Mat m_prevGreyFrame{};
cv::Mat m_currentGreyFrame{};
cv::Mat m_nextGreyFrame{};
cv::Rect m_motionBoundingRect{0, 0, 0, 0};
double m_fileDurationSecs{0.0};
time_t m_currentTime{};
cv::Ptr<cv::VideoWriter> m_videoWriter{};
bool m_writingStream{false};
core_lib::threads::MessageQueueThread<int, video_frame_t> m_msgQueueThread;
};

Expand Down
2 changes: 1 addition & 1 deletion Source/IpFreelyPreferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <sstream>
#include <fstream>
#include <utility>
#include <boost/throw_exception.hpp>
#include <boost/exception/all.hpp>
#include <boost/filesystem.hpp>
#include "Serialization/SerializeToVector.h"
#include "DebugLog/DebugLogging.h"
Expand Down
40 changes: 18 additions & 22 deletions Source/IpFreelyStreamProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "IpFreelyStreamProcessor.h"
#include <sstream>
#include <cmath>
#include <boost/throw_exception.hpp>
#include <boost/exception/all.hpp>
#include <boost/filesystem.hpp>
#include "IpFreelyMotionDetector.h"
#include "Threads/EventThread.h"
Expand Down Expand Up @@ -121,11 +121,11 @@ IpFreelyStreamProcessor::IpFreelyStreamProcessor(

CreateVideoCapture();

auto fps = m_videoCapture->get(CV_CAP_PROP_FPS);
auto fps = m_videoCapture->get(cv::CAP_PROP_FPS);
m_originalFps = fps;

DEBUG_MESSAGE_EX_INFO(
"Stream at: " << m_cameraDetails.streamUrl << ", stream FPS: " << m_originalFps);
DEBUG_MESSAGE_EX_INFO("Stream at: " << m_cameraDetails.streamUrl
<< ", stream FPS: " << m_originalFps);

if ((fps < MIN_FPS) || (fps > MAX_FPS))
{
Expand All @@ -139,10 +139,9 @@ IpFreelyStreamProcessor::IpFreelyStreamProcessor(
m_fps = fps;
m_updatePeriodMillisecs = static_cast<unsigned int>(1000.0 / m_fps);

DEBUG_MESSAGE_EX_INFO("Stream at: " << m_cameraDetails.streamUrl << " running with FPS of: "
<< m_fps
<< ", thread update period (ms): "
<< m_updatePeriodMillisecs);
DEBUG_MESSAGE_EX_INFO("Stream at: "
<< m_cameraDetails.streamUrl << " running with FPS of: " << m_fps
<< ", thread update period (ms): " << m_updatePeriodMillisecs);

DEBUG_MESSAGE_EX_INFO("Creating event thread for stream URL: " << m_cameraDetails.streamUrl);

Expand Down Expand Up @@ -396,8 +395,8 @@ void IpFreelyStreamProcessor::CreateCaptureObjects()

p /= oss.str();

DEBUG_MESSAGE_EX_INFO(
"Creating new output video file: " << p.string() << ", FPS: " << m_fps);
DEBUG_MESSAGE_EX_INFO("Creating new output video file: " << p.string()
<< ", FPS: " << m_fps);

#if BOOST_OS_WINDOWS
m_videoWriter = cv::makePtr<cv::VideoWriter>(p.string().c_str(),
Expand Down Expand Up @@ -520,21 +519,19 @@ void IpFreelyStreamProcessor::CreateVideoCapture()
BOOST_THROW_EXCEPTION(std::runtime_error(oss.str()));
}

m_videoWidth = static_cast<int>(m_videoCapture->get(CV_CAP_PROP_FRAME_WIDTH));
m_videoHeight = static_cast<int>(m_videoCapture->get(CV_CAP_PROP_FRAME_HEIGHT));
m_videoWidth = static_cast<int>(m_videoCapture->get(cv::CAP_PROP_FRAME_WIDTH));
m_videoHeight = static_cast<int>(m_videoCapture->get(cv::CAP_PROP_FRAME_HEIGHT));
}

void IpFreelyStreamProcessor::CheckFps()
{
auto fps = m_videoCapture->get(CV_CAP_PROP_FPS);
auto fps = m_videoCapture->get(cv::CAP_PROP_FPS);

if (std::abs(fps - m_originalFps) > 0.1)
{
DEBUG_MESSAGE_EX_WARNING("Detected change in FPS for stream: " << m_cameraDetails.streamUrl
<< ", changed from: "
<< m_originalFps
<< " to: "
<< fps);
DEBUG_MESSAGE_EX_WARNING("Detected change in FPS for stream: "
<< m_cameraDetails.streamUrl << ", changed from: " << m_originalFps
<< " to: " << fps);

m_originalFps = fps;

Expand All @@ -553,10 +550,9 @@ void IpFreelyStreamProcessor::CheckFps()
m_fps = fps;
m_updatePeriodMillisecs = static_cast<unsigned int>(1000.0 / m_fps);

DEBUG_MESSAGE_EX_INFO("Stream at: " << m_cameraDetails.streamUrl << " running with FPS of: "
<< m_fps
<< ", thread update period (ms): "
<< m_updatePeriodMillisecs);
DEBUG_MESSAGE_EX_INFO("Stream at: "
<< m_cameraDetails.streamUrl << " running with FPS of: " << m_fps
<< ", thread update period (ms): " << m_updatePeriodMillisecs);

if (m_videoWriter)
{
Expand Down
Loading

0 comments on commit fedf5bd

Please sign in to comment.