...
 
Commits (54)
VERSION = 1.2
QMAKE_TARGET_COMPANY = "University of Tuebingen"
QMAKE_TARGET_PRODUCT = "EyeRecToo"
QMAKE_TARGET_DESCRIPTION = ""
QMAKE_TARGET_COPYRIGHT = "Thiago Santini"
QT += core gui multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++14
TOP = $$PWD
TARGET = EyeRecToo
......@@ -12,6 +20,7 @@ win32: RC_ICONS = $${TOP}/icons/eyerectoo.ico
#TEMPLATE = vcapp
DEFINES += TURBOJPEG
TURBOJPEGPATH="$${TOP}/deps/libjpeg-turbo-1.5.90/"
# Note: Starburst and Swirski are not currently included in the repository; do not enable
#DEFINES += STARBURST
......@@ -44,7 +53,10 @@ SOURCES +=\
$${TOP}/src/pupil-detection/PupilDetectionMethod.cpp \
$${TOP}/src/Overlay.cpp \
$${TOP}/src/CommandManager.cpp \
$${TOP}/src/ERWidget.cpp
$${TOP}/src/ERWidget.cpp \
$${TOP}/src/pupil-tracking/PuReST.cpp \
$${TOP}/src/pupil-detection/PuRe.cpp \
$${TOP}/src/pupil-tracking/PupilTrackingMethod.cpp
HEADERS += \
$${TOP}/src/MainWindow.h\
......@@ -74,14 +86,17 @@ HEADERS += \
$${TOP}/src/CameraCalibration.h \
$${TOP}/src/Overlay.h \
$${TOP}/src/CommandManager.h \
$${TOP}/src/ERWidget.h
$${TOP}/src/ERWidget.h \
$${TOP}/src/pupil-tracking/PupilTrackingMethod.h \
$${TOP}/src/pupil-detection/PuRe.h \
$${TOP}/src/pupil-tracking/PuReST.h
FORMS += \
$${TOP}/src/MainWindow.ui \
$${TOP}/src/CameraWidget.ui \
$${TOP}/src/GazeEstimationWidget.ui \
$${TOP}/src/LogWidget.ui \
$${TOP}/src/PerformanceMonitorWidget.ui
$${TOP}/src/PerformanceMonitorWidget.ui
RESOURCES += \
$${TOP}/resources.qrc
......@@ -111,15 +126,16 @@ LIBS += \
-lopencv_imgcodecs$${CV_SUFFIX} \
-lopencv_imgproc$${CV_SUFFIX} \
-lopencv_videoio$${CV_SUFFIX} \
-lopencv_aruco$${CV_SUFFIX}
-lopencv_video$${CV_SUFFIX} \
-lopencv_aruco$${CV_SUFFIX}
# JPEG-TURBO
contains(DEFINES, TURBOJPEG) {
INCLUDEPATH += "$${TOP}/deps/libjpeg-turbo-1.5.1/libjpeg-turbo64/include/"
INCLUDEPATH += "$${TURBOJPEGPATH}/include/"
win32:contains(QMAKE_HOST.arch, x86_64) {
LIBS += "-L$${TOP}/deps/libjpeg-turbo-1.5.1/libjpeg-turbo64/lib/"
LIBS += "-L$${TURBOJPEGPATH}/lib/"
} else {
LIBS += "-L$${TOP}/deps/libjpeg-turbo-1.5.1/libjpeg-turbo32/lib/"
LIBS += "-L$${TURBOJPEGPATH}/lib/"
}
LIBS += -lturbojpeg
}
......@@ -166,8 +182,12 @@ unix{
}
system("git --version"):{
GIT_VERSION=$$system(git --git-dir $${TOP}/../.git --work-tree $$TOP describe --always --tags)
DEFINES += GIT_VERSION=\\\"$$GIT_VERSION\\\"
GIT_BRANCH=$$system(git rev-parse --abbrev-ref HEAD)
GIT_COMMIT_HASH=$$system(git rev-parse --short HEAD)
} else {
GIT_VERSION=""
GIT_BRANCH="unknown"
GIT_COMMIT_HASH="unknown"
}
DEFINES += VERSION=\\\"$$VERSION\\\"
DEFINES += GIT_BRANCH=\\\"$$GIT_BRANCH\\\"
DEFINES += GIT_COMMIT_HASH=\\\"$$GIT_COMMIT_HASH\\\"
/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
/* see jconfig.txt for explanations */
#define JPEG_LIB_VERSION 62
#define LIBJPEG_TURBO_VERSION 1.5.90
#define LIBJPEG_TURBO_VERSION_NUMBER 1005090
#define JPEG_LIB_VERSION 62
#define LIBJPEG_TURBO_VERSION 1.5.1
#define LIBJPEG_TURBO_VERSION_NUMBER 1005001
#define C_ARITH_CODING_SUPPORTED
#define D_ARITH_CODING_SUPPORTED
#define MEM_SRCDST_SUPPORTED
/*
* Define BITS_IN_JSAMPLE as either
* 8 for 8-bit sample values (the usual setting)
* 12 for 12-bit sample values
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
* JPEG standard, and the IJG code does not support anything else!
* We do not support run-time selection of data precision, sorry.
*/
#define WITH_SIMD
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef __CHAR_UNSIGNED__
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
#undef NEED_BSD_STRINGS
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
#undef INCOMPLETE_TYPES_BROKEN
#undef RIGHT_SHIFT_IS_UNSIGNED
#undef __CHAR_UNSIGNED__
/* Define "boolean" as unsigned char, not int, per Windows custom */
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
typedef unsigned char boolean;
#endif
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
/* Define "INT32" as int, not long, per Windows custom */
#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */
......@@ -43,9 +32,3 @@ typedef short INT16;
typedef signed int INT32;
#endif
#define XMD_H /* prevent jmorecfg.h from redefining it */
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#endif /* JPEG_INTERNALS */
......@@ -5,7 +5,7 @@
* Copyright (C) 1994-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2014, D. R. Commander.
* Copyright (C) 2014, 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
......@@ -28,7 +28,7 @@
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
#define JMESSAGE(code,string)
#define JMESSAGE(code, string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
......@@ -36,7 +36,7 @@
typedef enum {
#define JMESSAGE(code,string) code ,
#define JMESSAGE(code, string) code,
#endif /* JMAKE_ENUM_LIST */
......@@ -44,8 +44,7 @@ JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
/* For maintenance convenience, list is alphabetical by message code name */
#if JPEG_LIB_VERSION < 70
JMESSAGE(JERR_ARITH_NOTIMPL,
"Sorry, arithmetic coding is not implemented")
JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented")
#endif
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
......@@ -154,8 +153,7 @@ JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
JMESSAGE(JTRC_JFIF_EXTENSION,
"JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
......@@ -208,6 +206,7 @@ JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
#endif
#endif
JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
#ifdef JMAKE_ENUM_LIST
......@@ -228,90 +227,90 @@ JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
#define ERREXIT(cinfo,code) \
#define ERREXIT(cinfo, code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT1(cinfo,code,p1) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT2(cinfo,code,p1,p2) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT3(cinfo,code,p1,p2,p3) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT3(cinfo, code, p1, p2, p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXITS(cinfo,code,str) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXITS(cinfo, code, str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
#define WARNMS(cinfo,code) \
#define WARNMS(cinfo, code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS1(cinfo,code,p1) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
#define WARNMS1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS2(cinfo,code,p1,p2) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
#define WARNMS2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
/* Informational/debugging messages */
#define TRACEMS(cinfo,lvl,code) \
#define TRACEMS(cinfo, lvl, code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS1(cinfo,lvl,code,p1) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#define TRACEMS1(cinfo, lvl, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#define TRACEMS2(cinfo, lvl, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMSS(cinfo,lvl,code,str) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMSS(cinfo, lvl, code, str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#endif /* JERROR_H */
......@@ -49,15 +49,15 @@
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#define GETJSAMPLE(value) ((int)(value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef __CHAR_UNSIGNED__
#define GETJSAMPLE(value) ((int) (value))
#define GETJSAMPLE(value) ((int)(value))
#else
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
#define GETJSAMPLE(value) ((int)(value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
......@@ -74,7 +74,7 @@ typedef char JSAMPLE;
*/
typedef short JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#define GETJSAMPLE(value) ((int)(value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
......@@ -173,9 +173,9 @@ typedef short INT16;
*/
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
#ifndef _BASETSD_H /* MinGW is slightly different */
#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
#ifndef _BASETSD_H /* MinGW is slightly different */
#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
typedef long INT32;
#endif
#endif
......@@ -220,7 +220,7 @@ typedef unsigned int JDIMENSION;
* software out there that uses it.
*/
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
#define JMETHOD(type, methodname, arglist) type (*methodname) arglist
/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS),
......@@ -333,37 +333,37 @@ typedef int boolean;
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
#define JPEG_NUMCS 17
#define JPEG_NUMCS 17
#define EXT_RGB_RED 0
#define EXT_RGB_GREEN 1
#define EXT_RGB_BLUE 2
#define EXT_RGB_PIXELSIZE 3
#define EXT_RGB_RED 0
#define EXT_RGB_GREEN 1
#define EXT_RGB_BLUE 2
#define EXT_RGB_PIXELSIZE 3
#define EXT_RGBX_RED 0
#define EXT_RGBX_GREEN 1
#define EXT_RGBX_BLUE 2
#define EXT_RGBX_PIXELSIZE 4
#define EXT_RGBX_RED 0
#define EXT_RGBX_GREEN 1
#define EXT_RGBX_BLUE 2
#define EXT_RGBX_PIXELSIZE 4
#define EXT_BGR_RED 2
#define EXT_BGR_GREEN 1
#define EXT_BGR_BLUE 0
#define EXT_BGR_PIXELSIZE 3
#define EXT_BGR_RED 2
#define EXT_BGR_GREEN 1
#define EXT_BGR_BLUE 0
#define EXT_BGR_PIXELSIZE 3
#define EXT_BGRX_RED 2
#define EXT_BGRX_GREEN 1
#define EXT_BGRX_BLUE 0
#define EXT_BGRX_PIXELSIZE 4
#define EXT_BGRX_RED 2
#define EXT_BGRX_GREEN 1
#define EXT_BGRX_BLUE 0
#define EXT_BGRX_PIXELSIZE 4
#define EXT_XBGR_RED 3
#define EXT_XBGR_GREEN 2
#define EXT_XBGR_BLUE 1
#define EXT_XBGR_PIXELSIZE 4
#define EXT_XBGR_RED 3
#define EXT_XBGR_GREEN 2
#define EXT_XBGR_BLUE 1
#define EXT_XBGR_PIXELSIZE 4
#define EXT_XRGB_RED 1
#define EXT_XRGB_GREEN 2
#define EXT_XRGB_BLUE 3
#define EXT_XRGB_PIXELSIZE 4
#define EXT_XRGB_RED 1
#define EXT_XRGB_GREEN 2
#define EXT_XRGB_BLUE 3
#define EXT_XRGB_PIXELSIZE 4
static const int rgb_red[JPEG_NUMCS] = {
-1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED,
......@@ -404,7 +404,7 @@ static const int rgb_pixelsize[JPEG_NUMCS] = {
#ifndef WITH_SIMD
#define MULTIPLIER int /* type for fastest integer multiply */
#else
#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
#endif
#endif
......
This diff is collapsed.
......@@ -12,11 +12,16 @@
#include <QComboBox>
#include <QLabel>
#include <QGridLayout>
#include <QRegularExpression>
#include <QFormLayout>
#include <QDoubleSpinBox>
#include <QFileInfo>
#include "opencv/cv.h"
#include "FrameGrabber.h"
class CameraUI : public QDialog
{
Q_OBJECT
......@@ -30,7 +35,8 @@ public:
QGridLayout *layout = new QGridLayout();
QHBoxLayout *hBoxLayout;
QGroupBox *box;
QFormLayout *formLayout;
QGroupBox *box;
devicesBox = new QComboBox();
hBoxLayout = new QHBoxLayout();
......@@ -53,7 +59,40 @@ public:
box = new QGroupBox("Color:");
box->setLayout(hBoxLayout);
hBoxLayout->addWidget(colorBox);
layout->addWidget(box);
layout->addWidget(box);
// Sliders are prettier and easier, but spinboxes are more accurate; unfortunatelly, that's what we favor.
bool useSliders = false;
QComboBox *parBox;
box = new QGroupBox("Parameters:");
box->setWhatsThis("Set camera parameters mode or values as % of their range.\nCurrently, no test is performed to check if the camera actually supports changing the parameter.");
box->setToolTip(box->whatsThis());
formLayout = new QFormLayout();
QStringList list = {
"Brightness",
"Contrast",
"White Balance",
"Saturation",
"Sharpening Level",
//"Gamma",
//"Gain",
//"Backlight",
"Exposure Time",
};
for (auto i = list.begin(); i != list.end(); i++) {
if (useSliders)
addSlider(formLayout, *i);
else
addSpinBox(formLayout, *i);
}
parBox = addComboBox(formLayout, "Exposure Mode");
parBox->addItem("Manual", 1);
parBox->addItem("Auto", 2);
//parBox->addItem("Shutter", 4);
//parBox->addItem("Aperture", 8);
box->setLayout(formLayout);
layout->addWidget(box, 0, 1, 3, 1);
setLayout(layout);
connect(devicesBox, SIGNAL(currentIndexChanged(int)),
......@@ -62,7 +101,29 @@ public:
this, SLOT(settingsChanged(int)) );
connect(colorBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(colorChanged(int)) );
}
}
void setValue(QDoubleSpinBox *sb, double val) {
if (!sb)
return;
sb->blockSignals(true);
sb->setValue(100*val);
sb->blockSignals(false);
}
void setValue(QSlider *s, double val) {
if (!s)
return;
s->blockSignals(true);
s->setValue(100*val);
s->blockSignals(false);
}
void setValue(QComboBox *cb, QVariant val) {
if (!cb)
return;
cb->blockSignals(true);
cb->setCurrentIndex(cb->findData(val));
cb->blockSignals(false);
}
public slots:
void update(QCameraInfo current, int colorCode)
......@@ -116,17 +177,60 @@ public slots:
signals:
void setCamera(QCameraInfo cameraInfo);
void setViewfinderSettings(QCameraViewfinderSettings settings);
void setColorCode(int code);
void setColorCode(int code);
void setParameter(QString what, float value);
private slots:
void deviceChanged(int i) { emit setCamera(devicesBox->itemData(i).value<QCameraInfo>());}
void settingsChanged(int i) { emit setViewfinderSettings(settingsBox->itemData(i).value<QCameraViewfinderSettings>());}
void colorChanged(int i) { emit setColorCode(colorBox->itemData(i).value<int>()); }
void colorChanged(int i) { emit setColorCode(colorBox->itemData(i).value<int>()); }
void sliderReleased() {
QSlider *slider = static_cast<QSlider*>( QObject::sender() );
emit setParameter(slider->objectName(), slider->value() / 100.0);
}
void spinBoxChanged(double value) {
QDoubleSpinBox *sb = static_cast<QDoubleSpinBox*>( QObject::sender() );
emit setParameter(sb->objectName(), value/ 100.0);
}
void comboBoxChanged() {
QComboBox *box = static_cast<QComboBox*>( QObject::sender() );
emit setParameter(box->objectName(), box->currentData().toFloat());
}
private:
QComboBox *devicesBox;
QComboBox *settingsBox;
QComboBox *colorBox;
void addSlider(QFormLayout *formLayout, QString label ) {
QSlider *slider = new QSlider( Qt::Horizontal );
slider->setMinimum(0);
slider->setMaximum(100);
slider->setSingleStep(1);
slider->setObjectName(label.toLower().replace(" ", "_"));
formLayout->addRow(new QLabel(label), slider);
connect(slider, SIGNAL(sliderReleased()), this, SLOT(sliderReleased()) );
}
void addSpinBox(QFormLayout *formLayout, QString label ) {
QDoubleSpinBox *sb = new QDoubleSpinBox();
sb->setMinimum(0);
sb->setMaximum(100);
sb->setSingleStep(0.5);
sb->setDecimals(1);
sb->setObjectName(label.toLower().replace(" ", "_"));
sb->setSuffix("%");
formLayout->addRow(new QLabel(label), sb);
connect(sb, SIGNAL(valueChanged(double)), this, SLOT(spinBoxChanged(double)) );
}
QComboBox* addComboBox(QFormLayout *formLayout, QString label ) {
QComboBox *box = new QComboBox();
box->setObjectName(label.toLower().replace(" ", "_"));
formLayout->addRow(new QLabel(label), box);
connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxChanged()) );
return box;
}
};
class Camera : public QObject
......@@ -150,12 +254,14 @@ public slots:
void setViewfinderSettings(QCameraViewfinderSettings settings);
void setCamera(const QCameraInfo &cameraInfo);
void setCamera(const QCameraInfo &cameraInfo, QCameraViewfinderSettings settings);
void setColorCode(int code);
void showOptions();
void setColorCode(int code);
void setParameter(QString what, float value);
void setValuesUI();
void showOptions();
void saveCfg();
void loadCfg();
void timedout();
void retry();
void retry();
private:
QString id;
......@@ -170,14 +276,49 @@ private:
int retriesLeft;
int maxRetries;
static QMutex setCameraMutex;
static QMutex setCameraMutex;
void searchDefaultCamera();
bool isAvailable(const QCameraInfo &cameraInfo) {
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
for (auto c = cameras.begin(); c != cameras.end(); c++) {
if (c->description() == cameraInfo.description() && c->deviceName() == cameraInfo.deviceName())
return true;
}
return false;
}
QString makeSettingsFileName() { return QString("%1/cfg/camera-parameters/%2.ini").arg(QCoreApplication::applicationDirPath()).arg(currentCameraInfo.deviceName()); }
bool loadCameraParameter(const QSettings &settings, const QString &parameter, double &value)
{
if ( ! settings.contains(parameter) )
return false;
value = settings.value(parameter).toDouble();
return true;
}
bool loadCameraParameter(const QString &parameter, double &value)
{
QFileInfo cameraSettingsFile( makeSettingsFileName() );
if ( ! cameraSettingsFile.exists() )
return false;
QSettings settings(cameraSettingsFile.absoluteFilePath(), QSettings::IniFormat);
return loadCameraParameter(settings, parameter, value);
}
void saveCameraParameter(const QString &parameter, const double &value)
{
QFileInfo cameraSettingsFile( makeSettingsFileName() );
QSettings s(cameraSettingsFile.absoluteFilePath(), QSettings::IniFormat);
s.setValue(parameter, value);
}
void loadAndSet(const QSettings &settings, QString key) {
double value;
if ( loadCameraParameter(settings, key, value) )
setParameter(key, value);
}
void loadUserCameraParameters();
private slots:
void reset();
void reset();
};
Q_DECLARE_METATYPE(cv::Mat)
Q_DECLARE_METATYPE(QCameraInfo)
Q_DECLARE_METATYPE(Timestamp)
#endif // CAMERA_H
......@@ -47,6 +47,7 @@ void CameraCalibration::startCalibration()
void CameraCalibration::finishCalibration()
{
calibrated = false;
QFuture<void> future = QtConcurrent::run(this, &CameraCalibration::calibrate);
watcher.setFuture(future);
}
......@@ -54,12 +55,12 @@ void CameraCalibration::finishCalibration()
void CameraCalibration::onCalibrated()
{
this->layout()->setEnabled(true);
updateCalibrationStatus( calibrationSuccessful );
updateCalibrationStatus( calibrated );
calibrationTogglePB->setText("Start");
calibrationTogglePB->setEnabled(true);
undistortPB->setEnabled(true);
settingsGB->setEnabled(true);
emit calibrationFinished( calibrationSuccessful );
emit calibrationFinished( calibrated );
}
void CameraCalibration::updateCalibrationStatus(bool success)
......@@ -121,15 +122,13 @@ void CameraCalibration::newSample(const Mat &frame)
undistortSample(frame);
}
void CameraCalibration::undistortSample(const Mat &frame)
{
if (undistortPB->isEnabled())
return;
Mat tmp;
if (fishEyeCB->isChecked())
remap(frame, tmp, map1, map2, CV_INTER_AREA);
else
remap(frame, tmp, map1, map2, CV_INTER_AREA);
undistort(frame, tmp);
imshow("Undistorted Image", tmp);
this->activateWindow();
this->setFocus();
......@@ -153,7 +152,7 @@ void CameraCalibration::processSample(const Mat &frame)
Size patternSize( hPatternSizeSB->value(), vPatternSizeSB->value() );
int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE;
if( !fishEyeCB->isChecked())
if( !fishEye)
chessBoardFlags |= CALIB_CB_FAST_CHECK;
switch( patternCB->currentData().toInt() )
......@@ -204,16 +203,36 @@ void CameraCalibration::processSample(const Mat &frame)
collectPB->setEnabled(true);
}
void CameraCalibration::internalInitUndistortRectifyMap()
{
float alpha = 1;
if (fishEye) {
fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize, Matx33d::eye(), newCameraMatrix, alpha, imageSize);
fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, Matx33d::eye(),
newCameraMatrix, imageSize, CV_16SC2,
map1, map2
);
} else {
newCameraMatrix = getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha, imageSize);
initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
newCameraMatrix, imageSize, CV_16SC2,
map1, map2
);
}
}
void CameraCalibration::calibrate()
{
calibrated = false;
qInfo() << "Calibrating, this might take some time; please wait.";
cameraMatrix = Mat::eye(3, 3, CV_64F);
if (fishEyeCB->isChecked())
fishEye = fishEyeCB->isChecked();
if (fishEye)
distCoeffs = Mat::zeros(4, 1, CV_64F);
else
distCoeffs = Mat::zeros(8, 1, CV_64F);
calibrationSuccessful = false;
rms = 0;
if (imagePoints.size() < 5)
......@@ -225,28 +244,20 @@ void CameraCalibration::calibrate()
try {
Mat rv, tv;
if (fishEyeCB->isChecked()) {
if (fishEye) {
int fisheyeFlags = 0;
fisheyeFlags |= fisheye::CALIB_RECOMPUTE_EXTRINSIC;
fisheyeFlags |= fisheye::CALIB_CHECK_COND;
fisheyeFlags |= fisheye::CALIB_FIX_SKEW;
rms = fisheye::calibrate(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rv, tv, fisheyeFlags);
fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize, Matx33d::eye(), newCameraMatrix, 1, imageSize);
fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, Matx33d::eye(),
newCameraMatrix, imageSize, CV_16SC2,
map1, map2);
} else {
rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rv, tv);
newCameraMatrix = getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize);
initUndistortRectifyMap( cameraMatrix, distCoeffs, Mat(),
newCameraMatrix, imageSize, CV_16SC2,
map1, map2
);
}
calibrationSuccessful = true;
internalInitUndistortRectifyMap();
calibrated = true;
} catch (cv::Exception &e) {
qWarning() << "Calibration failed:" << e.what();
calibrationSuccessful = false;
calibrated = false;
}
}
......@@ -260,14 +271,14 @@ void CameraCalibration::store(const QString &fileName)
fs << "sampleCount" << sampleCount;
fs << "coverage" << coverage;
fs << "rms" << rms;
fs << "fisheye" << fishEyeCB->isChecked();
fs << "fishEye" << fishEye;
}
void CameraCalibration::load(const QString &fileName)
{
QFileInfo info(fileName);
if ( !info.exists() ) {
calibrationSuccessful = false;
calibrated = false;
} else {
FileStorage fs( QString(fileName).toStdString(), FileStorage::READ);
fs["cameraMatrix"] >> cameraMatrix;
......@@ -277,19 +288,10 @@ void CameraCalibration::load(const QString &fileName)
fs["sampleCount"] >> sampleCount;
fs["coverage"] >> coverage;
fs["rms"] >> rms;
bool isFisheye;
fs["fisheye"] >> isFisheye;
calibrationSuccessful = true;
if (isFisheye) {
fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, Matx33d::eye(),
newCameraMatrix, imageSize, CV_16SC2,
map1, map2);
} else {
initUndistortRectifyMap( cameraMatrix, distCoeffs, Mat(),
newCameraMatrix, imageSize, CV_32FC1,
map1, map2
);
}
fs["fishEye"] >> fishEye;
fishEyeCB->setChecked(fishEye);
internalInitUndistortRectifyMap();
calibrated = true;
}
updateCalibrationStatus(calibrationSuccessful);
updateCalibrationStatus(calibrated);
}
......@@ -32,7 +32,7 @@ class CameraCalibration : public QDialog
public:
CameraCalibration(QString id, QWidget *parent=0)
: QDialog(parent),
calibrationSuccessful(false),
calibrated(false),
sampleCount(0),
coverage(0),
id(id)
......@@ -129,15 +129,39 @@ public:
CHESSBOARD = 2,
};
cv::Mat cameraMatrix;
cv::Mat newCameraMatrix;
cv::Mat distCoeffs;
cv::Size imageSize;
cv::Rect covered;
int sampleCount;
double coverage;
double rms;
bool calibrationSuccessful;
void undistort(const cv::Mat &in, cv::Mat &out) {
if ( !calibrated || in.cols != imageSize.width || in.rows != imageSize.height ) {
out = in.clone();
return;
}
if (fishEye)
remap(in, out, map1, map2, CV_INTER_AREA);
else
remap(in, out, map1, map2, CV_INTER_AREA);
}
cv::Mat getCameraMatrix(cv::Size size) {
if ( !calibrated || size != imageSize ) {
return (cv::Mat_<double>(3,3) <<
size.width, 0, 0.5*size.width,
0, size.width, 0.5*size.height,
0, 0 ,1 );
}
return cameraMatrix;
}
cv::Mat getDistortionCoefficients(cv::Size size) {
if ( !calibrated || size != imageSize )
return (cv::Mat_<double>(4,1) << 0, 0, 0, 0);
// our coefficients are k1,k2,k3,k4, but estimatePoseSingleMarkers wants (k1,k2,p1,p2[,k3[,k4,k5,k6],[s1,s2,s3,s4]])
if (fishEye)
return (cv::Mat_<double>(4,1) << distCoeffs.at<double>(0,0), distCoeffs.at<double>(1,0), 0, 0);
else
return distCoeffs;
}
signals:
void requestSample();
......@@ -176,6 +200,16 @@ private:
QFutureWatcher<void> watcher;
std::vector<std::vector<cv::Point2f> > imagePoints;
cv::Mat cameraMatrix;
cv::Mat newCameraMatrix;
cv::Mat distCoeffs;
cv::Size imageSize;
cv::Rect covered;
int sampleCount;
double coverage;
double rms;
bool fishEye;
std::atomic<bool> calibrated;
cv::Mat map1, map2;
void processSample(const cv::Mat &frame);
......@@ -183,6 +217,7 @@ private:
void calculateBoardCorners(std::vector<cv::Point3f> &corners);
void calibrate();
void updateCalibrationStatus(bool success);
void internalInitUndistortRectifyMap();
void setLabelText(QLabel* label, QString val, QString color) {
label->setStyleSheet("QLabel { font : bold; color : " + color + " }");
label->setText( val );
......
......@@ -5,26 +5,25 @@ using namespace std;
using namespace cv;
CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *parent) :
ERWidget(parent),
id(id),
ERWidget(id, parent),
type(type),
sROI(QPoint(0,0)),
eROI(QPoint(0,0)),
settingROI(false),
lastUpdate(0),
updateIntervalMs(50),
updateIntervalMs(80),
maxAgeMs(300),
cameraCalibrationSampleRequested(false),
ui(new Ui::CameraWidget)
{
ui->setupUi(this);
ui->setupUi(this);
ui->viewFinder->setScaledContents(false);
ui->viewFinder->setAttribute(Qt::WA_OpaquePaintEvent, true);
ui->viewFinder->setCursor(Qt::CrossCursor);
ui->viewFinder->setCursor(Qt::CrossCursor);
switch (type) {
case ImageProcessor::Eye:
ui->viewFinder->setToolTip("You can select a region of interest by clicking and holding the right mouse button.");
ui->viewFinder->setToolTip("You can select a region of interest by clicking and holding the left mouse button.");
break;
case ImageProcessor::Field:
ui->viewFinder->setToolTip("After starting the collection you can select points by clicking in this view with the left mouse button.");
......@@ -38,7 +37,6 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *paren
gPerformanceMonitor.enrol(id, "Image Processor");
gPerformanceMonitor.enrol(id, "Data Recorder");
setWindowTitle(id + " Widget");
camera = NULL;
imageProcessor = NULL;
......@@ -53,15 +51,23 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *paren
this, SLOT(noCamera(QString)));
// debugging preview
//connect(camera, SIGNAL(newFrame(Timestamp, const cv::Mat&)),
// this, SLOT(preview(Timestamp, const cv::Mat&)) );
// this, SLOT(preview(Timestamp, const cv::Mat&)) );
cameraCalibration = new CameraCalibration(id);
connect(cameraCalibration, SIGNAL(requestSample()),
this, SLOT(requestCameraCalibrationSample()) );
connect(cameraCalibration, SIGNAL(calibrationFinished(bool)),
this, SLOT(onCameraCalibrationFinished(bool)) );
cameraCalibration->load(gCfgDir + "/" + id + "Calibration.xml");
// Image Processor
processorThread = new QThread();
processorThread->setObjectName(id + " Processor");
processorThread->start();
processorThread->setPriority(QThread::TimeCriticalPriority);
imageProcessor = new ImageProcessor(id, type);
imageProcessor->moveToThread(processorThread);
imageProcessor = new ImageProcessor(id, type);
imageProcessor->cameraCalibration = cameraCalibration;
imageProcessor->moveToThread(processorThread);
switch (type) {
case ImageProcessor::Eye:
imageProcessor->eyeProcessorUI = new EyeImageProcessorUI;
......@@ -70,8 +76,8 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *paren
connect(imageProcessor, SIGNAL(newData(EyeData)),
this, SIGNAL(newData(EyeData)) );
break;
case ImageProcessor::Field:
imageProcessor->fieldProcessorUI = new FieldImageProcessorUI;
case ImageProcessor::Field:
imageProcessor->fieldProcessorUI = new FieldImageProcessorUI;
connect(imageProcessor, SIGNAL(newData(FieldData)),
this, SLOT(preview(FieldData)) );
connect(imageProcessor, SIGNAL(newData(FieldData)),
......@@ -79,7 +85,7 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *paren
break;
}
QMetaObject::invokeMethod(imageProcessor, "create");
connect(camera, SIGNAL(newFrame(Timestamp, const cv::Mat&)),
connect(camera, SIGNAL(newFrame(Timestamp, const cv::Mat&)),
imageProcessor, SIGNAL(process(Timestamp, const cv::Mat&)) );
// Data Recorder
......@@ -91,13 +97,6 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *paren
recorder->moveToThread(recorderThread);
QMetaObject::invokeMethod(recorder, "create");
cameraCalibration = new CameraCalibration(id);
connect(cameraCalibration, SIGNAL(requestSample()),
this, SLOT(requestCameraCalibrationSample()) );
connect(cameraCalibration, SIGNAL(calibrationFinished(bool)),
this, SLOT(onCameraCalibrationFinished(bool)) );
cameraCalibration->load(gCfgDir + "/" + id + "Calibration.xml");
// GUI
optionsGroup = new QActionGroup(this);
connect(optionsGroup, SIGNAL(triggered(QAction*)),
......@@ -106,7 +105,7 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *paren
optionAction = new QAction("Camera", optionsGroup);
optionAction->setData(QVariant::fromValue(optionAction->text()));
optionAction->setCheckable(false);
ui->menuOptions->addAction(optionAction);
ui->menuOptions->addAction(optionAction);
optionAction = new QAction("Image Processor", optionsGroup);
optionAction->setData(QVariant::fromValue(optionAction->text()));
......@@ -289,7 +288,7 @@ void CameraWidget::options(QAction* action)
QMetaObject::invokeMethod(camera, "showOptions", Qt::QueuedConnection);
}
}
if (option == "image processor")
if (option == "image processor")
if (imageProcessor)
QMetaObject::invokeMethod(imageProcessor, "showOptions", Qt::QueuedConnection, Q_ARG(QPoint, this->pos()));
......@@ -310,21 +309,21 @@ void CameraWidget::startRecording()
void CameraWidget::stopRecording()
{
QMetaObject::invokeMethod(recorder, "stopRecording");
disconnect(imageProcessor, SIGNAL(newData(EyeData)),
recorder, SIGNAL(newData(EyeData)) );
disconnect(imageProcessor, SIGNAL(newData(FieldData)),
recorder, SIGNAL(newData(FieldData)) );
disconnect(imageProcessor, SIGNAL(newData(EyeData)),
recorder, SIGNAL(newData(EyeData)) );
disconnect(imageProcessor, SIGNAL(newData(FieldData)),
recorder, SIGNAL(newData(FieldData)) );
QMetaObject::invokeMethod(recorder, "stopRecording", Qt::QueuedConnection);
ui->menubar->setEnabled(true);
}
void CameraWidget::mousePressEvent(QMouseEvent *event)
{
if (ui->viewFinder->underMouse()) {
if (event->button() == Qt::LeftButton)
if (event->button() == Qt::LeftButton && type == ImageProcessor::Field)
emit newClick( gTimer.elapsed(), ui->viewFinder->mapFromGlobal(this->mapToGlobal(event->pos())), ui->viewFinder->size());
if (event->button() == Qt::RightButton) {
if (event->button() == Qt::LeftButton && type == ImageProcessor::Eye) {
sROI = ui->viewFinder->mapFrom(this, event->pos());
validatePoint(sROI);
sROI.setX( sROI.x() / ui->viewFinder->width());
......@@ -349,7 +348,7 @@ void CameraWidget::mouseMoveEvent(QMouseEvent *event)
void CameraWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::RightButton) {
if (event->button() == Qt::LeftButton && type == ImageProcessor::Eye) {
eROI = ui->viewFinder->mapFrom(this, event->pos());
validatePoint(eROI);
eROI.setX( eROI.x() / ui->viewFinder->width());
......@@ -378,7 +377,10 @@ void CameraWidget::validatePoint(QPointF &point)
bool CameraWidget::shouldUpdate(Timestamp t)
{
if (!this->isVisible())
return false;
return false;
if (gFreezePreview)
return false;
/* TODO: Right now, we don't update every frame to save resources.
* Make this parametrizable or move to faster drawing methods.
......@@ -470,6 +472,12 @@ void CameraWidget::onCameraCalibrationFinished(bool success)
void CameraWidget::updateWidgetSize(const int &width, const int &height)
{
if ( this->type == ImageProcessor::Eye)
this->setMaximumSize(320, 240);
if ( this->type == ImageProcessor::Field)
this->setMaximumSize(640, 360);
return;
// Logic to limit the size of the camera widgets
QSize newFrameSize = { width, height };
if (frameSize == newFrameSize)
......
......@@ -70,7 +70,6 @@ public slots:
void onCameraCalibrationFinished(bool success);
private:
QString id;
ImageProcessor::Type type;
Ui::CameraWidget *ui;
......@@ -87,7 +86,7 @@ private:
QActionGroup *optionsGroup;
QAction *optionAction;
std::deque<int> tq;
std::deque<Timestamp> tq;
Timestamp lastFrameRateUpdate;
void updateFrameRate(Timestamp t);
......
......@@ -10,6 +10,12 @@
<height>240</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>240</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
......
#include "CommandManager.h"
#include <QSettings>
#include <QDebug>
// TODO: make these keys configurable
CommandManager::CommandManager(QObject *parent)
{
Q_UNUSED(parent);
QString settingsFileName = QString("%1/CommandManager.ini").arg(gCfgDir);
bool hasSettings = QFile::exists(settingsFileName);
QSettings *settings = new QSettings(settingsFileName, QSettings::IniFormat);
if (hasSettings) {
remoteCalibrationToggleKey = settings->value("remoteCalibrationToggleKey").toInt();
remoteRecordingToggleKey = settings->value("remoteRecordingToggleKey").toInt();
calibrationToggleKey = settings->value("calibrationToggleKey").toInt();
collectionToggleKey = settings->value("collectionToggleKey").toInt();
recordingToggleKey = settings->value("recordingToggleKey").toInt();
previewToggleKey = settings->value("previewToggleKey").toInt();
} else {
settings->setValue("remoteCalibrationToggleKey", remoteCalibrationToggleKey);
settings->setValue("remoteRecordingToggleKey", remoteRecordingToggleKey);
settings->setValue("calibrationToggleKey", calibrationToggleKey);
settings->setValue("collectionToggleKey", collectionToggleKey);
settings->setValue("recordingToggleKey", recordingToggleKey);
settings->setValue("previewToggleKey", previewToggleKey);
}
settings->deleteLater();
}
void CommandManager::keyPress(QKeyEvent *event)
{
if (event->isAutoRepeat())
return;
switch (event->key()) {
case Qt::Key_C:
case Qt::Key_PageDown:
emit enableMarkerCollection();
break;
case Qt::Key_S:
case Qt::Key_PageUp:
emit toggleCalibration();
break;
case Qt::Key_R:
case Qt::Key_B:
emit toggleRecording();
break;
case Qt::Key_F:
emit freezeCameraImages();
break;
default:
break;
}
if (event->isAutoRepeat())
return;
if (event->key() == remoteCalibrationToggleKey) {
emit toggleRemoteCalibration();
} else if (event->key() == remoteRecordingToggleKey) {
emit toggleRemoteRecording();
} else if (event->key() == calibrationToggleKey) {
emit toggleCalibration();
} else if (event->key() == collectionToggleKey) {
emit toggleMarkerCollection();
} else if (event->key() == recordingToggleKey) {
emit toggleRecording();
} else if (event->key() == previewToggleKey ){
emit togglePreview();
}
}
void CommandManager::keyRelease(QKeyEvent *event)
{
if (event->isAutoRepeat())
return;
switch (event->key()) {
case Qt::Key_C:
case Qt::Key_PageDown:
emit disableMarkerCollection();
break;
case Qt::Key_F:
emit unfreezeCameraImages();
break;
default:
break;
}
}
......@@ -5,21 +5,36 @@
#include <QEvent>
#include <QKeyEvent>
#include "utils.h"
class CommandManager : public QObject
{
Q_OBJECT
public:
explicit CommandManager(QObject *parent = 0);
public slots:
void keyPress(QKeyEvent *event);
void keyRelease(QKeyEvent *event);
signals:
void toggleCalibration();
void toggleMarkerCollection();
void toggleRemoteCalibration();
void toggleRecording();
void enableMarkerCollection();
void disableMarkerCollection();
void toggleRemoteRecording();
void togglePreview();
void freezeCameraImages();
void unfreezeCameraImages();
void unfreezeCameraImages();
private:
int remoteCalibrationToggleKey = Qt::Key_PageDown;
int calibrationToggleKey = Qt::Key_S;
int collectionToggleKey = Qt::Key_C;
int recordingToggleKey = Qt::Key_R;
int remoteRecordingToggleKey = Qt::Key_PageUp;
int previewToggleKey = Qt::Key_B;
};
#endif // COMMANDMANAGER_H