diff --git a/include/codeMarkerItem.h b/include/codeMarkerItem.h
index bd5b8307451a8e110629231871627fe4d7b3f318..1263cce759d98134985a420917e7647b1155e0a1 100644
--- a/include/codeMarkerItem.h
+++ b/include/codeMarkerItem.h
@@ -28,6 +28,10 @@
 class Petrack;
 class Control;
 class Tracker;
+namespace reco {
+    class CodeMarkerOptions;
+}
+
 
 struct OffsetMarker {
     std::vector<cv::Point2f> corners;
@@ -40,6 +44,7 @@ class CodeMarkerItem : public QGraphicsItem
 {
 private:
     Petrack *mMainWindow;
+    const reco::CodeMarkerOptions &mArucoOptions;
     const QColor mRejectedColor = QColor(255,0,0); // red
     const QColor mCornerColor = QColor(0,0,255); // blue
     const QColor mAcceptedColor = QColor(0,255,0); // green
@@ -49,7 +54,7 @@ private:
     Vec2F mUlc;  // upper left corner to draw
 
 public:
-    CodeMarkerItem(QWidget *wParent, QGraphicsItem * parent = nullptr);
+    CodeMarkerItem(QWidget *wParent, const reco::CodeMarkerOptions &options, QGraphicsItem * parent = nullptr);
     QRectF boundingRect() const override;
     void setRect(Vec2F& v);
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
diff --git a/include/codeMarkerWidget.h b/include/codeMarkerWidget.h
index 8fc06b18b4a4db7b2f6cf82db1405dc9231edadd..658a18568b0f38fd62ad8f59e8ccdbfde2b7c943 100644
--- a/include/codeMarkerWidget.h
+++ b/include/codeMarkerWidget.h
@@ -24,18 +24,23 @@
 #include <QtWidgets>
 #include <opencv2/aruco.hpp>
 
-#include "ui_codeMarker.h"
+
 
 #include "petrack.h"
 #include "codeMarkerItem.h"
 #include "recognition.h"
+namespace Ui{
+    class CodeMarker;
+}
+
+
 
-class CodeMarkerWidget: public QWidget, public Ui::CodeMarker
+class CodeMarkerWidget: public QWidget
 {
     Q_OBJECT
 
 public:
-    CodeMarkerWidget(QWidget *parent, reco::CodeMarkerOptions& opt);
+    CodeMarkerWidget(QWidget *parent, reco::CodeMarkerOptions& opt, Ui::CodeMarker *mUi);
 
     // store data in xml node
     void setXml(QDomElement &elem);
@@ -43,8 +48,7 @@ public:
     // read data from xml node
     void getXml(QDomElement &elem);
 
-    reco::ArucoCodeParams packDetectorParams();
-
+    bool showDetectedCandidates();
 
 private slots:
 
@@ -62,8 +66,12 @@ private slots:
     void readDictListIndex();
 
 private:
+    Ui::CodeMarker *mUi;
+
     Petrack *mMainWindow;
     reco::CodeMarkerOptions &mCodeMarkerOpt;
 };
 
+reco::ArucoCodeParams packDetectorParams(const Ui::CodeMarker *ui);
+
 #endif
diff --git a/include/recognition.h b/include/recognition.h
index 4076c237b830f61e2057c3a302238d2cec32772e..3a190d05f460b05814d3cc71e3b9395c52bea2d8 100644
--- a/include/recognition.h
+++ b/include/recognition.h
@@ -51,7 +51,7 @@ namespace reco {
         Code = 6,
     };
 
-    struct ArucoCodeParams {
+    class ArucoCodeParams {
         double minMarkerPerimeter = 5;
         double maxMarkerPerimeter = 15;
         double minCornerDistance = 0.05;
@@ -73,6 +73,8 @@ namespace reco {
         double minOtsuStdDev = 5;
         double errorCorrectionRate = 0.6;
 
+    public:
+
         friend inline constexpr bool operator==(const ArucoCodeParams & lhs, const ArucoCodeParams & rhs) noexcept
         {
             return (lhs.minMarkerPerimeter == rhs.minMarkerPerimeter) && ((lhs.maxMarkerPerimeter == rhs.maxMarkerPerimeter) && ((lhs.minCornerDistance == rhs.minCornerDistance) && ((lhs.minMarkerDistance == rhs.minMarkerDistance) && ((lhs.adaptiveThreshWinSizeMin == rhs.adaptiveThreshWinSizeMin) && ((lhs.adaptiveThreshWinSizeMax == rhs.adaptiveThreshWinSizeMax) && ((lhs.adaptiveThreshWinSizeStep == rhs.adaptiveThreshWinSizeStep) && ((lhs.adaptiveThreshConstant == rhs.adaptiveThreshConstant) && ((lhs.polygonalApproxAccuracyRate == rhs.polygonalApproxAccuracyRate) && ((lhs.minDistanceToBorder == rhs.minDistanceToBorder) && ((static_cast<int>(lhs.doCornerRefinement) == static_cast<int>(rhs.doCornerRefinement)) && ((lhs.cornerRefinementWinSize == rhs.cornerRefinementWinSize) && ((lhs.cornerRefinementMaxIterations == rhs.cornerRefinementMaxIterations) && ((lhs.cornerRefinementMinAccuracy == rhs.cornerRefinementMinAccuracy) && ((lhs.markerBorderBits == rhs.markerBorderBits) && ((lhs.perspectiveRemovePixelPerCell == rhs.perspectiveRemovePixelPerCell) && ((lhs.perspectiveRemoveIgnoredMarginPerCell == rhs.perspectiveRemoveIgnoredMarginPerCell) && ((lhs.maxErroneousBitsInBorderRate == rhs.maxErroneousBitsInBorderRate) && ((lhs.minOtsuStdDev == rhs.minOtsuStdDev) && (lhs.errorCorrectionRate == rhs.errorCorrectionRate)))))))))))))))))));
@@ -81,13 +83,53 @@ namespace reco {
         {
             return !(lhs == rhs);
         }
+        double getMinMarkerPerimeter() const;
+        void setMinMarkerPerimeter(double newMinMarkerPerimeter);
+        double getMaxMarkerPerimeter() const;
+        void setMaxMarkerPerimeter(double newMaxMarkerPerimeter);
+        double getMinCornerDistance() const;
+        void setMinCornerDistance(double newMinCornerDistance);
+        double getMinMarkerDistance() const;
+        void setMinMarkerDistance(double newMinMarkerDistance);
+        int getAdaptiveThreshWinSizeMin() const;
+        void setAdaptiveThreshWinSizeMin(int newAdaptiveThreshWinSizeMin);
+        int getAdaptiveThreshWinSizeMax() const;
+        void setAdaptiveThreshWinSizeMax(int newAdaptiveThreshWinSizeMax);
+        int getAdaptiveThreshWinSizeStep() const;
+        void setAdaptiveThreshWinSizeStep(int newAdaptiveThreshWinSizeStep);
+        int getAdaptiveThreshConstant() const;
+        void setAdaptiveThreshConstant(int newAdaptiveThreshConstant);
+        double getPolygonalApproxAccuracyRate() const;
+        void setPolygonalApproxAccuracyRate(double newPolygonalApproxAccuracyRate);
+        int getMinDistanceToBorder() const;
+        void setMinDistanceToBorder(int newMinDistanceToBorder);
+        bool getDoCornerRefinement() const;
+        void setDoCornerRefinement(bool newDoCornerRefinement);
+        int getCornerRefinementWinSize() const;
+        void setCornerRefinementWinSize(int newCornerRefinementWinSize);
+        int getCornerRefinementMaxIterations() const;
+        void setCornerRefinementMaxIterations(int newCornerRefinementMaxIterations);
+        double getCornerRefinementMinAccuracy() const;
+        void setCornerRefinementMinAccuracy(double newCornerRefinementMinAccuracy);
+        int getMarkerBorderBits() const;
+        void setMarkerBorderBits(int newMarkerBorderBits);
+        int getPerspectiveRemovePixelPerCell() const;
+        void setPerspectiveRemovePixelPerCell(int newPerspectiveRemovePixelPerCell);
+        double getPerspectiveRemoveIgnoredMarginPerCell() const;
+        void setPerspectiveRemoveIgnoredMarginPerCell(double newPerspectiveRemoveIgnoredMarginPerCell);
+        double getMaxErroneousBitsInBorderRate() const;
+        void setMaxErroneousBitsInBorderRate(double newMaxErroneousBitsInBorderRate);
+        double getMinOtsuStdDev() const;
+        void setMinOtsuStdDev(double newMinOtsuStdDev);
+        double getErrorCorrectionRate() const;
+        void setErrorCorrectionRate(double newErrorCorrectionRate);
     };
 
 
-    struct CodeMarkerOptions : public QObject{
+    class CodeMarkerOptions : public QObject{
         Q_OBJECT
 
-    public:
+    private:
         CodeMarkerItem *codeMarkerItem;
         int indexOfMarkerDict = 16;
 
@@ -97,12 +139,22 @@ namespace reco {
         Vec2F offsetCropRect2Roi = Vec2F{0,0};
 
     public:
+        // TODO: Remove getter and setter for pointers;
+        // cannot properly set these in constructor because of
+        // bidirectional dependecies
+        CodeMarkerItem *getCodeMarkerItem() const {return codeMarkerItem;}
+        Control *getControlWidget() const {return controlWidget;}
         ArucoCodeParams getDetectorParams() const {return detectorParams;}
         int getIndexOfMarkerDict() const {return indexOfMarkerDict;}
 
     public:
-        void userChangedDetectorParams(ArucoCodeParams params);
-        void userChangedIndexOfMarkerDict(int idx);
+        void setCodeMarkerItem(CodeMarkerItem *item) {codeMarkerItem = item;}
+        void setControlWidget(Control *control) {controlWidget = control;}
+        void setDetectorParams(ArucoCodeParams params);
+        void setIndexOfMarkerDict(int idx);
+
+        const Vec2F &getOffsetCropRect2Roi() const;
+        void setOffsetCropRect2Roi(const Vec2F &newOffsetCropRect2Roi);
 
     signals:
         void detectorParamsChanged();
diff --git a/src/codeMarkerItem.cpp b/src/codeMarkerItem.cpp
index c959e4ead4d74a1b836c3709c2f630ac91642c01..ba27927ee8b75dae682429ed27eb9d2256b5e4d8 100644
--- a/src/codeMarkerItem.cpp
+++ b/src/codeMarkerItem.cpp
@@ -29,9 +29,9 @@
 
 // in x und y gleichermassen skaliertes koordinatensystem,
 // da von einer vorherigen intrinsischen kamerakalibrierung ausgegenagen wird,
-// so dass pixel quadratisch 
-CodeMarkerItem::CodeMarkerItem(QWidget *wParent, QGraphicsItem * parent)
-    : QGraphicsItem(parent)
+// so dass pixel quadratisch
+CodeMarkerItem::CodeMarkerItem(QWidget *wParent, const reco::CodeMarkerOptions &options, QGraphicsItem * parent)
+    : QGraphicsItem(parent), mArucoOptions(options)
 {
     mMainWindow = (class Petrack*) wParent;
 }
@@ -73,7 +73,7 @@ void CodeMarkerItem::setRect(Vec2F& v)
 void CodeMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
 {
 
-    if (mMainWindow->getCodeMarkerWidget()->showDetectedCandidates->isChecked())
+    if (mMainWindow->getCodeMarkerWidget()->showDetectedCandidates())
     {
         int nMarkers = static_cast<int>(mCorners.size());
         int nRejected = static_cast<int>(mRejected.size());
@@ -91,8 +91,8 @@ void CodeMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*
 
     if (false) // Show min/max marker size
     {
-        int minPerimeter = mMainWindow->getCodeMarkerWidget()->minMarkerPerimeter->value();
-        int maxPerimeter = mMainWindow->getCodeMarkerWidget()->maxMarkerPerimeter->value();
+        int minPerimeter = mArucoOptions.getDetectorParams().getMinMarkerPerimeter();
+        int maxPerimeter = mArucoOptions.getDetectorParams().getMaxMarkerPerimeter();
         double height = mMainWindow->getStatusPosRealHeight();
 
         cv::Point2f p0,p1,p2,p3;
diff --git a/src/codeMarkerWidget.cpp b/src/codeMarkerWidget.cpp
index b141e6bdf508621caf5cf36719dafeb65d5429de..0982a4385573cd1fb1a234754d013ed49de87064 100644
--- a/src/codeMarkerWidget.cpp
+++ b/src/codeMarkerWidget.cpp
@@ -20,38 +20,46 @@
 
 #include <opencv2/core/version.hpp>
 
+#include "ui_codeMarker.h"
+
 #include "codeMarkerWidget.h"
 #include "recognition.h"
+#include "pMessageBox.h"
 
-CodeMarkerWidget::CodeMarkerWidget(QWidget *parent, reco::CodeMarkerOptions& codeMarkerOpt)
+CodeMarkerWidget::CodeMarkerWidget(QWidget *parent, reco::CodeMarkerOptions& codeMarkerOpt, Ui::CodeMarker* ui)
     : QWidget(parent), mCodeMarkerOpt(codeMarkerOpt)
 {
     mMainWindow = (class Petrack*) parent;
+    if(!ui){
+        mUi = new Ui::CodeMarker();
+    }else{
+        mUi = ui;
+    }
 
-    setupUi(this);
+    mUi->setupUi(this);
 
-    dictList->addItem("DICT_4X4_50");  // 0
-    dictList->addItem("DICT_4X4_100"); // 1
-    dictList->addItem("DICT_4X4_250"); // 2
-    dictList->addItem("DICT_4X4_1000");// 3
+    mUi->dictList->addItem("DICT_4X4_50");  // 0
+    mUi->dictList->addItem("DICT_4X4_100"); // 1
+    mUi->dictList->addItem("DICT_4X4_250"); // 2
+    mUi->dictList->addItem("DICT_4X4_1000");// 3
 
-    dictList->addItem("DICT_5X5_50");  // 4
-    dictList->addItem("DICT_5X5_100"); // 5
-    dictList->addItem("DICT_5X5_250"); // 6
-    dictList->addItem("DICT_5X5_1000");// 7
+    mUi->dictList->addItem("DICT_5X5_50");  // 4
+    mUi->dictList->addItem("DICT_5X5_100"); // 5
+    mUi->dictList->addItem("DICT_5X5_250"); // 6
+    mUi->dictList->addItem("DICT_5X5_1000");// 7
 
-    dictList->addItem("DICT_6X6_50");  // 8
-    dictList->addItem("DICT_6X6_100"); // 9
-    dictList->addItem("DICT_6X6_250"); // 10
-    dictList->addItem("DICT_6X6_1000");// 11
+    mUi->dictList->addItem("DICT_6X6_50");  // 8
+    mUi->dictList->addItem("DICT_6X6_100"); // 9
+    mUi->dictList->addItem("DICT_6X6_250"); // 10
+    mUi->dictList->addItem("DICT_6X6_1000");// 11
 
-    dictList->addItem("DICT_7X7_50");  // 12
-    dictList->addItem("DICT_7X7_100"); // 13
-    dictList->addItem("DICT_7X7_250"); // 14
-    dictList->addItem("DICT_7X7_1000");// 15
+    mUi->dictList->addItem("DICT_7X7_50");  // 12
+    mUi->dictList->addItem("DICT_7X7_100"); // 13
+    mUi->dictList->addItem("DICT_7X7_250"); // 14
+    mUi->dictList->addItem("DICT_7X7_1000");// 15
 
-    dictList->addItem("DICT_ARUCO_ORGINAL"); // 16
-    dictList->addItem("DICT_mip_36h12");//17
+    mUi->dictList->addItem("DICT_ARUCO_ORGINAL"); // 16
+    mUi->dictList->addItem("DICT_mip_36h12");//17
 
     connect(&mCodeMarkerOpt, &reco::CodeMarkerOptions::detectorParamsChanged, this, &CodeMarkerWidget::readDetectorParams);
     connect(&mCodeMarkerOpt, &reco::CodeMarkerOptions::indexOfMarkerDictChanged, this, &CodeMarkerWidget::readDictListIndex);
@@ -64,34 +72,39 @@ CodeMarkerWidget::CodeMarkerWidget(QWidget *parent, reco::CodeMarkerOptions& cod
     // NOTE: No parameter validation done here
     // Can result in crash, when invalid params are chosen (e.g. min larger than max)
     auto changedParams = [&](){
-        sendDetectorParams(packDetectorParams());
+        try{
+        sendDetectorParams(packDetectorParams(mUi));
         notifyChanged();
+        }catch(std::invalid_argument &e){
+            PWarning(this, "Wrong Value", e.what());
+            readDetectorParams();
+        }
     };
 
-    connect(minMarkerPerimeter, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-    connect(maxMarkerPerimeter, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-
-    connect(adaptiveThreshWinSizeMin, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(adaptiveThreshWinSizeMax, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(adaptiveThreshWinSizeStep, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(adaptiveThreshConstant, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-
-    connect(polygonalApproxAccuracyRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-    connect(minCornerDistance, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-    connect(minDistanceToBorder, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(minMarkerDistance, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-
-    connect(doCornerRefinement, &QGroupBox::clicked, changedParams);
-    connect(cornerRefinementWinSize, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(cornerRefinementMaxIterations, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(cornerRefinementMinAccuracy, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-
-    connect(markerBorderBits, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(perspectiveRemovePixelPerCell, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
-    connect(perspectiveRemoveIgnoredMarginPerCell, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-    connect(maxErroneousBitsInBorderRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-    connect(errorCorrectionRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
-    connect(minOtsuStdDev, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+    connect(mUi->minMarkerPerimeter, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+    connect(mUi->maxMarkerPerimeter, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+
+    connect(mUi->adaptiveThreshWinSizeMin, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->adaptiveThreshWinSizeMax, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->adaptiveThreshWinSizeStep, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->adaptiveThreshConstant, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+
+    connect(mUi->polygonalApproxAccuracyRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+    connect(mUi->minCornerDistance, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+    connect(mUi->minDistanceToBorder, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->minMarkerDistance, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+
+    connect(mUi->doCornerRefinement, &QGroupBox::clicked, changedParams);
+    connect(mUi->cornerRefinementWinSize, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->cornerRefinementMaxIterations, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->cornerRefinementMinAccuracy, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+
+    connect(mUi->markerBorderBits, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->perspectiveRemovePixelPerCell, QOverload<int>::of(&QSpinBox::valueChanged), changedParams);
+    connect(mUi->perspectiveRemoveIgnoredMarginPerCell, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+    connect(mUi->maxErroneousBitsInBorderRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+    connect(mUi->errorCorrectionRate, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
+    connect(mUi->minOtsuStdDev, QOverload<double>::of(&QDoubleSpinBox::valueChanged), changedParams);
 }
 
 //<COLOR_MARKER>
@@ -107,31 +120,31 @@ void CodeMarkerWidget::setXml(QDomElement &elem)
     QDomElement subElem;
 
     subElem = (elem.ownerDocument()).createElement("DICTIONARY");
-    subElem.setAttribute("ID", dictList->currentIndex());
+    subElem.setAttribute("ID", mUi->dictList->currentIndex());
     elem.appendChild(subElem);
 
     subElem = (elem.ownerDocument()).createElement("PARAM");
-    subElem.setAttribute("ADAPTIVE_THRESH_WIN_SIZE_MIN",adaptiveThreshWinSizeMin->value());
-    subElem.setAttribute("ADAPTIVE_THRESH_WIN_SIZE_MAX",adaptiveThreshWinSizeMax->value());
-    subElem.setAttribute("ADAPTIVE_THRESH_WIN_SIZE_STEP",adaptiveThreshWinSizeStep->value());
-    subElem.setAttribute("ADAPTIVE_THRESH_CONSTANT",adaptiveThreshConstant->value());
-    subElem.setAttribute("MIN_MARKER_PERIMETER",minMarkerPerimeter->value());
-    subElem.setAttribute("MAX_MARKER_PERIMETER",maxMarkerPerimeter->value());
-    subElem.setAttribute("MAX_RATIO_ERROR",polygonalApproxAccuracyRate->value());
-    subElem.setAttribute("MIN_CORNER_DISTANCE",minCornerDistance->value());
-    subElem.setAttribute("MIN_DISTANCE_TO_BORDER",minDistanceToBorder->value());
-    subElem.setAttribute("MIN_MARKER_DISTANCE",minMarkerDistance->value());
-    subElem.setAttribute("CORNER_REFINEMENT", doCornerRefinement->isChecked());
-    subElem.setAttribute("CORNER_REFINEMENT_WIN_SIZE",cornerRefinementWinSize->value());
-    subElem.setAttribute("CORNER_REFINEMENT_MAX_ITERATIONS",cornerRefinementMaxIterations->value());
-    subElem.setAttribute("CORNER_REFINEMENT_MIN_ACCURACY",cornerRefinementMinAccuracy->value());
-    subElem.setAttribute("MARKER_BORDER_BITS",markerBorderBits->value());
-    subElem.setAttribute("PERSPECTIVE_REMOVE_PIXEL_PER_CELL",perspectiveRemovePixelPerCell->value());
-    subElem.setAttribute("PERSPECTIVE_REMOVE_IGNORED_MARGIN_PER_CELL",perspectiveRemoveIgnoredMarginPerCell->value());
-    subElem.setAttribute("MAX_ERRONEOUS_BITS_IN_BORDER_RATE",maxErroneousBitsInBorderRate->value());
-    subElem.setAttribute("MIN_OTSU_STD_DEV",minOtsuStdDev->value());
-    subElem.setAttribute("ERROR_CORRECTION_RATE",errorCorrectionRate->value());
-    subElem.setAttribute("SHOW_DETECTED_CANDIDATES", showDetectedCandidates->isChecked());
+    subElem.setAttribute("ADAPTIVE_THRESH_WIN_SIZE_MIN",mUi->adaptiveThreshWinSizeMin->value());
+    subElem.setAttribute("ADAPTIVE_THRESH_WIN_SIZE_MAX",mUi->adaptiveThreshWinSizeMax->value());
+    subElem.setAttribute("ADAPTIVE_THRESH_WIN_SIZE_STEP",mUi->adaptiveThreshWinSizeStep->value());
+    subElem.setAttribute("ADAPTIVE_THRESH_CONSTANT",mUi->adaptiveThreshConstant->value());
+    subElem.setAttribute("MIN_MARKER_PERIMETER",mUi->minMarkerPerimeter->value());
+    subElem.setAttribute("MAX_MARKER_PERIMETER",mUi->maxMarkerPerimeter->value());
+    subElem.setAttribute("MAX_RATIO_ERROR",mUi->polygonalApproxAccuracyRate->value());
+    subElem.setAttribute("MIN_CORNER_DISTANCE",mUi->minCornerDistance->value());
+    subElem.setAttribute("MIN_DISTANCE_TO_BORDER",mUi->minDistanceToBorder->value());
+    subElem.setAttribute("MIN_MARKER_DISTANCE",mUi->minMarkerDistance->value());
+    subElem.setAttribute("CORNER_REFINEMENT",mUi-> doCornerRefinement->isChecked());
+    subElem.setAttribute("CORNER_REFINEMENT_WIN_SIZE",mUi->cornerRefinementWinSize->value());
+    subElem.setAttribute("CORNER_REFINEMENT_MAX_ITERATIONS",mUi->cornerRefinementMaxIterations->value());
+    subElem.setAttribute("CORNER_REFINEMENT_MIN_ACCURACY",mUi->cornerRefinementMinAccuracy->value());
+    subElem.setAttribute("MARKER_BORDER_BITS",mUi->markerBorderBits->value());
+    subElem.setAttribute("PERSPECTIVE_REMOVE_PIXEL_PER_CELL",mUi->perspectiveRemovePixelPerCell->value());
+    subElem.setAttribute("PERSPECTIVE_REMOVE_IGNORED_MARGIN_PER_CELL",mUi->perspectiveRemoveIgnoredMarginPerCell->value());
+    subElem.setAttribute("MAX_ERRONEOUS_BITS_IN_BORDER_RATE",mUi->maxErroneousBitsInBorderRate->value());
+    subElem.setAttribute("MIN_OTSU_STD_DEV",mUi->minOtsuStdDev->value());
+    subElem.setAttribute("ERROR_CORRECTION_RATE",mUi->errorCorrectionRate->value());
+    subElem.setAttribute("SHOW_DETECTED_CANDIDATES",mUi-> showDetectedCandidates->isChecked());
     elem.appendChild(subElem);
 
 }
@@ -148,82 +161,88 @@ void CodeMarkerWidget::getXml(QDomElement &elem)
         if (subElem.tagName() == "DICTIONARY")
         {
             if (subElem.hasAttribute("ID"))
-                dictList->setCurrentIndex(subElem.attribute("ID").toInt());
+                mUi->dictList->setCurrentIndex(subElem.attribute("ID").toInt());
         }
 
         if (subElem.tagName() == "PARAM")
         {
-            if (subElem.hasAttribute("ADAPTIVE_THRESH_WIN_SIZE_MIN"))
-                adaptiveThreshWinSizeMin->setValue(subElem.attribute("ADAPTIVE_THRESH_WIN_SIZE_MIN").toInt());
-            if (subElem.hasAttribute("ADAPTIVE_THRESH_WIN_SIZE_MAX"))
-                adaptiveThreshWinSizeMax->setValue(subElem.attribute("ADAPTIVE_THRESH_WIN_SIZE_MAX").toInt());
-            if (subElem.hasAttribute("ADAPTIVE_THRESH_WIN_SIZE_STEP"))
-                adaptiveThreshWinSizeStep->setValue(subElem.attribute("ADAPTIVE_THRESH_WIN_SIZE_STEP").toInt());
-            if (subElem.hasAttribute("ADAPTIVE_THRESH_CONSTANT"))
-                adaptiveThreshConstant->setValue(subElem.attribute("ADAPTIVE_THRESH_CONSTANT").toInt());
+            if (subElem.hasAttribute("ADAPTIVE_TRHESH_WIN_SIZE_MIN"))
+                mUi->adaptiveThreshWinSizeMin->setValue(subElem.attribute("ADAPTIVE_THRESH_WIN_SIZE_MIN").toInt());
+            if (subElem.hasAttribute("ADAPTIVE_TRHESH_WIN_SIZE_MAX"))
+                mUi->adaptiveThreshWinSizeMax->setValue(subElem.attribute("ADAPTIVE_THRESH_WIN_SIZE_MAX").toInt());
+            if (subElem.hasAttribute("ADAPTIVE_TRHESH_WIN_SIZE_STEP"))
+                mUi->adaptiveThreshWinSizeStep->setValue(subElem.attribute("ADAPTIVE_THRESH_WIN_SIZE_STEP").toInt());
+            if (subElem.hasAttribute("ADAPTIVE_TRHESH_CONSTANT"))
+                mUi->adaptiveThreshConstant->setValue(subElem.attribute("ADAPTIVE_THRESH_CONSTANT").toInt());
             if (subElem.hasAttribute("MIN_MARKER_PERIMETER"))
-                minMarkerPerimeter->setValue(subElem.attribute("MIN_MARKER_PERIMETER").toDouble());
+                mUi->minMarkerPerimeter->setValue(subElem.attribute("MIN_MARKER_PERIMETER").toDouble());
             if (subElem.hasAttribute("MAX_MARKER_PERIMETER"))
-                maxMarkerPerimeter->setValue(subElem.attribute("MAX_MARKER_PERIMETER").toDouble());
+                mUi->maxMarkerPerimeter->setValue(subElem.attribute("MAX_MARKER_PERIMETER").toDouble());
             if (subElem.hasAttribute("MAX_RATIO_ERROR"))
-                polygonalApproxAccuracyRate->setValue(subElem.attribute("MAX_RATIO_ERROR").toDouble());
+                mUi->polygonalApproxAccuracyRate->setValue(subElem.attribute("MAX_RATIO_ERROR").toDouble());
             if (subElem.hasAttribute("MIN_CORNER_DISTANCE"))
-                minCornerDistance->setValue(subElem.attribute("MIN_CORNER_DISTANCE").toDouble());
+                mUi->minCornerDistance->setValue(subElem.attribute("MIN_CORNER_DISTANCE").toDouble());
             if (subElem.hasAttribute("MIN_DISTANCE_TO_BORDER"))
-                minDistanceToBorder->setValue(subElem.attribute("MIN_DISTANCE_TO_BORDER").toInt());
+                mUi->minDistanceToBorder->setValue(subElem.attribute("MIN_DISTANCE_TO_BORDER").toInt());
             if (subElem.hasAttribute("MIN_MARKER_DISTANCE"))
-                minMarkerDistance->setValue(subElem.attribute("MIN_MARKER_DISTANCE").toDouble());
+                mUi->minMarkerDistance->setValue(subElem.attribute("MIN_MARKER_DISTANCE").toDouble());
             if (subElem.hasAttribute("CORNER_REFINEMENT"))
-                doCornerRefinement->setChecked(subElem.attribute("CORNER_REFINEMENT").toInt());
-          if (subElem.hasAttribute("CORNER_REFINEMENT_WIN_SIZE"))
-                cornerRefinementWinSize->setValue(subElem.attribute("CORNER_REFINEMENT_WIN_SIZE").toInt());
+                mUi->doCornerRefinement->setChecked(subElem.attribute("CORNER_REFINEMENT").toInt());
+            if (subElem.hasAttribute("CORNER_REFINEMENT_WIN_SIZE"))
+                mUi->cornerRefinementWinSize->setValue(subElem.attribute("CORNER_REFINEMENT_WIN_SIZE").toInt());
             if (subElem.hasAttribute("CORNER_REFINEMENT_MAX_ITERATIONS"))
-                cornerRefinementMaxIterations->setValue(subElem.attribute("CORNER_REFINEMENT_MAX_ITERATIONS").toInt());
+                mUi->cornerRefinementMaxIterations->setValue(subElem.attribute("CORNER_REFINEMENT_MAX_ITERATIONS").toInt());
             if (subElem.hasAttribute("CORNER_REFINEMENT_MIN_ACCURACY"))
-                cornerRefinementMinAccuracy->setValue(subElem.attribute("CORNER_REFINEMENT_MIN_ACCURACY").toDouble());
+                mUi->cornerRefinementMinAccuracy->setValue(subElem.attribute("CORNER_REFINEMENT_MIN_ACCURACY").toDouble());
             if (subElem.hasAttribute("MARKER_BORDER_BITS"))
-                markerBorderBits->setValue(subElem.attribute("MARKER_BORDER_BITS").toInt());
+                mUi->markerBorderBits->setValue(subElem.attribute("MARKER_BORDER_BITS").toInt());
             if (subElem.hasAttribute("PERSPECTIVE_REMOVE_PIXEL_PER_CELL"))
-                perspectiveRemovePixelPerCell->setValue(subElem.attribute("PERSPECTIVE_REMOVE_PIXEL_PER_CELL").toInt());
+                mUi->perspectiveRemovePixelPerCell->setValue(subElem.attribute("PERSPECTIVE_REMOVE_PIXEL_PER_CELL").toInt());
             if (subElem.hasAttribute("PERSPECTIVE_REMOVE_IGNORED_MARGIN_PER_CELL"))
-                perspectiveRemoveIgnoredMarginPerCell->setValue(subElem.attribute("PERSPECTIVE_REMOVE_IGNORED_MARGIN_PER_CELL").toDouble());
+                mUi->perspectiveRemoveIgnoredMarginPerCell->setValue(subElem.attribute("PERSPECTIVE_REMOVE_IGNORED_MARGIN_PER_CELL").toDouble());
             if (subElem.hasAttribute("MAX_ERRONEOUS_BITS_IN_BORDER_RATE"))
-                maxErroneousBitsInBorderRate->setValue(subElem.attribute("MAX_ERRONEOUS_BITS_IN_BORDER_RATE").toDouble());
+                mUi->maxErroneousBitsInBorderRate->setValue(subElem.attribute("MAX_ERRONEOUS_BITS_IN_BORDER_RATE").toDouble());
             if (subElem.hasAttribute("MIN_OTSU_STD_DEV"))
-                minOtsuStdDev->setValue(subElem.attribute("MIN_OTSU_STD_DEV").toDouble());
+                mUi->minOtsuStdDev->setValue(subElem.attribute("MIN_OTSU_STD_DEV").toDouble());
             if (subElem.hasAttribute("ERROR_CORRECTION_RATE"))
-                errorCorrectionRate->setValue(subElem.attribute("ERROR_CORRECTION_RATE").toDouble());
+                mUi->errorCorrectionRate->setValue(subElem.attribute("ERROR_CORRECTION_RATE").toDouble());
             if (subElem.hasAttribute("SHOW_DETECTED_CANDIDATES"))
-                showDetectedCandidates->setCheckState(subElem.attribute("SHOW_DETECTED_CANDIDATES").toInt() ? Qt::Checked : Qt::Unchecked);
+                mUi->showDetectedCandidates->setCheckState(subElem.attribute("SHOW_DETECTED_CANDIDATES").toInt() ? Qt::Checked : Qt::Unchecked);
         }
     }
 }
 
-reco::ArucoCodeParams CodeMarkerWidget::packDetectorParams()
+reco::ArucoCodeParams packDetectorParams(const Ui::CodeMarker *ui)
 {
     reco::ArucoCodeParams params;
-    params.adaptiveThreshConstant = adaptiveThreshConstant->value();
-    params.adaptiveThreshWinSizeMax = adaptiveThreshWinSizeMax->value();
-    params.adaptiveThreshWinSizeMin = adaptiveThreshWinSizeMin->value();
-    params.adaptiveThreshWinSizeStep = adaptiveThreshWinSizeStep->value();
-    params.cornerRefinementMaxIterations = cornerRefinementMaxIterations->value();
-    params.cornerRefinementMinAccuracy = cornerRefinementMinAccuracy->value();
-    params.cornerRefinementWinSize = cornerRefinementWinSize->value();
-    params.doCornerRefinement = doCornerRefinement->isChecked();
-    params.errorCorrectionRate = errorCorrectionRate->value();
-    params.markerBorderBits = markerBorderBits->value();
-    params.maxErroneousBitsInBorderRate = maxErroneousBitsInBorderRate->value();
-    params.minDistanceToBorder = minDistanceToBorder->value();
-    params.minMarkerDistance = minMarkerDistance->value();
-    params.minMarkerPerimeter = minMarkerPerimeter->value();
-    params.minOtsuStdDev = minOtsuStdDev->value();
-    params.perspectiveRemoveIgnoredMarginPerCell = perspectiveRemoveIgnoredMarginPerCell->value();
-    params.perspectiveRemovePixelPerCell = perspectiveRemovePixelPerCell->value();
-    params.polygonalApproxAccuracyRate = polygonalApproxAccuracyRate->value();
+    params.setAdaptiveThreshConstant(ui->adaptiveThreshConstant->value());
+    params.setAdaptiveThreshWinSizeMax(ui->adaptiveThreshWinSizeMax->value());
+    params.setAdaptiveThreshWinSizeMin(ui->adaptiveThreshWinSizeMin->value());
+    params.setAdaptiveThreshWinSizeStep(ui->adaptiveThreshWinSizeStep->value());
+    params.setCornerRefinementMaxIterations(ui->cornerRefinementMaxIterations->value());
+    params.setCornerRefinementMinAccuracy(ui->cornerRefinementMinAccuracy->value());
+    params.setCornerRefinementWinSize(ui->cornerRefinementWinSize->value());
+    params.setDoCornerRefinement(ui->doCornerRefinement->isChecked());
+    params.setErrorCorrectionRate(ui->errorCorrectionRate->value());
+    params.setMarkerBorderBits(ui->markerBorderBits->value());
+    params.setMaxErroneousBitsInBorderRate(ui->maxErroneousBitsInBorderRate->value());
+    params.setMinDistanceToBorder(ui->minDistanceToBorder->value());
+    params.setMinMarkerDistance(ui->minMarkerDistance->value());
+    params.setMaxMarkerPerimeter(ui->maxMarkerPerimeter->value());
+    params.setMinMarkerPerimeter(ui->minMarkerPerimeter->value());
+    params.setMinOtsuStdDev(ui->minOtsuStdDev->value());
+    params.setPerspectiveRemoveIgnoredMarginPerCell(ui->perspectiveRemoveIgnoredMarginPerCell->value());
+    params.setPerspectiveRemovePixelPerCell(ui->perspectiveRemovePixelPerCell->value());
+    params.setPolygonalApproxAccuracyRate(ui->polygonalApproxAccuracyRate->value());
 
     return params;
 }
 
+bool CodeMarkerWidget::showDetectedCandidates()
+{
+    return mUi->showDetectedCandidates->isChecked();
+}
+
 void CodeMarkerWidget::on_showDetectedCandidates_stateChanged(int i)
 {
     mMainWindow->getCodeMarkerItem()->setVisible(i);
@@ -240,7 +259,7 @@ void CodeMarkerWidget::on_moreInfosButton_clicked()
 
 void CodeMarkerWidget::on_dictList_currentIndexChanged(int i)
 {
-    mCodeMarkerOpt.userChangedIndexOfMarkerDict(i);
+    mCodeMarkerOpt.setIndexOfMarkerDict(i);
     notifyChanged();
 }
 
@@ -255,34 +274,35 @@ void CodeMarkerWidget::notifyChanged()
 void CodeMarkerWidget::readDetectorParams()
 {
     auto params = mCodeMarkerOpt.getDetectorParams();
-    adaptiveThreshConstant->setValue(params.adaptiveThreshConstant);
-    adaptiveThreshWinSizeMax->setValue(params.adaptiveThreshWinSizeMax);
-    adaptiveThreshWinSizeMin->setValue(params.adaptiveThreshWinSizeMin);
-    adaptiveThreshWinSizeStep->setValue(params.adaptiveThreshWinSizeStep);
-    cornerRefinementMaxIterations->setValue(params.cornerRefinementMaxIterations);
-    cornerRefinementMinAccuracy->setValue(params.cornerRefinementMinAccuracy);
-    cornerRefinementWinSize->setValue(params.cornerRefinementWinSize);
-    doCornerRefinement->setChecked(params.doCornerRefinement);
-    errorCorrectionRate->setValue(params.errorCorrectionRate);
-    markerBorderBits->setValue(params.markerBorderBits);
-    maxErroneousBitsInBorderRate->setValue(params.maxErroneousBitsInBorderRate);
-    minDistanceToBorder->setValue(params.minDistanceToBorder);
-    minMarkerDistance->setValue(params.minMarkerDistance);
-    minMarkerPerimeter->setValue(params.minMarkerPerimeter);
-    minOtsuStdDev->setValue(params.minOtsuStdDev);
-    perspectiveRemoveIgnoredMarginPerCell->setValue(params.perspectiveRemoveIgnoredMarginPerCell);
-    perspectiveRemovePixelPerCell->setValue(params.perspectiveRemovePixelPerCell);
-    polygonalApproxAccuracyRate->setValue(params.polygonalApproxAccuracyRate);
+    mUi->adaptiveThreshConstant->setValue(params.getAdaptiveThreshConstant());
+    mUi->adaptiveThreshWinSizeMax->setValue(params.getAdaptiveThreshWinSizeMax());
+    mUi->adaptiveThreshWinSizeMin->setValue(params.getAdaptiveThreshWinSizeMin());
+    mUi->adaptiveThreshWinSizeStep->setValue(params.getAdaptiveThreshWinSizeStep());
+    mUi->cornerRefinementMaxIterations->setValue(params.getCornerRefinementMaxIterations());
+    mUi->cornerRefinementMinAccuracy->setValue(params.getCornerRefinementMinAccuracy());
+    mUi->cornerRefinementWinSize->setValue(params.getCornerRefinementWinSize());
+    mUi->doCornerRefinement->setChecked(params.getDoCornerRefinement());
+    mUi->errorCorrectionRate->setValue(params.getErrorCorrectionRate());
+    mUi->markerBorderBits->setValue(params.getMarkerBorderBits());
+    mUi->maxErroneousBitsInBorderRate->setValue(params.getMaxErroneousBitsInBorderRate());
+    mUi->minDistanceToBorder->setValue(params.getMinDistanceToBorder());
+    mUi->minMarkerDistance->setValue(params.getMinMarkerDistance());
+    mUi->maxMarkerPerimeter->setValue(params.getMaxMarkerPerimeter());
+    mUi->minMarkerPerimeter->setValue(params.getMinMarkerPerimeter());
+    mUi->minOtsuStdDev->setValue(params.getMinOtsuStdDev());
+    mUi->perspectiveRemoveIgnoredMarginPerCell->setValue(params.getPerspectiveRemoveIgnoredMarginPerCell());
+    mUi->perspectiveRemovePixelPerCell->setValue(params.getPerspectiveRemovePixelPerCell());
+    mUi->polygonalApproxAccuracyRate->setValue(params.getPolygonalApproxAccuracyRate());
 }
 
 void CodeMarkerWidget::readDictListIndex()
 {
-    dictList->setCurrentIndex(mCodeMarkerOpt.getIndexOfMarkerDict());
+    mUi->dictList->setCurrentIndex(mCodeMarkerOpt.getIndexOfMarkerDict());
 }
 
 void CodeMarkerWidget::sendDetectorParams(reco::ArucoCodeParams params)
 {
-    mCodeMarkerOpt.userChangedDetectorParams(params);
+    mCodeMarkerOpt.setDetectorParams(params);
 }
 
 #include "moc_codeMarkerWidget.cpp"
diff --git a/src/petrack.cpp b/src/petrack.cpp
index afd58b41ca2555145c8abee63a761d2bae7dcb1b..00cbb5f423bfa7784c09e1ff7b0eab641d09bceb 100644
--- a/src/petrack.cpp
+++ b/src/petrack.cpp
@@ -127,7 +127,7 @@ Petrack::Petrack() : mAuthors(IO::readAuthors(QCoreApplication::applicationDirPa
     mColorMarkerWidget->setWindowFlags(Qt::Window);
     mColorMarkerWidget->setWindowTitle("Color marker parameter");
 
-    mCodeMarkerWidget = new CodeMarkerWidget(this, mReco.getCodeMarkerOptions());
+    mCodeMarkerWidget = new CodeMarkerWidget(this, mReco.getCodeMarkerOptions(), nullptr);
     mCodeMarkerWidget->setWindowFlags(Qt::Window);
     mCodeMarkerWidget->setWindowTitle("Code marker parameter");
 
@@ -203,7 +203,7 @@ Petrack::Petrack() : mAuthors(IO::readAuthors(QCoreApplication::applicationDirPa
     mColorMarkerItem->setVisible(false);
     //---------------------------
 
-    mCodeMarkerItem = new CodeMarkerItem(this);
+    mCodeMarkerItem = new CodeMarkerItem(this, mReco.getCodeMarkerOptions());
     mCodeMarkerItem->setZValue(2);// groesser heisst weiter oben
     mCodeMarkerItem->setVisible(false);
     //---------------------------
@@ -271,8 +271,8 @@ Petrack::Petrack() : mAuthors(IO::readAuthors(QCoreApplication::applicationDirPa
     createStatusBar();
 
     // TODO delete once we get Options to be value only (i.e. no Pointer/Ref anymore)
-    mReco.getCodeMarkerOptions().controlWidget = mControlWidget;
-    mReco.getCodeMarkerOptions().codeMarkerItem = mCodeMarkerItem;
+    mReco.getCodeMarkerOptions().setControlWidget(mControlWidget);
+    mReco.getCodeMarkerOptions().setCodeMarkerItem(mCodeMarkerItem);
 
     mSeqFileName = QDir::currentPath(); //fuer allerersten Aufruf des Programms
     readSettings();
diff --git a/src/recognition.cpp b/src/recognition.cpp
index 023f3d47ce3e613f7de9b0f48b1c5b5c3c67f06a..fb448346eae3ddd4ce575fb09960f899eca29779 100644
--- a/src/recognition.cpp
+++ b/src/recognition.cpp
@@ -582,7 +582,7 @@ void detail::refineWithAruco(std::vector<ColorBlob> &blobs, const cv::Mat& img,
             continue;
         // TODO: Use Reference to actual codeMarkerOptions in MulticolorMarkerOptions
         // NOTE: For now, add as parameter of findMulticolorMarker
-        codeOpt.offsetCropRect2Roi = offsetCropRect2Roi;
+        codeOpt.setOffsetCropRect2Roi(offsetCropRect2Roi);
         findCodeMarker(subImg, crossList, options.method, codeOpt);
 
         // The next three statements each:
@@ -636,7 +636,7 @@ void detail::refineWithAruco(std::vector<ColorBlob> &blobs, const cv::Mat& img,
             crossList.back() = crossList.back() + (Vec2F(cropRect.x, cropRect.y) + moveDir);
         }
     }
-    codeOpt.offsetCropRect2Roi = Vec2F{0,0};
+    codeOpt.setOffsetCropRect2Roi(Vec2F{0,0});
 }
 
 /**
@@ -864,12 +864,13 @@ void findColorMarker(cv::Mat &img, QList<TrackPoint> &crossList, Control *contro
  */
 void detail::findCodeMarker(cv::Mat &img, QList<TrackPoint> &crossList, RecognitionMethod recoMethod, const CodeMarkerOptions& opt)
 {
-    CodeMarkerItem *codeMarkerItem = opt.codeMarkerItem;
-    const auto& par = opt.detectorParams;
+    CodeMarkerItem *codeMarkerItem = opt.getCodeMarkerItem();
+    Control *controlWidget = opt.getControlWidget();
+    const auto& par = opt.getDetectorParams();
 
-    cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(opt.indexOfMarkerDict));
+    cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(opt.getIndexOfMarkerDict()));
 
-    if (opt.indexOfMarkerDict == 17) //for usage of DICT_mip_36h12 as it is not predifined in opencv
+    if (opt.getIndexOfMarkerDict() == 17) //for usage of DICT_mip_36h12 as it is not predifined in opencv
     {
         dictionary = detail::getDictMip36h12();
     }
@@ -878,11 +879,11 @@ void detail::findCodeMarker(cv::Mat &img, QList<TrackPoint> &crossList, Recognit
 
     double minMarkerPerimeterRate = 0.03, maxMarkerPerimeterRate = 4, minCornerDistanceRate = 0.05, minMarkerDistanceRate = 0.05;
 
-    Petrack *mainWindow = opt.controlWidget->getMainWindow();
+    Petrack *mainWindow = controlWidget->getMainWindow();
 
     int bS = mainWindow->getImageBorderSize();
 
-    if (opt.controlWidget->getCalibCoordDimension() == 0) // 3D
+    if (controlWidget->getCalibCoordDimension() == 0) // 3D
     {
         if (recoMethod == RecognitionMethod::Code)  // for usage of codemarker with CodeMarker-function (-> without MulticolorMarker)
         {
@@ -890,18 +891,18 @@ void detail::findCodeMarker(cv::Mat &img, QList<TrackPoint> &crossList, Recognit
                        myRound(mainWindow->getRecoRoiItem()->rect().y()),
                        myRound(mainWindow->getRecoRoiItem()->rect().width()),
                        myRound(mainWindow->getRecoRoiItem()->rect().height()));
-            QPointF p1 = mainWindow->getImageItem()->getCmPerPixel(rect.x(),rect.y(),opt.controlWidget->mapDefaultHeight->value()),
-                    p2 = mainWindow->getImageItem()->getCmPerPixel(rect.x()+rect.width(),rect.y(),opt.controlWidget->mapDefaultHeight->value()),
-                    p3 = mainWindow->getImageItem()->getCmPerPixel(rect.x(),rect.y()+rect.height(),opt.controlWidget->mapDefaultHeight->value()),
-                    p4 = mainWindow->getImageItem()->getCmPerPixel(rect.x()+rect.width(),rect.y()+rect.height(),opt.controlWidget->mapDefaultHeight->value());
+            QPointF p1 = mainWindow->getImageItem()->getCmPerPixel(rect.x(),rect.y(),controlWidget->mapDefaultHeight->value()),
+                    p2 = mainWindow->getImageItem()->getCmPerPixel(rect.x()+rect.width(),rect.y(),controlWidget->mapDefaultHeight->value()),
+                    p3 = mainWindow->getImageItem()->getCmPerPixel(rect.x(),rect.y()+rect.height(),controlWidget->mapDefaultHeight->value()),
+                    p4 = mainWindow->getImageItem()->getCmPerPixel(rect.x()+rect.width(),rect.y()+rect.height(),controlWidget->mapDefaultHeight->value());
 
             double cmPerPixel_min = std::min(std::min(std::min(p1.x(), p1.y()), std::min(p2.x(), p2.y())),
                                              std::min(std::min(p3.x(), p3.y()), std::min(p4.x(), p4.y())));
             double cmPerPixel_max = std::max(std::max(std::max(p1.x(), p1.y()), std::max(p2.x(), p2.y())),
                                              std::max(std::max(p3.x(), p3.y()), std::max(p4.x(), p4.y())));
 
-            minMarkerPerimeterRate = (par.minMarkerPerimeter*4./cmPerPixel_max)/std::max(rect.width(),rect.height());
-            maxMarkerPerimeterRate = (par.maxMarkerPerimeter*4./cmPerPixel_min)/std::max(rect.width(),rect.height());
+            minMarkerPerimeterRate = (par.getMinMarkerPerimeter()*4./cmPerPixel_max)/std::max(rect.width(),rect.height());
+            maxMarkerPerimeterRate = (par.getMaxMarkerPerimeter()*4./cmPerPixel_min)/std::max(rect.width(),rect.height());
         } else if (recoMethod == RecognitionMethod::MultiColor)   // for usage of codemarker with MulticolorMarker
         {
             QRect rect(0,0, img.rows, img.cols);
@@ -911,44 +912,44 @@ void detail::findCodeMarker(cv::Mat &img, QList<TrackPoint> &crossList, Recognit
             maxMarkerPerimeterRate = 4.;
         }
 
-        minCornerDistanceRate = par.minCornerDistance;
-        minMarkerDistanceRate = par.minMarkerDistance;
+        minCornerDistanceRate = par.getMinCornerDistance();
+        minMarkerDistanceRate = par.getMinMarkerDistance();
 
     }
     else // 2D
     {
         double cmPerPixel = mainWindow->getImageItem()->getCmPerPixel();
-        minMarkerPerimeterRate = (par.minMarkerPerimeter*4/cmPerPixel)/std::max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS);
-        maxMarkerPerimeterRate = (par.maxMarkerPerimeter*4/cmPerPixel)/std::max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS);
+        minMarkerPerimeterRate = (par.getMinMarkerPerimeter()*4/cmPerPixel)/std::max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS);
+        maxMarkerPerimeterRate = (par.getMaxMarkerPerimeter()*4/cmPerPixel)/std::max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS);
 
-        minCornerDistanceRate = par.minCornerDistance;
-        minMarkerDistanceRate = par.minMarkerDistance;
+        minCornerDistanceRate = par.getMinCornerDistance();
+        minMarkerDistanceRate = par.getMinMarkerDistance();
     }
 
-    detectorParams->adaptiveThreshWinSizeMin              = par.adaptiveThreshWinSizeMin;
-    detectorParams->adaptiveThreshWinSizeMax              = par.adaptiveThreshWinSizeMax;
-    detectorParams->adaptiveThreshWinSizeStep             = par.adaptiveThreshWinSizeStep;
-    detectorParams->adaptiveThreshConstant                = par.adaptiveThreshConstant;
+    detectorParams->adaptiveThreshWinSizeMin              = par.getAdaptiveThreshWinSizeMin();
+    detectorParams->adaptiveThreshWinSizeMax              = par.getAdaptiveThreshWinSizeMax();
+    detectorParams->adaptiveThreshWinSizeStep             = par.getAdaptiveThreshWinSizeStep();
+    detectorParams->adaptiveThreshConstant                = par.getAdaptiveThreshConstant();
     detectorParams->minMarkerPerimeterRate                = minMarkerPerimeterRate;
     detectorParams->maxMarkerPerimeterRate                = maxMarkerPerimeterRate;
-    detectorParams->polygonalApproxAccuracyRate           = par.polygonalApproxAccuracyRate;
+    detectorParams->polygonalApproxAccuracyRate           = par.getPolygonalApproxAccuracyRate();
     detectorParams->minCornerDistanceRate                 = minCornerDistanceRate;
-    detectorParams->minDistanceToBorder                   = par.minDistanceToBorder;
+    detectorParams->minDistanceToBorder                   = par.getMinDistanceToBorder();
     detectorParams->minMarkerDistanceRate                 = minMarkerDistanceRate;
     // No refinement is default value
     // TODO Check if this is the best MEthod for our usecase
-    if(par.doCornerRefinement){
+    if(par.getDoCornerRefinement()){
         detectorParams->cornerRefinementMethod            = cv::aruco::CornerRefineMethod::CORNER_REFINE_SUBPIX;
     }
-    detectorParams->cornerRefinementWinSize               = par.cornerRefinementWinSize;
-    detectorParams->cornerRefinementMaxIterations         = par.cornerRefinementMaxIterations;
-    detectorParams->cornerRefinementMinAccuracy           = par.cornerRefinementMinAccuracy;
-    detectorParams->markerBorderBits                      = par.markerBorderBits;
-    detectorParams->perspectiveRemovePixelPerCell         = par.perspectiveRemovePixelPerCell;
-    detectorParams->perspectiveRemoveIgnoredMarginPerCell = par.perspectiveRemoveIgnoredMarginPerCell;
-    detectorParams->maxErroneousBitsInBorderRate          = par.maxErroneousBitsInBorderRate;
-    detectorParams->minOtsuStdDev                         = par.minOtsuStdDev;
-    detectorParams->errorCorrectionRate                   = par.errorCorrectionRate;
+    detectorParams->cornerRefinementWinSize               = par.getCornerRefinementWinSize();
+    detectorParams->cornerRefinementMaxIterations         = par.getCornerRefinementMaxIterations();
+    detectorParams->cornerRefinementMinAccuracy           = par.getCornerRefinementMinAccuracy();
+    detectorParams->markerBorderBits                      = par.getMarkerBorderBits();
+    detectorParams->perspectiveRemovePixelPerCell         = par.getPerspectiveRemovePixelPerCell();
+    detectorParams->perspectiveRemoveIgnoredMarginPerCell = par.getPerspectiveRemoveIgnoredMarginPerCell();
+    detectorParams->maxErroneousBitsInBorderRate          = par.getMaxErroneousBitsInBorderRate();
+    detectorParams->minOtsuStdDev                         = par.getMinOtsuStdDev();
+    detectorParams->errorCorrectionRate                   = par.getErrorCorrectionRate();
 
     std::vector<int> ids;
     std::vector<std::vector<cv::Point2f> > corners, rejected;
@@ -958,8 +959,8 @@ void detail::findCodeMarker(cv::Mat &img, QList<TrackPoint> &crossList, Recognit
 
     cv::aruco::detectMarkers(img, dictionary, corners, ids, detectorParams, rejected);
 
-    codeMarkerItem->addDetectedMarkers(corners,ids, opt.offsetCropRect2Roi);
-    codeMarkerItem->addRejectedMarkers(rejected, opt.offsetCropRect2Roi);
+    codeMarkerItem->addDetectedMarkers(corners,ids, opt.getOffsetCropRect2Roi());
+    codeMarkerItem->addRejectedMarkers(rejected, opt.getOffsetCropRect2Roi());
 
     // detected code markers
     for(size_t i = 0; i<ids.size(); i++)
@@ -1149,7 +1150,17 @@ QList<TrackPoint> Recognizer::getMarkerPos(cv::Mat &img, QRect &roi, Control *co
     return crossList;
 }
 
-void CodeMarkerOptions::userChangedDetectorParams(ArucoCodeParams params)
+const Vec2F &CodeMarkerOptions::getOffsetCropRect2Roi() const
+{
+    return offsetCropRect2Roi;
+}
+
+void CodeMarkerOptions::setOffsetCropRect2Roi(const Vec2F &newOffsetCropRect2Roi)
+{
+    offsetCropRect2Roi = newOffsetCropRect2Roi;
+}
+
+void CodeMarkerOptions::setDetectorParams(ArucoCodeParams params)
 {
     if(params != detectorParams){
         detectorParams = params;
@@ -1157,7 +1168,7 @@ void CodeMarkerOptions::userChangedDetectorParams(ArucoCodeParams params)
     }
 }
 
-void CodeMarkerOptions::userChangedIndexOfMarkerDict(int idx)
+void CodeMarkerOptions::setIndexOfMarkerDict(int idx)
 {
     if(idx != indexOfMarkerDict){
         indexOfMarkerDict = idx;
@@ -1198,4 +1209,250 @@ cv::Ptr<cv::aruco::Dictionary> detail::getDictMip36h12()
 
     return dictionary;
 }
+
+double ArucoCodeParams::getMaxMarkerPerimeter() const
+{
+    return maxMarkerPerimeter;
+}
+
+void ArucoCodeParams::setMaxMarkerPerimeter(double newMaxMarkerPerimeter)
+{
+    if(newMaxMarkerPerimeter < minMarkerPerimeter){
+        throw std::invalid_argument("Max perimeter length needs to be at least as big as min perimiter length");
+    }
+    maxMarkerPerimeter = newMaxMarkerPerimeter;
+}
+
+double ArucoCodeParams::getMinCornerDistance() const
+{
+    return minCornerDistance;
+}
+
+void ArucoCodeParams::setMinCornerDistance(double newMinCornerDistance)
+{
+    if(newMinCornerDistance < 0){
+        throw std::invalid_argument("Min corner distance cannot be negative");
+    }
+    minCornerDistance = newMinCornerDistance;
+}
+
+double ArucoCodeParams::getMinMarkerDistance() const
+{
+    return minMarkerDistance;
+}
+
+void ArucoCodeParams::setMinMarkerDistance(double newMinMarkerDistance)
+{
+    minMarkerDistance = newMinMarkerDistance;
+}
+
+int ArucoCodeParams::getAdaptiveThreshWinSizeMin() const
+{
+    return adaptiveThreshWinSizeMin;
+}
+
+void ArucoCodeParams::setAdaptiveThreshWinSizeMin(int newAdaptiveThreshWinSizeMin)
+{
+    if(newAdaptiveThreshWinSizeMin > adaptiveThreshWinSizeMax){
+        throw std::invalid_argument("Min adaptiveTreshWinSize needs to be at most as large as max");
+    }
+    if(newAdaptiveThreshWinSizeMin < 3){
+        throw std::invalid_argument("Min winsize must be at least 3");
+    }
+    adaptiveThreshWinSizeMin = newAdaptiveThreshWinSizeMin;
+}
+
+int ArucoCodeParams::getAdaptiveThreshWinSizeMax() const
+{
+    return adaptiveThreshWinSizeMax;
+}
+
+void ArucoCodeParams::setAdaptiveThreshWinSizeMax(int newAdaptiveThreshWinSizeMax)
+{
+    if(newAdaptiveThreshWinSizeMax < adaptiveThreshWinSizeMin){
+        throw std::invalid_argument("Max adaptiveThreshWinSize needs to be at least as large as the minimum");
+    }
+    if(newAdaptiveThreshWinSizeMax < 3){
+        throw std::invalid_argument("Max adaptive winsize needs to be at lest 3");
+    }
+    adaptiveThreshWinSizeMax = newAdaptiveThreshWinSizeMax;
+}
+
+int ArucoCodeParams::getAdaptiveThreshWinSizeStep() const
+{
+    return adaptiveThreshWinSizeStep;
+}
+
+void ArucoCodeParams::setAdaptiveThreshWinSizeStep(int newAdaptiveThreshWinSizeStep)
+{
+    if(newAdaptiveThreshWinSizeStep <= 0){
+        throw std::invalid_argument("Winsize step needs to be larger than 0");
+    }
+    adaptiveThreshWinSizeStep = newAdaptiveThreshWinSizeStep;
+}
+
+int ArucoCodeParams::getAdaptiveThreshConstant() const
+{
+    return adaptiveThreshConstant;
+}
+
+void ArucoCodeParams::setAdaptiveThreshConstant(int newAdaptiveThreshConstant)
+{
+    adaptiveThreshConstant = newAdaptiveThreshConstant;
+}
+
+double ArucoCodeParams::getPolygonalApproxAccuracyRate() const
+{
+    return polygonalApproxAccuracyRate;
+}
+
+void ArucoCodeParams::setPolygonalApproxAccuracyRate(double newPolygonalApproxAccuracyRate)
+{
+    polygonalApproxAccuracyRate = newPolygonalApproxAccuracyRate;
+}
+
+int ArucoCodeParams::getMinDistanceToBorder() const
+{
+    return minDistanceToBorder;
+}
+
+void ArucoCodeParams::setMinDistanceToBorder(int newMinDistanceToBorder)
+{
+    if(newMinDistanceToBorder < 0){
+        throw std::invalid_argument("Min distance to border cannot be negative");
+    }
+    minDistanceToBorder = newMinDistanceToBorder;
+}
+
+bool ArucoCodeParams::getDoCornerRefinement() const
+{
+    return doCornerRefinement;
+}
+
+void ArucoCodeParams::setDoCornerRefinement(bool newDoCornerRefinement)
+{
+    doCornerRefinement = newDoCornerRefinement;
+}
+
+int ArucoCodeParams::getCornerRefinementWinSize() const
+{
+    return cornerRefinementWinSize;
+}
+
+void ArucoCodeParams::setCornerRefinementWinSize(int newCornerRefinementWinSize)
+{
+    if(newCornerRefinementWinSize < 1){
+        throw std::invalid_argument("Winsize needs to be at least 1");
+    }
+    cornerRefinementWinSize = newCornerRefinementWinSize;
+}
+
+int ArucoCodeParams::getCornerRefinementMaxIterations() const
+{
+    return cornerRefinementMaxIterations;
+}
+
+void ArucoCodeParams::setCornerRefinementMaxIterations(int newCornerRefinementMaxIterations)
+{
+    if(newCornerRefinementMaxIterations < 1){
+        throw std::invalid_argument("Max iterations needs to be at least 1");
+    }
+    cornerRefinementMaxIterations = newCornerRefinementMaxIterations;
+}
+
+double ArucoCodeParams::getCornerRefinementMinAccuracy() const
+{
+    return cornerRefinementMinAccuracy;
+}
+
+void ArucoCodeParams::setCornerRefinementMinAccuracy(double newCornerRefinementMinAccuracy)
+{
+    if(newCornerRefinementMinAccuracy <= 0){
+        throw std::invalid_argument("Min accuracy needs to be larger than 0");
+    }
+    cornerRefinementMinAccuracy = newCornerRefinementMinAccuracy;
+}
+
+int ArucoCodeParams::getMarkerBorderBits() const
+{
+    return markerBorderBits;
+}
+
+void ArucoCodeParams::setMarkerBorderBits(int newMarkerBorderBits)
+{
+    if(newMarkerBorderBits < 1){
+        throw std::invalid_argument("Marker Borderbits needs to be at least 1");
+    }
+    markerBorderBits = newMarkerBorderBits;
+}
+
+int ArucoCodeParams::getPerspectiveRemovePixelPerCell() const
+{
+    return perspectiveRemovePixelPerCell;
+}
+
+void ArucoCodeParams::setPerspectiveRemovePixelPerCell(int newPerspectiveRemovePixelPerCell)
+{
+    perspectiveRemovePixelPerCell = newPerspectiveRemovePixelPerCell;
+}
+
+double ArucoCodeParams::getPerspectiveRemoveIgnoredMarginPerCell() const
+{
+    return perspectiveRemoveIgnoredMarginPerCell;
+}
+
+void ArucoCodeParams::setPerspectiveRemoveIgnoredMarginPerCell(double newPerspectiveRemoveIgnoredMarginPerCell)
+{
+    perspectiveRemoveIgnoredMarginPerCell = newPerspectiveRemoveIgnoredMarginPerCell;
+}
+
+double ArucoCodeParams::getMaxErroneousBitsInBorderRate() const
+{
+    return maxErroneousBitsInBorderRate;
+}
+
+void ArucoCodeParams::setMaxErroneousBitsInBorderRate(double newMaxErroneousBitsInBorderRate)
+{
+    maxErroneousBitsInBorderRate = newMaxErroneousBitsInBorderRate;
+}
+
+double ArucoCodeParams::getMinOtsuStdDev() const
+{
+    return minOtsuStdDev;
+}
+
+void ArucoCodeParams::setMinOtsuStdDev(double newMinOtsuStdDev)
+{
+    if(newMinOtsuStdDev <= 0){
+        throw std::invalid_argument("Min Otsu stddev needs to be larger than 0");
+    }
+    minOtsuStdDev = newMinOtsuStdDev;
+}
+
+double ArucoCodeParams::getErrorCorrectionRate() const
+{
+    return errorCorrectionRate;
+}
+
+void ArucoCodeParams::setErrorCorrectionRate(double newErrorCorrectionRate)
+{
+    errorCorrectionRate = newErrorCorrectionRate;
+}
+
+double ArucoCodeParams::getMinMarkerPerimeter() const
+{
+    return minMarkerPerimeter;
+}
+
+void ArucoCodeParams::setMinMarkerPerimeter(double newMinMarkerPerimeter)
+{
+    if(newMinMarkerPerimeter > maxMarkerPerimeter){
+        throw std::invalid_argument("Min marker perimeter needs to be at most as large as the max perimeter.");
+    }
+    if(newMinMarkerPerimeter <= 0){
+        throw std::invalid_argument("Min marker perimeter must be larger than 0");
+    }
+    minMarkerPerimeter = newMinMarkerPerimeter;
+}
+
 } // namespace reco
diff --git a/tests/unit_test/CMakeLists.txt b/tests/unit_test/CMakeLists.txt
index 542fa407076194fa0102718c7094fbb5a9f29844..8b9088c44cb7bad704f5b1b06852408f90072d09 100644
--- a/tests/unit_test/CMakeLists.txt
+++ b/tests/unit_test/CMakeLists.txt
@@ -8,6 +8,7 @@ target_sources(petrack_tests PRIVATE
     tst_SkeletonTree.cpp
     tst_moCapController.cpp
     tst_recognition.cpp
+    tst_codeMarkerWidget.cpp
 )
 
 
diff --git a/tests/unit_test/main.cpp b/tests/unit_test/main.cpp
index db7f294c2596d9502b3314e006c6d7dfe6b3d795..ff63ecda9a346b96591ebebee16a78d94bc52fc7 100644
--- a/tests/unit_test/main.cpp
+++ b/tests/unit_test/main.cpp
@@ -23,13 +23,35 @@
 
 #include <QApplication>
 #include <QtTest>
+#include <vector>
 
 int main( int argc, char* argv[] )
 {
-    QApplication a(argc, argv);
+    // always start unit tests as offscreen, so PMessageBox-es only log
+    bool platformAlreadyGiven = false;
+    for(int i = 0; i < argc; ++i){
+        if(qstrcmp("-platform", argv[i]) == 0){
+            platformAlreadyGiven = true;
+        }
+    }
+    int argc2;
+    char **argv2;
+    auto args = std::vector<const char*>(argv, argv+argc);
+    if(!platformAlreadyGiven)
+    {
+        args.push_back("-platform");
+        args.push_back("offscreen");
+        argc2 = argc+2;
+        argv2 = const_cast<char **>(args.data());
+    }else{
+        argc2 = argc;
+        argv2 = argv;
+    }
+
+    QApplication a(argc2, argv2);
 
     QTEST_SET_MAIN_SOURCE_PATH
-    const int result = Catch::Session().run( argc, argv );
+    const int result = Catch::Session().run( argc2, argv2 );
 
     return ( result < 0xff ? result : 0xff );
 }
diff --git a/tests/unit_test/tst_codeMarkerWidget.cpp b/tests/unit_test/tst_codeMarkerWidget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4db371b653611a92f8a72dc9594e7dc99bcfc35f
--- /dev/null
+++ b/tests/unit_test/tst_codeMarkerWidget.cpp
@@ -0,0 +1,218 @@
+/*
+ * PeTrack - Software for tracking pedestrians movement in videos
+ * Copyright (C) 2010-2020 Forschungszentrum Jülich GmbH,
+ * Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
+ * Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <catch2/catch.hpp>
+
+#include "recognition.h"
+#include "codeMarkerWidget.h"
+#include "ui_codeMarker.h"
+
+SCENARIO("The user opens the CodeMarkerWidget", "[ui]")
+{
+    // create the dialog
+    Petrack petrack;
+    reco::CodeMarkerOptions options;
+    Ui::CodeMarker *view = new Ui::CodeMarker();
+    CodeMarkerWidget widget {&petrack, options, view};
+
+    THEN("The view shows the correct values")
+    {
+        const auto& params = options.getDetectorParams();
+        const auto displayedParams = packDetectorParams(view);
+        REQUIRE(params == displayedParams);
+    }
+
+    GIVEN("The user changes an AruCo Parameter")
+    {
+        // since the params are handled the same, not all are
+        // explicitly tested here
+        constexpr double newMinMarkerDistance = 0;
+        view->minMarkerDistance->setValue(newMinMarkerDistance); // <- user input
+
+        const int newListIndex = view->dictList->currentIndex() + 1;
+        view->dictList->setCurrentIndex(newListIndex); // <- user input
+
+        THEN("The options-object is updated")
+        {
+            REQUIRE(options.getDetectorParams().getMinMarkerDistance() == Approx(newMinMarkerDistance));
+            REQUIRE(options.getIndexOfMarkerDict() == newListIndex);
+        }
+    }
+
+    GIVEN("The AruCo Parameters changed via an other way")
+    {
+        reco::ArucoCodeParams newData;
+        newData.setMinMarkerDistance(10);
+        options.setDetectorParams(newData);
+        constexpr int newIndex = 2;
+        options.setIndexOfMarkerDict(newIndex);
+
+        THEN("The view is updated")
+        {
+            REQUIRE(packDetectorParams(view) == newData);
+            REQUIRE(view->dictList->currentIndex() == newIndex);
+        }
+    }
+
+    GIVEN("Minimum larger than maximum")
+    {
+        auto oldValues = packDetectorParams(view);
+        view->adaptiveThreshWinSizeMin->setValue(view->adaptiveThreshWinSizeMax->value() + 1);
+        view->minMarkerPerimeter->setValue(view->maxMarkerPerimeter->value() + 1);
+        THEN("It is not changed")
+        {
+            REQUIRE(view->adaptiveThreshWinSizeMin->value() == oldValues.getAdaptiveThreshWinSizeMin());
+            REQUIRE(view->minMarkerPerimeter->value() == Approx(oldValues.getMinMarkerPerimeter()));
+        }
+    }
+
+    GIVEN("Maximum lower than minimum")
+    {
+        auto oldValues = packDetectorParams(view);
+        // Since min already has minimal value this isn't properly tested with the default min
+        view->adaptiveThreshWinSizeMin->setValue(10);
+        view->adaptiveThreshWinSizeMax->setValue(view->adaptiveThreshWinSizeMin->value()-1);
+        //view->minMarkerPerimeter->
+        view->maxMarkerPerimeter->setValue(view->minMarkerPerimeter->value()-1);
+        THEN("It is not changed")
+        {
+            REQUIRE(view->adaptiveThreshWinSizeMax->value() == oldValues.getAdaptiveThreshWinSizeMax());
+            REQUIRE(view->maxMarkerPerimeter->value() == Approx(oldValues.getMaxMarkerPerimeter()));
+        }
+    }
+
+    GIVEN("A cornerRefinementWinSize less than 1")
+    {
+        view->cornerRefinementWinSize->setValue(-2);
+        THEN("The value gets set to 1")
+        {
+            REQUIRE(view->cornerRefinementWinSize->value() == 1);
+        }
+    }
+
+    GIVEN("A cornerRefinementMaxIterations less than 1")
+    {
+        view->cornerRefinementMaxIterations->setValue(0);
+        THEN("The value gets set to 1")
+        {
+            REQUIRE(view->cornerRefinementMaxIterations->value() == 1);
+        }
+    }
+
+    GIVEN("A cornerRefinementMinAccuracy less than or equal to 0")
+    {
+        view->cornerRefinementMinAccuracy->setValue(-3);
+        THEN("It is set to 0.01")
+        {
+            REQUIRE(view->cornerRefinementMinAccuracy->value() == Approx(0.01));
+        }
+    }
+
+    GIVEN("markerBorderBits less than 1")
+    {
+        view->markerBorderBits->setValue(0);
+        THEN("The value is set to 1")
+        {
+            REQUIRE(view->markerBorderBits->value() == 1);
+        }
+    }
+
+    GIVEN("minStdDevOtsu less than or equal to 0")
+    {
+        view->minOtsuStdDev->setValue(-2);
+        THEN("The value is set to 0.01")
+        {
+            REQUIRE(view->minOtsuStdDev->value() == Approx(0.01));
+        }
+    }
+
+    GIVEN("adaptiveThreshSizeMin less than 3")
+    {
+        view->adaptiveThreshWinSizeMin->setValue(1);
+        THEN("The value is set to 3"){
+            REQUIRE(view->adaptiveThreshWinSizeMin->value() == 3);
+        }
+    }
+
+    GIVEN("adaptiveThreshSizeMax less than 3")
+    {
+        view->adaptiveThreshWinSizeMax->setValue(1);
+        THEN("The value is set to 3")
+        {
+            REQUIRE(view->adaptiveThreshWinSizeMax->value() == 3);
+        }
+    }
+
+    GIVEN("adaptiveThreshWinSizeStep less than or equal to 0")
+    {
+        view->adaptiveThreshWinSizeStep->setValue(0);
+        THEN("The value is set to 1")
+        {
+            REQUIRE(view->adaptiveThreshWinSizeStep->value() == 1);
+        }
+    }
+
+    GIVEN("minMarkerPerimeter less than or equal to 0")
+    {
+        view->minMarkerPerimeter->setValue(0);
+        THEN("The value is set to 0.1")
+        {
+            REQUIRE(view->minMarkerPerimeter->value() == Approx(0.1));
+        }
+    }
+
+    GIVEN("maxMarkerPerimeter less than or equal to 0")
+    {
+        auto oldVal = view->maxMarkerPerimeter->value();
+        view->minMarkerPerimeter->setValue(0); // since max cannot be lower than min
+        view->maxMarkerPerimeter->setValue(0);
+        THEN("The value is not changed")
+        {
+            REQUIRE(view->maxMarkerPerimeter->value() == Approx(oldVal));
+        }
+    }
+
+    GIVEN("cornerRefinementMinAccuracy less than or equal to 0")
+    {
+        view->cornerRefinementMinAccuracy->setValue(0);
+        THEN("The value is set to 0.01")
+        {
+            REQUIRE(view->cornerRefinementMinAccuracy->value() == Approx(0.01));
+        }
+    }
+
+    GIVEN("minCornerDistance less than 0")
+    {
+        view->minCornerDistance->setValue(-1);
+        THEN("The value is set to 1")
+        {
+            REQUIRE(view->minCornerDistance->value() == Approx(0));
+        }
+    }
+
+    GIVEN("minDistanceToBorder less than 0")
+    {
+        view->minDistanceToBorder->setValue(-2);
+        THEN("The value is set to 0")
+        {
+            REQUIRE(view->minDistanceToBorder->value() == 0);
+        }
+    }
+}
diff --git a/tests/unit_test/tst_recognition.cpp b/tests/unit_test/tst_recognition.cpp
index 77b603e01ed78a6ab2b1ec9db161fc447c1596e1..758c1cb4b2ac3faabdba6b272b45e8a828612909 100644
--- a/tests/unit_test/tst_recognition.cpp
+++ b/tests/unit_test/tst_recognition.cpp
@@ -20,9 +20,13 @@
 
 #include <catch2/catch.hpp>
 
+#include <QSignalSpy>
+
 #include "recognition.h"
 #include "petrack.h"
 
+using namespace reco;
+
 TEST_CASE("src/recognition", "[recognition]")
 {
     SECTION("RecognitionMarker to int")
@@ -37,3 +41,202 @@ TEST_CASE("src/recognition", "[recognition]")
         REQUIRE(static_cast<int>(reco::RecognitionMethod::Code) == 6);
     }
 }
+
+SCENARIO("I change Aruco parameters (via UI)"){
+    CodeMarkerOptions options;
+
+    GIVEN("I change the detector params"){
+        QSignalSpy spy{&options, &CodeMarkerOptions::detectorParamsChanged};
+        ArucoCodeParams params;
+        params.setAdaptiveThreshConstant(20);
+        options.setDetectorParams(params);
+        THEN("A corresponding change signal was emitted"){
+            REQUIRE(spy.count() == 1);
+        }
+    }
+
+    GIVEN("I change the index of the marker dict"){
+        QSignalSpy spy{&options, &CodeMarkerOptions::indexOfMarkerDictChanged};
+        const int newIndex = options.getIndexOfMarkerDict() + 1;
+        options.setIndexOfMarkerDict(newIndex);
+        THEN("A corresponding change signal was emitted"){
+            REQUIRE(spy.count() == 1);
+        }
+    }
+}
+
+SCENARIO("I use the setter/getter of ArucoCodeParams")
+{
+    ArucoCodeParams params;
+    GIVEN("I set a minimum larger than the maximum")
+    {
+        const int newAdaptiveThreshWinSizeMin = params.getAdaptiveThreshWinSizeMax() + 1;
+        const double newMinMarkerPerimeter = params.getMaxMarkerPerimeter() + 1;
+        const auto oldAdaptiveThreshWinSizeMin = params.getAdaptiveThreshWinSizeMin();
+        const auto oldMinMarkerPerimeter = params.getMinMarkerPerimeter();
+        THEN("An exception is thrown and values aren't changed")
+        {
+            REQUIRE_THROWS(params.setAdaptiveThreshWinSizeMin(newAdaptiveThreshWinSizeMin));
+            REQUIRE(params.getAdaptiveThreshWinSizeMin() == oldAdaptiveThreshWinSizeMin);
+            REQUIRE_THROWS(params.setMinMarkerPerimeter(newMinMarkerPerimeter));
+            REQUIRE(params.getMinMarkerPerimeter() == Approx(oldMinMarkerPerimeter));
+        }
+    }
+
+    GIVEN("I set a maximum lower than the minimum")
+    {
+        const int newAdaptiveThreshSizeMax = params.getAdaptiveThreshWinSizeMin() - 1;
+        const double newMaxMarkerPerimeter = params.getMinMarkerPerimeter() - 1;
+        const auto oldAdaptiveThreshWinSizeMax = params.getAdaptiveThreshWinSizeMax();
+        const auto oldMaxMarkerPerimeter = params.getMaxMarkerPerimeter();
+        THEN("An exception is thrown and values aren't changed")
+        {
+            REQUIRE_THROWS(params.setAdaptiveThreshWinSizeMax(newAdaptiveThreshSizeMax));
+            REQUIRE(params.getAdaptiveThreshWinSizeMax() == oldAdaptiveThreshWinSizeMax);
+            REQUIRE_THROWS(params.setMaxMarkerPerimeter(newMaxMarkerPerimeter));
+            REQUIRE(params.getMaxMarkerPerimeter() == Approx(oldMaxMarkerPerimeter));
+        }
+    }
+
+    GIVEN("A cornerRefinementWinSize less than 1")
+    {
+        constexpr int newCornerRefinementWinSize = -2;
+        const int oldCornerRefinementWinSize = params.getCornerRefinementWinSize();
+        THEN("An Exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setCornerRefinementWinSize(newCornerRefinementWinSize));
+            REQUIRE(params.getCornerRefinementWinSize() == oldCornerRefinementWinSize);
+        }
+    }
+
+    GIVEN("A cornerRefinementMaxIterations less than 1")
+    {
+        constexpr int newCornerRefinementMaxIterations = 0;
+        const int oldCornerRefinementMaxIterations = params.getCornerRefinementMaxIterations();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setCornerRefinementMaxIterations(newCornerRefinementMaxIterations));
+            REQUIRE(params.getCornerRefinementMaxIterations() == oldCornerRefinementMaxIterations);
+        }
+    }
+
+    GIVEN("A cornerRefinementMinAccuracy less than or equal to 0")
+    {
+        constexpr double newCornerRefinementMinAccuracy = -3;
+        const auto oldCornerRefinementMinAccuracy = params.getCornerRefinementMinAccuracy();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setCornerRefinementMinAccuracy(newCornerRefinementMinAccuracy));
+            REQUIRE(params.getCornerRefinementMinAccuracy() == Approx(oldCornerRefinementMinAccuracy));
+        }
+    }
+
+    GIVEN("markerBorderBits less than 1")
+    {
+        constexpr int newBorderBits = 0;
+        const int oldBorderBits = params.getMarkerBorderBits();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setMarkerBorderBits(newBorderBits));
+            REQUIRE(params.getMarkerBorderBits() == oldBorderBits);
+        }
+    }
+
+    GIVEN("minStdDevOtsu less than or equal to 0")
+    {
+        constexpr double newMinOtsuStdDev = -2;
+        const auto oldMinOtsuStdDev = params.getMinOtsuStdDev();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setMinOtsuStdDev(newMinOtsuStdDev));
+            REQUIRE(params.getMinOtsuStdDev() == Approx(oldMinOtsuStdDev));
+        }
+    }
+
+    GIVEN("adaptiveThreshSizeMin less than 3")
+    {
+        constexpr int newThreshSizeMin = 2;
+        const int oldThreshSizeMin = params.getAdaptiveThreshWinSizeMin();
+        THEN("An exception is thrown and value isn't changed"){
+            REQUIRE_THROWS(params.setAdaptiveThreshWinSizeMin(newThreshSizeMin));
+            REQUIRE(params.getAdaptiveThreshWinSizeMin() == oldThreshSizeMin);
+        }
+    }
+
+    GIVEN("adaptiveThreshSizeMax less than 3")
+    {
+        constexpr int newThreshWinSizeMax = 2;
+        const int oldThreshWinSizeMax = params.getAdaptiveThreshWinSizeMax();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setAdaptiveThreshWinSizeMax(newThreshWinSizeMax));
+            REQUIRE(params.getAdaptiveThreshWinSizeMax() == oldThreshWinSizeMax);
+        }
+    }
+
+    GIVEN("adaptiveThreshWinSizeStep less than or equal to 0")
+    {
+        constexpr int newWinSizeStep = 0;
+        const int oldWinSizeStep = params.getAdaptiveThreshWinSizeStep();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setAdaptiveThreshWinSizeStep(newWinSizeStep));
+            REQUIRE(params.getAdaptiveThreshWinSizeStep() == oldWinSizeStep);
+        }
+    }
+
+    GIVEN("minMarkerPerimeter less than or equal to 0")
+    {
+        constexpr double newMinMarkerPerimeter = 0;
+        const auto oldMinMarkerPerimeter = params.getMinMarkerPerimeter();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setMinMarkerPerimeter(newMinMarkerPerimeter));
+            REQUIRE(params.getMinMarkerPerimeter() == Approx(oldMinMarkerPerimeter));
+        }
+    }
+
+    GIVEN("maxMarkerPerimeter less than or equal to 0")
+    {
+        constexpr double newMaxMarkerPerimeter = 0;
+        const auto oldMaxMarkerPerimeter = params.getMaxMarkerPerimeter();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setMaxMarkerPerimeter(newMaxMarkerPerimeter));
+            REQUIRE(params.getMaxMarkerPerimeter() == Approx(oldMaxMarkerPerimeter));
+        }
+    }
+
+    GIVEN("cornerRefinementMinAccuracy less than or equal to 0")
+    {
+        constexpr double newMinAccuracy = 0;
+        const auto oldMinAccuracy = params.getCornerRefinementMinAccuracy();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setCornerRefinementMinAccuracy(newMinAccuracy));
+            REQUIRE(params.getCornerRefinementMinAccuracy() == Approx(oldMinAccuracy));
+        }
+    }
+
+    GIVEN("minCornerDistance less than 0")
+    {
+        constexpr double newMinCornerDistance = -1;
+        const auto oldMinCornerDistance = params.getMinMarkerDistance();
+        THEN("An exception is thrown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setMinCornerDistance(newMinCornerDistance));
+            REQUIRE(params.getMinCornerDistance() == Approx(oldMinCornerDistance));
+        }
+    }
+
+    GIVEN("minDistanceToBorder less than 0")
+    {
+        constexpr int newMinDistToBorder = -2;
+        const int oldMinDistToBorder = params.getMinDistanceToBorder();
+        THEN("An exception is thown and value isn't changed")
+        {
+            REQUIRE_THROWS(params.setMinDistanceToBorder(newMinDistToBorder));
+            REQUIRE(params.getMinDistanceToBorder() == oldMinDistToBorder);
+        }
+    }
+}