Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 9 additions & 1 deletion biotracker/BioTrackerApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@
#include <QKeyEvent>
#include <QMouseEvent>

#include "util/platform.h"
#include "TrackingThread.h"
#include "ImageStream.h"
#include "Registry.h"
#include "settings/Settings.h"
#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:
Expand All @@ -46,6 +48,12 @@ class 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 openMediumBySetting();

/**
* @throw boost::filesystem_error
* @brief openVideo opens a single video which type is supported by opencv and stores path in settings
Expand Down
5 changes: 3 additions & 2 deletions biotracker/Registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <QObject>

#include "util/platform.h"
#include "zmq/ZmqInfoFile.h"
#include "TrackingAlgorithm.h"
#include "util/stdext.h"
Expand All @@ -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<TrackingAlgorithm> operator()(Settings &settings) const = 0;
virtual ~NewTrackerFactory() {}
};

class Registry : public QObject, public Util::Singleton<Registry> {
class BIOTRACKER_DLLEXPORT Registry : public QObject, public Util::Singleton<Registry> {
Q_OBJECT
public:
typedef std::map<const TrackerType, std::shared_ptr<NewTrackerFactory>>
Expand Down
5 changes: 3 additions & 2 deletions biotracker/TrackingAlgorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <QPointer>
#include <QMouseEvent>

#include "util/platform.h"
#include "settings/Messages.h"
#include "settings/ParamNames.h"
#include "serialization/TrackedObject.h"
Expand Down Expand Up @@ -55,14 +56,14 @@ class ProxyMat {
boost::optional<cv::Mat> 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;
};

Expand Down
4 changes: 3 additions & 1 deletion biotracker/settings/SystemCompatibilityCheck.h
Original file line number Diff line number Diff line change
@@ -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();
}

4 changes: 4 additions & 0 deletions biotracker/src/BioTrackerApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ void BioTrackerApp::initConnects() {
this, &BioTrackerApp::trackerIsAlreadyLoadedFromRegistry);
}

void BioTrackerApp::openMediumBySetting() {
m_trackingThread.loadFromSettings();
}

void BioTrackerApp::openVideo(const boost::filesystem::path &path) {
m_trackingThread.loadVideo(path);
}
Expand Down
6 changes: 5 additions & 1 deletion biotracker/src/ImageStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ class ImageStreamPictures : public ImageStream {
public:
explicit ImageStreamPictures(std::vector<boost::filesystem::path> 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);
Expand Down Expand Up @@ -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) {
Expand Down
100 changes: 74 additions & 26 deletions biotracker/src/TrackingThread.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "TrackingThread.h"

#include <iostream>
#include <sstream>

#include <chrono>
#include <thread>
Expand All @@ -10,6 +11,7 @@
#include "settings/Messages.h"
#include "settings/Settings.h"
#include "settings/ParamNames.h"
#include "Exceptions.h"

#include <QCoreApplication>
#include <QtOpenGL/qgl.h>
Expand Down Expand Up @@ -40,33 +42,66 @@ TrackingThread::~TrackingThread(void) {
}

void TrackingThread::loadFromSettings() {
std::string filenameStr = m_settings.getValueOfParam<std::string>
(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;
} else {
playOnce();
}
// Determine which media type was used the last time
boost::optional<uint8_t> mediaTypeOpt = m_settings.maybeGetValueOfParam<uint8_t>(GuiParam::MEDIA_TYPE);
GuiParam::MediaType mediaType = mediaTypeOpt ? static_cast<GuiParam::MediaType>(*mediaTypeOpt) :
GuiParam::MediaType::NoMedia;

if (mediaType == GuiParam::MediaType::Video) {
boost::optional<std::string> filenameStr = m_settings.maybeGetValueOfParam<std::string>(CaptureParam::CAP_VIDEO_FILE);
// Abort, because filename string was not set (just to prevent manipulated config files)
if (!filenameStr) {
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(GuiParam::MediaType::NoMedia));
return;
}
boost::filesystem::path filename {*filenameStr};
try {
loadVideo(filename);
} catch (file_not_found &e) {
// Preventing segfault when video file vanished
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(GuiParam::MediaType::NoMedia));
Q_EMIT notifyGUI(e.what(), MessageType::FAIL);
}
} else if (mediaType == GuiParam::MediaType::Camera) {
boost::optional<int> camIdOpt = m_settings.maybeGetValueOfParam<int>(CaptureParam::CAP_CAMERA_ID);
int camId = camIdOpt ? *camIdOpt : -1;
try {
loadCamera(camId);
} catch (device_open_error e) {
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(GuiParam::MediaType::NoMedia));
Q_EMIT notifyGUI(e.what(), MessageType::FAIL);
}
} else if (mediaType == GuiParam::MediaType::Images) {
boost::optional<std::string> filenamesStrOpt = m_settings.maybeGetValueOfParam<std::string>
(PictureParam::PICTURE_FILES);

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;
if (!filenamesStrOpt) {
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(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<boost::filesystem::path> 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());
}
try {
loadPictures(std::move(filenames));
} catch (file_not_found e) {
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(GuiParam::MediaType::NoMedia));
Q_EMIT notifyGUI(e.what(), MessageType::FAIL);
}
} else {
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(GuiParam::MediaType::NoMedia));
}

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) {
Expand All @@ -78,6 +113,7 @@ void TrackingThread::loadVideo(const boost::filesystem::path &filename) {
m_status = TrackerStatus::Invalid;
return;
} else {
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(m_imageStream->type()));
playOnce();
}

Expand All @@ -97,13 +133,23 @@ void TrackingThread::loadVideo(const boost::filesystem::path &filename) {
}
}
Q_EMIT notifyGUI(note, MessageType::FILE_OPEN);
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(m_imageStream->type()));
}

void TrackingThread::loadPictures(std::vector<boost::filesystem::path>
&&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
Expand All @@ -116,9 +162,12 @@ void TrackingThread::loadPictures(std::vector<boost::filesystem::path>
m_status = TrackerStatus::Invalid;
return;
} else {
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(m_imageStream->type()));
playOnce();
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
Expand All @@ -128,7 +177,6 @@ void TrackingThread::loadPictures(std::vector<boost::filesystem::path>
}
}
}
m_settings.setParam<uint8_t>(GuiParam::MEDIA_TYPE, static_cast<uint8_t>(m_imageStream->type()));
}

void TrackingThread::loadCamera(int device) {
Expand Down
8 changes: 5 additions & 3 deletions biotracker/src/util/stringTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
#include <string> // std::string
#include <stdexcept> // 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
Expand All @@ -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()) {
Expand Down Expand Up @@ -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();
}
Expand Down
14 changes: 14 additions & 0 deletions biotracker/util/platform.h
Original file line number Diff line number Diff line change
@@ -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