From e3e8e469f5b11979abba8d889bef8b611f2b9cbd Mon Sep 17 00:00:00 2001 From: justayak Date: Thu, 21 Apr 2016 11:27:11 +0000 Subject: [PATCH 1/5] add reload of camera and video when biotracker is started --- biotracker/src/BioTrackerApp.cpp | 1 + biotracker/src/TrackingThread.cpp | 51 +++++++++++++++---------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/biotracker/src/BioTrackerApp.cpp b/biotracker/src/BioTrackerApp.cpp index f72b7e9d..76564db6 100644 --- a/biotracker/src/BioTrackerApp.cpp +++ b/biotracker/src/BioTrackerApp.cpp @@ -17,6 +17,7 @@ BioTrackerApp::BioTrackerApp() loadModulesInPath(ConfigParam::MODULE_PATH); m_trackingThread.start(); + m_trackingThread.loadFromSettings(); } BioTrackerApp::~BioTrackerApp() { diff --git a/biotracker/src/TrackingThread.cpp b/biotracker/src/TrackingThread.cpp index 70d288b9..ac63dbad 100644 --- a/biotracker/src/TrackingThread.cpp +++ b/biotracker/src/TrackingThread.cpp @@ -40,33 +40,31 @@ TrackingThread::~TrackingThread(void) { } void TrackingThread::loadFromSettings() { - std::string filenameStr = m_settings.getValueOfParam - (CaptureParam::CAP_VIDEO_FILE); - boost::filesystem::path filename {filenameStr}; - m_imageStream = make_ImageStreamVideo(filename); - if (m_imageStream->type() == GuiParam::MediaType::NoMedia) { - // could not open video - std::string errorMsg = "unable to open file " + filename.string(); - Q_EMIT notifyGUI(errorMsg, MessageType::FAIL); - m_status = TrackerStatus::Invalid; - return; + // Determine which media type was used the last time + boost::optional mediaTypeOpt = m_settings.maybeGetValueOfParam(GuiParam::MEDIA_TYPE); + GuiParam::MediaType mediaType = mediaTypeOpt ? static_cast(*mediaTypeOpt) : + GuiParam::MediaType::NoMedia; + + if (mediaType == GuiParam::MediaType::Video) { + boost::optional filenameStr = m_settings.maybeGetValueOfParam(CaptureParam::CAP_VIDEO_FILE); + // Abort, because filename string was not set (just to prevent manipulated config files) + if (!filenameStr) { + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); + return; + } + boost::filesystem::path filename {*filenameStr}; + loadVideo(filename); + } else if (mediaType == GuiParam::MediaType::Camera) { + boost::optional camIdOpt = m_settings.maybeGetValueOfParam(CaptureParam::CAP_CAMERA_ID); + int camId = camIdOpt ? *camIdOpt : -1; + loadCamera(camId); + } else if (mediaType == GuiParam::MediaType::Images) { + // Currently, image paths are not saved in settings + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); } else { - playOnce(); + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); } - m_fps = m_imageStream->fps(); - m_ignoreFilenameChanged = false; - Q_EMIT fileOpened(filenameStr, m_imageStream->numFrames(), m_fps); - if (m_tracker && m_somethingIsLoaded && - m_lastFilename.compare(filenameStr) != 0) { - m_tracker->inputChanged(); - m_tracker->onFileChanged(filenameStr); - m_lastFilename = filenameStr; - } - - std::string note = "opened file: " + filenameStr + " (#frames: " - + QString::number(m_imageStream->numFrames()).toStdString() + ")"; - Q_EMIT notifyGUI(note, MessageType::FILE_OPEN); } void TrackingThread::loadVideo(const boost::filesystem::path &filename) { @@ -78,6 +76,7 @@ void TrackingThread::loadVideo(const boost::filesystem::path &filename) { m_status = TrackerStatus::Invalid; return; } else { + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(m_imageStream->type())); playOnce(); } @@ -97,7 +96,6 @@ void TrackingThread::loadVideo(const boost::filesystem::path &filename) { } } Q_EMIT notifyGUI(note, MessageType::FILE_OPEN); - m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(m_imageStream->type())); } void TrackingThread::loadPictures(std::vector @@ -116,9 +114,11 @@ void TrackingThread::loadPictures(std::vector m_status = TrackerStatus::Invalid; return; } else { + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(m_imageStream->type())); playOnce(); Q_EMIT fileOpened(m_imageStream->currentFilename(), m_imageStream->numFrames(), m_fps); + if (m_tracker) { m_tracker->inputChanged(); if (m_somethingIsLoaded @@ -128,7 +128,6 @@ void TrackingThread::loadPictures(std::vector } } } - m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(m_imageStream->type())); } void TrackingThread::loadCamera(int device) { From 1ad208c05edbe405231be784185fdeabcca5faae Mon Sep 17 00:00:00 2001 From: David Dormagen Date: Thu, 21 Apr 2016 15:37:21 +0200 Subject: [PATCH 2/5] added macro to mark all symbols that are to be exported to a DLL (MSVC) This is necessary, because on windows the linker will optimize out all unused, unmarked symbols. Only symbols with declspec(dllexport) will survive in the DLL. And dllexport must only be set when actually building the DLL. When just using the headers, you'll need to leave it out (or use dllimport as an optimization). --- CMakeLists.txt | 2 ++ biotracker/BioTrackerApp.h | 4 +++- biotracker/Registry.h | 5 +++-- biotracker/TrackingAlgorithm.h | 5 +++-- biotracker/settings/SystemCompatibilityCheck.h | 4 +++- biotracker/src/util/stringTools.cpp | 8 +++++--- biotracker/util/platform.h | 14 ++++++++++++++ 7 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 biotracker/util/platform.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 536e64b6..13b9c751 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,8 @@ CPM_ExportAdditionalDefinition(-DQT_NO_KEYWORDS) # Disable warnings add_definitions(-D_SCL_SECURE_NO_WARNINGS) +# Specify that we want to export symbols to a DLL (as opposed to importing them from a DLL). +add_definitions(-DBUILD_BIOTRACKER_DLL) # include external dependecies as SYSTEM headers to prevent warnings from # external files. unfortunately, this has no effect when using MSVC. diff --git a/biotracker/BioTrackerApp.h b/biotracker/BioTrackerApp.h index e76cec80..1e66742d 100644 --- a/biotracker/BioTrackerApp.h +++ b/biotracker/BioTrackerApp.h @@ -9,6 +9,7 @@ #include #include +#include "util/platform.h" #include "TrackingThread.h" #include "ImageStream.h" #include "Registry.h" @@ -16,11 +17,12 @@ #include "TrackerStatus.h" #include "PanZoomState.h" + namespace BioTracker { namespace Core { /* Used to be Facade */ -class BioTrackerApp : public QObject { +class BIOTRACKER_DLLEXPORT BioTrackerApp : public QObject { public: Q_OBJECT public: diff --git a/biotracker/Registry.h b/biotracker/Registry.h index 55b41996..19543e91 100644 --- a/biotracker/Registry.h +++ b/biotracker/Registry.h @@ -6,6 +6,7 @@ #include +#include "util/platform.h" #include "zmq/ZmqInfoFile.h" #include "TrackingAlgorithm.h" #include "util/stdext.h" @@ -22,12 +23,12 @@ static const TrackerType NoTracking = 0; // construct on first use idiom TrackerType getNextId(); -struct NewTrackerFactory { +struct BIOTRACKER_DLLEXPORT NewTrackerFactory { virtual std::shared_ptr operator()(Settings &settings) const = 0; virtual ~NewTrackerFactory() {} }; -class Registry : public QObject, public Util::Singleton { +class BIOTRACKER_DLLEXPORT Registry : public QObject, public Util::Singleton { Q_OBJECT public: typedef std::map> diff --git a/biotracker/TrackingAlgorithm.h b/biotracker/TrackingAlgorithm.h index b5f9a7d9..8e7a575c 100644 --- a/biotracker/TrackingAlgorithm.h +++ b/biotracker/TrackingAlgorithm.h @@ -12,6 +12,7 @@ #include #include +#include "util/platform.h" #include "settings/Messages.h" #include "settings/ParamNames.h" #include "serialization/TrackedObject.h" @@ -55,14 +56,14 @@ class ProxyMat { boost::optional m_modifiedMat; }; -class TrackingAlgorithm : public QObject { +class BIOTRACKER_DLLEXPORT TrackingAlgorithm : public QObject { Q_OBJECT public: TrackingAlgorithm(Settings &settings); virtual ~TrackingAlgorithm() override; - struct View { + struct BIOTRACKER_DLLEXPORT View { std::string name; }; diff --git a/biotracker/settings/SystemCompatibilityCheck.h b/biotracker/settings/SystemCompatibilityCheck.h index 06dc13f1..829f1af1 100644 --- a/biotracker/settings/SystemCompatibilityCheck.h +++ b/biotracker/settings/SystemCompatibilityCheck.h @@ -1,10 +1,12 @@ #pragma once +#include "util/platform.h" + namespace SystemCompatibilityCheck { /** * Check the system supports openGL. * @return true, system supports openGL, false otherwise. */ -bool checkOpenGLSupport(); +bool BIOTRACKER_DLLEXPORT checkOpenGLSupport(); } diff --git a/biotracker/src/util/stringTools.cpp b/biotracker/src/util/stringTools.cpp index 5055469b..711a8e80 100644 --- a/biotracker/src/util/stringTools.cpp +++ b/biotracker/src/util/stringTools.cpp @@ -4,10 +4,12 @@ #include // std::string #include // std::invalid_argument +#include "util/platform.h" + namespace BioTracker { namespace Util { -std::string escape_non_ascii(const std::string &s) { +std::string BIOTRACKER_DLLEXPORT escape_non_ascii(const std::string &s) { std::string result; for (const auto c : s) { // MSB is set --> not a valid ASCII character --> escape @@ -29,7 +31,7 @@ std::string escape_non_ascii(const std::string &s) { } -std::string unescape_non_ascii(const std::string &s) { +std::string BIOTRACKER_DLLEXPORT unescape_non_ascii(const std::string &s) { const auto advance = [&s](std::string::const_iterator &it) { if (++it == s.cend()) { @@ -78,7 +80,7 @@ std::string unescape_non_ascii(const std::string &s) { return result; } -std::string stem_filename(const std::string &s) { +std::string BIOTRACKER_DLLEXPORT stem_filename(const std::string &s) { boost::filesystem::path p(s); return p.stem().string(); } diff --git a/biotracker/util/platform.h b/biotracker/util/platform.h new file mode 100644 index 00000000..f7ff04c2 --- /dev/null +++ b/biotracker/util/platform.h @@ -0,0 +1,14 @@ +#pragma once + +/* +This macro must be used to mark all symbols that should be exported to a DLL. +*/ +#ifdef _MSC_VER +#ifdef BUILD_BIOTRACKER_DLL +#define BIOTRACKER_DLLEXPORT __declspec(dllexport) +#else +#define BIOTRACKER_DLLEXPORT __declspec(dllimport) +#endif +#else +#define BIOTRACKER_DLLEXPORT +#endif From 3ba72780cbe2e69804f13cd3a1946cefea47fe11 Mon Sep 17 00:00:00 2001 From: Amjad Saadeh Date: Thu, 21 Apr 2016 12:12:18 +0000 Subject: [PATCH 3/5] fix wrong number of frames in GUI --- biotracker/BioTrackerApp.h | 6 ++++++ biotracker/src/BioTrackerApp.cpp | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/biotracker/BioTrackerApp.h b/biotracker/BioTrackerApp.h index 1e66742d..1562f85e 100644 --- a/biotracker/BioTrackerApp.h +++ b/biotracker/BioTrackerApp.h @@ -48,6 +48,12 @@ class BIOTRACKER_DLLEXPORT BioTrackerApp : public QObject { return m_trackingThread.getStatus(); } + /** + * @throw boost::filesystem_error + * @brief openMediaBySetting opens a medium (camera, images or video) which has been storen in the settings + */ + void openMedumBySetting(); + /** * @throw boost::filesystem_error * @brief openVideo opens a single video which type is supported by opencv and stores path in settings diff --git a/biotracker/src/BioTrackerApp.cpp b/biotracker/src/BioTrackerApp.cpp index 76564db6..acc83750 100644 --- a/biotracker/src/BioTrackerApp.cpp +++ b/biotracker/src/BioTrackerApp.cpp @@ -17,7 +17,6 @@ BioTrackerApp::BioTrackerApp() loadModulesInPath(ConfigParam::MODULE_PATH); m_trackingThread.start(); - m_trackingThread.loadFromSettings(); } BioTrackerApp::~BioTrackerApp() { @@ -43,6 +42,10 @@ void BioTrackerApp::initConnects() { this, &BioTrackerApp::trackerIsAlreadyLoadedFromRegistry); } +void BioTrackerApp::openMedumBySetting() { + m_trackingThread.loadFromSettings(); +} + void BioTrackerApp::openVideo(const boost::filesystem::path &path) { m_trackingThread.loadVideo(path); } From 4cf8b7125d5c544e38dfd59c2d3f7dfd253b179f Mon Sep 17 00:00:00 2001 From: Amjad Saadeh Date: Sun, 24 Apr 2016 10:20:44 +0000 Subject: [PATCH 4/5] add loading of last opened pictures on start --- biotracker/src/TrackingThread.cpp | 36 +++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/biotracker/src/TrackingThread.cpp b/biotracker/src/TrackingThread.cpp index ac63dbad..48d9cba4 100644 --- a/biotracker/src/TrackingThread.cpp +++ b/biotracker/src/TrackingThread.cpp @@ -1,6 +1,7 @@ #include "TrackingThread.h" #include +#include #include #include @@ -59,8 +60,27 @@ void TrackingThread::loadFromSettings() { int camId = camIdOpt ? *camIdOpt : -1; loadCamera(camId); } else if (mediaType == GuiParam::MediaType::Images) { - // Currently, image paths are not saved in settings - m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); + boost::optional filenamesStrOpt = m_settings.maybeGetValueOfParam + (PictureParam::PICTURE_FILES); + + if (!filenamesStrOpt) { + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); + return; + } + std::string filenamesStr = *filenamesStrOpt; + + // Split string of paths into a vector a paths + // source: http://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c + std::vector filenames; + std::string delimiter = ";"; + size_t pos = 0; + std::string token; + while ((pos = filenamesStr.find(delimiter)) != std::string::npos) { + token = filenamesStr.substr(0, pos); + filenames.push_back(boost::filesystem::path(token)); + filenamesStr.erase(0, pos + delimiter.length()); + } + loadPictures(std::move(filenames)); } else { m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); } @@ -102,6 +122,17 @@ void TrackingThread::loadPictures(std::vector &&filenames) { m_fps = 1; m_ignoreFilenameChanged = false; + + // Convert filenames into one string for settings. This is done here, because move may clear the vector with filenames. + std::stringstream filenamesStr; + if (!filenames.empty()) { + filenamesStr << filenames[0].string(); + for (uint32_t i = 1; i < filenames.size(); i++) { + filenamesStr << ';'; + filenamesStr << filenames[i].string(); + } + } + m_imageStream = make_ImageStreamPictures(std::move(filenames)); if (m_imageStream->type() == GuiParam::MediaType::NoMedia) { // could not open video @@ -119,6 +150,7 @@ void TrackingThread::loadPictures(std::vector Q_EMIT fileOpened(m_imageStream->currentFilename(), m_imageStream->numFrames(), m_fps); + m_settings.setParam(PictureParam::PICTURE_FILES, filenamesStr.str()); if (m_tracker) { m_tracker->inputChanged(); if (m_somethingIsLoaded From 5420d27857ef01e3568f2afbc00b41ee8193227c Mon Sep 17 00:00:00 2001 From: Amjad Saadeh Date: Sun, 24 Apr 2016 11:57:13 +0000 Subject: [PATCH 5/5] fix errors when previously loaded files are not present anymore --- biotracker/BioTrackerApp.h | 2 +- biotracker/src/BioTrackerApp.cpp | 2 +- biotracker/src/ImageStream.cpp | 6 +++++- biotracker/src/TrackingThread.cpp | 23 ++++++++++++++++++++--- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/biotracker/BioTrackerApp.h b/biotracker/BioTrackerApp.h index 1562f85e..e3a58f01 100644 --- a/biotracker/BioTrackerApp.h +++ b/biotracker/BioTrackerApp.h @@ -52,7 +52,7 @@ class BIOTRACKER_DLLEXPORT BioTrackerApp : public QObject { * @throw boost::filesystem_error * @brief openMediaBySetting opens a medium (camera, images or video) which has been storen in the settings */ - void openMedumBySetting(); + void openMediumBySetting(); /** * @throw boost::filesystem_error diff --git a/biotracker/src/BioTrackerApp.cpp b/biotracker/src/BioTrackerApp.cpp index acc83750..7c698431 100644 --- a/biotracker/src/BioTrackerApp.cpp +++ b/biotracker/src/BioTrackerApp.cpp @@ -42,7 +42,7 @@ void BioTrackerApp::initConnects() { this, &BioTrackerApp::trackerIsAlreadyLoadedFromRegistry); } -void BioTrackerApp::openMedumBySetting() { +void BioTrackerApp::openMediumBySetting() { m_trackingThread.loadFromSettings(); } diff --git a/biotracker/src/ImageStream.cpp b/biotracker/src/ImageStream.cpp index 6fa1cb31..a6a08d1c 100644 --- a/biotracker/src/ImageStream.cpp +++ b/biotracker/src/ImageStream.cpp @@ -134,6 +134,10 @@ class ImageStreamPictures : public ImageStream { public: explicit ImageStreamPictures(std::vector picture_files) : m_picture_files(std::move(picture_files)) { + if (m_picture_files.empty()) { + throw file_not_found("Could not find any picture files"); + } + // load first image if (this->numFrames() > 0) { this->setFrameNumber_impl(0); @@ -244,7 +248,7 @@ class ImageStreamCamera : public ImageStream { : m_capture(device_id) , m_fps(m_capture.get(CV_CAP_PROP_FPS)) { if (! m_capture.isOpened()) { - throw device_open_error(":("); + throw device_open_error("Could not open camera " + std::to_string(device_id)); } // load first image if (this->numFrames() > 0) { diff --git a/biotracker/src/TrackingThread.cpp b/biotracker/src/TrackingThread.cpp index 48d9cba4..7e984238 100644 --- a/biotracker/src/TrackingThread.cpp +++ b/biotracker/src/TrackingThread.cpp @@ -11,6 +11,7 @@ #include "settings/Messages.h" #include "settings/Settings.h" #include "settings/ParamNames.h" +#include "Exceptions.h" #include #include @@ -54,11 +55,22 @@ void TrackingThread::loadFromSettings() { return; } boost::filesystem::path filename {*filenameStr}; - loadVideo(filename); + try { + loadVideo(filename); + } catch (file_not_found &e) { + // Preventing segfault when video file vanished + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); + Q_EMIT notifyGUI(e.what(), MessageType::FAIL); + } } else if (mediaType == GuiParam::MediaType::Camera) { boost::optional camIdOpt = m_settings.maybeGetValueOfParam(CaptureParam::CAP_CAMERA_ID); int camId = camIdOpt ? *camIdOpt : -1; - loadCamera(camId); + try { + loadCamera(camId); + } catch (device_open_error e) { + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); + Q_EMIT notifyGUI(e.what(), MessageType::FAIL); + } } else if (mediaType == GuiParam::MediaType::Images) { boost::optional filenamesStrOpt = m_settings.maybeGetValueOfParam (PictureParam::PICTURE_FILES); @@ -80,7 +92,12 @@ void TrackingThread::loadFromSettings() { filenames.push_back(boost::filesystem::path(token)); filenamesStr.erase(0, pos + delimiter.length()); } - loadPictures(std::move(filenames)); + try { + loadPictures(std::move(filenames)); + } catch (file_not_found e) { + m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); + Q_EMIT notifyGUI(e.what(), MessageType::FAIL); + } } else { m_settings.setParam(GuiParam::MEDIA_TYPE, static_cast(GuiParam::MediaType::NoMedia)); }