From e91c65b1b37dfca5f7aee975bd751a43e0f4b9e8 Mon Sep 17 00:00:00 2001
From: "Kilic, Deniz" <d.kilic@fz-juelich.de>
Date: Tue, 22 Dec 2020 16:01:47 +0100
Subject: [PATCH] Implemented aruco marker visualization with offset

See #71
---
 include/codeMarkerItem.h |  23 ++++++--
 include/vector.h         |   1 +
 src/codeMarkerItem.cpp   | 122 ++++++++++++---------------------------
 src/petrack.cpp          |   2 +
 src/recognition.cpp      |  14 +----
 src/vector.cpp           |   7 +++
 6 files changed, 67 insertions(+), 102 deletions(-)

diff --git a/include/codeMarkerItem.h b/include/codeMarkerItem.h
index 6fb7c2a30..02c353d76 100644
--- a/include/codeMarkerItem.h
+++ b/include/codeMarkerItem.h
@@ -29,25 +29,36 @@ class Petrack;
 class Control;
 class Tracker;
 
+struct OffsetMarker {
+    std::vector<cv::Point2f> corners;
+    Vec2F offset;
+
+    OffsetMarker(std::vector<cv::Point2f> corn, Vec2F off) : corners(corn), offset(off) {};
+};
+
 class CodeMarkerItem : public QGraphicsItem
 {
 private:
     Petrack *mMainWindow;
-//    QImage *mImage;
+    const QColor mRejectedColor = QColor(255,0,0); // red
+    const QColor mCornerColor = QColor(0,0,255); // blue
+    const QColor mAcceptedColor = QColor(0,255,0); // green
 
     std::vector<int> mIds;
-    std::vector<std::vector<cv::Point2f> > mCorners, mRejected;
+    std::vector<OffsetMarker> mCorners, mRejected;
     Vec2F mUlc;  // upper left corner to draw
-    Vec2F mOffsetCropRect2Roi; //
 
 public:
     CodeMarkerItem(QWidget *wParent, QGraphicsItem * parent = NULL);
     QRectF boundingRect() const;
     void setRect(Vec2F& v);
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
-    void setDetectedMarkers(std::vector<std::vector<cv::Point2f> > corners, std::vector<int> ids);
-    void setRejectedMarkers(std::vector<std::vector<cv::Point2f> > rejected);
-    void setOffsetCropRect2Roi(Vec2F offsetCropRect2Roi);
+    void addDetectedMarkers(std::vector<std::vector<cv::Point2f> > corners, std::vector<int> ids, Vec2F offset = Vec2F(0,0));
+    void addRejectedMarkers(std::vector<std::vector<cv::Point2f> > rejected, Vec2F offset = Vec2F(0,0));
+    void resetSavedMarkers();
+
+private:
+    void drawMarker(const OffsetMarker& currentMarker, int id, const QColor& borderColor, QPainter *painter);
 };
 
 #endif
diff --git a/include/vector.h b/include/vector.h
index 41931c56a..15406bba1 100644
--- a/include/vector.h
+++ b/include/vector.h
@@ -129,6 +129,7 @@ public:
     Vec2F(double x, double y);
     Vec2F(const Vec2F& v) = default;
     Vec2F(const QPointF& v);
+    Vec2F(const cv::Point2f& p);
     Vec2F(const CvPoint* v);
     Vec2F(const CvPoint2D32f* v);
 
diff --git a/src/codeMarkerItem.cpp b/src/codeMarkerItem.cpp
index a891f0039..41981d6b6 100644
--- a/src/codeMarkerItem.cpp
+++ b/src/codeMarkerItem.cpp
@@ -79,10 +79,6 @@ void CodeMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*
 
     if (mMainWindow->getCodeMarkerWidget()->showDetectedCandidates->isChecked())
     {
-        QColor textColor = QColor(255,0,0), // red
-               cornerColor = QColor(0,0,255), // blue
-               borderColor = QColor(0,255,0); // green
-
         int nMarkers = mCorners.size();
         int nRejected = mRejected.size();
 
@@ -90,77 +86,14 @@ void CodeMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*
         Point2f p0, p1;
         for(int i = 0; i < nMarkers; i++) // draws green square/ circle around head if person recognized
         {
-            int recoMethod = mMainWindow->getControlWidget()->getRecoMethod();
-
-            if (recoMethod == 6) // for usage of ArucoCodeMarker-Funktion (without MulticolorMarker)
-            {
-                vector<Point2f> currentMarker = mCorners.at(i);
-                // draw marker sides
-                for(int j = 0; j < 4; j++) {
-                    p0 = currentMarker.at(j);
-                    p1 = currentMarker.at((j + 1) % 4);
-    //                debout << "p0: " << p0 << " p1: " << p1 << endl;
-                    painter->setPen(borderColor);
-                    painter->drawLine(QPointF(mUlc.x()+p0.x,mUlc.y()+p0.y),QPointF(mUlc.x()+p1.x,mUlc.y()+p1.y));
-                }
-                painter->setPen(cornerColor);
-                painter->drawText(QPointF(mUlc.x()+currentMarker.at(0).x+10.,mUlc.y()+currentMarker.at(0).y+10. ), QString::number(mIds.at(i)));
-                painter->drawRect(QRectF(mUlc.x()+currentMarker.at(0).x-3.0,mUlc.y()+currentMarker.at(0).y-3.0,6.0,6.0));
-            }
-
-            if (recoMethod == 5) // for usage of codemarker with MulticolorMarker
-            {
-                vector<Point2f> currentMarker = mCorners.at(i);
-                // draw marker sides
-                for(int j = 0; j < 4; j++) {
-                    p0 = currentMarker.at(j);
-                    p1 = currentMarker.at((j + 1) % 4);
-    //                debout << "p0: " << p0 << " p1: " << p1 << endl;
-                    painter->setPen(borderColor);
-                    painter->drawLine(QPointF(mUlc.x()+p0.x+mOffsetCropRect2Roi.x(),mUlc.y()+p0.y+mOffsetCropRect2Roi.y()),QPointF(mUlc.x()+p1.x+mOffsetCropRect2Roi.x(),mUlc.y()+p1.y+mOffsetCropRect2Roi.y()));
-                }
-                painter->setPen(cornerColor);
-                painter->drawText(QPointF(mUlc.x()+currentMarker.at(0).x+mOffsetCropRect2Roi.x()+10.,mUlc.y()+currentMarker.at(0).y+mOffsetCropRect2Roi.y()+10. ), QString::number(mIds.at(i)));
-                painter->drawRect(QRectF(mUlc.x()+currentMarker.at(0).x+mOffsetCropRect2Roi.x()-3.0,mUlc.y()+currentMarker.at(0).y+mOffsetCropRect2Roi.y()-3.0,6.0,6.0));
-            }
-
+            drawMarker(mCorners.at(i), mIds.at(i), mAcceptedColor, painter);
         }
         for(int i = 0; i < nRejected; i++)
         {
-            int recoMethod = mMainWindow->getControlWidget()->getRecoMethod();
-
-            if (recoMethod == 6) // for usage of ArucoCodeMarker-Funktion (without MulticolorMarker)
-            {
-                vector<Point2f> currentMarker = mRejected.at(i);
-
-                for(int j = 0; j < 4; j++) {
-                    p0 = currentMarker.at(j);
-                    p1 = currentMarker.at((j + 1) % 4);
-    //                debout << "p0: " << p0 << " p1: " << p1 << endl;
-                    painter->setPen(textColor);
-                    painter->drawLine(QPointF(mUlc.x()+p0.x,mUlc.y()+p0.y),QPointF(mUlc.x()+p1.x,mUlc.y()+p1.y));
-                }
-                painter->setPen(borderColor);
-                painter->drawRect(QRectF(mUlc.x()+currentMarker.at(0).x-3.0,mUlc.y()+currentMarker.at(0).y-3.0,6.0,6.0));
-            }
-
-            if (recoMethod == 5) // for usage of all types of detection (except combination of multicolormarker with arucoCode)
-            {
-                vector<Point2f> currentMarker = mRejected.at(i);
-
-                for(int j = 0; j < 4; j++) {
-                    p0 = currentMarker.at(j);
-                    p1 = currentMarker.at((j + 1) % 4);
-    //                debout << "p0: " << p0 << " p1: " << p1 << endl;
-                    painter->setPen(textColor);
-                    painter->drawLine(QPointF(mUlc.x()+p0.x+mOffsetCropRect2Roi.x(),mUlc.y()+p0.y+mOffsetCropRect2Roi.y()),QPointF(mUlc.x()+p1.x+mOffsetCropRect2Roi.x(),mUlc.y()+p1.y+mOffsetCropRect2Roi.y()));
-                }
-                painter->setPen(borderColor);
-                painter->drawRect(QRectF(mUlc.x()+currentMarker.at(0).x+mOffsetCropRect2Roi.x()-3.0,mUlc.y()+currentMarker.at(0).y+mOffsetCropRect2Roi.y()-3.0,6.0,6.0));
-            }
-
+            drawMarker(mRejected.at(i), -1, mRejectedColor, painter);
         }
     }
+
     if (false) // Show min/max marker size
     {
         int minPerimeter = mMainWindow->getCodeMarkerWidget()->minMarkerPerimeter->value();
@@ -196,26 +129,45 @@ void CodeMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*
 
 }
 
-void CodeMarkerItem::setDetectedMarkers(vector<vector<Point2f> > corners, vector<int> ids)
+inline void CodeMarkerItem::drawMarker(const OffsetMarker& currentMarker, int id, const QColor& borderColor, QPainter *painter)
+{
+    Vec2F offset = currentMarker.offset;
+    // draw marker sides
+    for(int j = 0; j < 4; j++) {
+        Vec2F p0 = currentMarker.corners.at(j);
+        Vec2F p1 = currentMarker.corners.at((j + 1) % 4);
+        //                debout << "p0: " << p0 << " p1: " << p1 << endl;
+        painter->setPen(borderColor);
+        painter->drawLine((mUlc + p0 + offset).toQPointF(), (mUlc + p1 + offset).toQPointF());
+    }
+    Vec2F topLeftCorner {currentMarker.corners.at(0)};
+    painter->setPen(mCornerColor);
+    if(id != -1) {
+        painter->drawText((mUlc + topLeftCorner + offset + Vec2F(10,10)).toQPointF(), QString::number(id));
+    }
+    painter->drawRect(QRectF((mUlc + topLeftCorner + offset - Vec2F(3,3)).toQPointF(), QSize(6.0,6.0)));
+}
+
+void CodeMarkerItem::addDetectedMarkers(vector<vector<Point2f> > corners, vector<int> ids, Vec2F offset /* = (0,0)*/)
 {
-    mCorners = corners;
-    mIds = ids;
+    for(std::vector<Point2f> singleMarkerCorners : corners)
+    {
+        mCorners.emplace_back(singleMarkerCorners, offset);
+    }
+    mIds.insert(mIds.end(), ids.begin(), ids.end());
 }
 
-void CodeMarkerItem::setRejectedMarkers(vector<vector<Point2f> > rejected)
+void CodeMarkerItem::addRejectedMarkers(vector<vector<Point2f> > rejected, Vec2F offset /* = (0,0)*/)
 {
-    mRejected = rejected;
+    for(std::vector<Point2f> singleMarkerCorners : rejected)
+    {
+        mRejected.emplace_back(singleMarkerCorners, offset);
+    }
 }
 
-/**
- * @brief sets Offset from cropRect to Roi for correct drawing of CodeMarkers in paint() when calling findCodeMarker() out of findMulticolorMarker().
- *
- * Explanation: when calling findCodeMarker() out of findMultiColorMarker() the transfer parameter is not the entire image but rather a small rectangle (cropRect) around the detected colorBlobb.
- * Offset additions via 'offset' and 'v' only allow addition of ONE offset for all candidates per frame, as is originates from realising the offset from the entire image to the region of interest (ROI).
- * offsetCropRect2Roi closes the resulting gap between ROI and cropRect (which is individuall for each pedestrian and frame).
- * @param offsetCropRect2Roi
- */
-void CodeMarkerItem::setOffsetCropRect2Roi(Vec2F offsetCropRect2Roi)
+void CodeMarkerItem::resetSavedMarkers()
 {
-    mOffsetCropRect2Roi = offsetCropRect2Roi;
+    mCorners.clear();
+    mIds.clear();
+    mRejected.clear();
 }
diff --git a/src/petrack.cpp b/src/petrack.cpp
index 6cae68113..2db70305d 100644
--- a/src/petrack.cpp
+++ b/src/petrack.cpp
@@ -3560,6 +3560,8 @@ void Petrack::updateImage(bool imageChanged) // default = false (only true for n
     debout << "go  update: " << getElapsedTime() <<endl;
 #endif
 
+    mCodeMarkerItem->resetSavedMarkers();
+
     static int lastRecoFrame = -10000;
     static bool borderChangedForTracking = false;
 
diff --git a/src/recognition.cpp b/src/recognition.cpp
index 2b93f03ed..f6a16c623 100644
--- a/src/recognition.cpp
+++ b/src/recognition.cpp
@@ -813,8 +813,6 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr
                     {
                         offsetCropRect2Roi.setX(0); // set to zero as cooridinates are directly used from cropRect
                         offsetCropRect2Roi.setY(0);
-                        CodeMarkerItem* codeMarkerItem = controlWidget->getMainWindow()->getCodeMarkerItem();
-                        codeMarkerItem->setOffsetCropRect2Roi(offsetCropRect2Roi);
 
                         if (autoCorrect && !autoCorrectOnlyExport)
                         {
@@ -1100,7 +1098,7 @@ void findColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWid
  * @param crossList[out] list of detected TrackPoints
  * @param controlWidget
  */
-void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidget, Vec2F offsetCropRect2Roi)
+void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidget, Vec2F offsetCropRect2Roi /*=(0,0)*/)
 {
 //#if 0 // Maik temporaer, damit es auf dem Mac laeuft
 
@@ -1212,14 +1210,8 @@ void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidg
     debout << "end detectCodeMarkers  : " << getElapsedTime() <<endl;
 #endif
 
-
-    if (offsetCropRect2Roi.length()!=0)
-    {
-        codeMarkerItem->setOffsetCropRect2Roi(offsetCropRect2Roi);
-    }
-
-    codeMarkerItem->setDetectedMarkers(corners,ids);
-    codeMarkerItem->setRejectedMarkers(rejected);
+    codeMarkerItem->addDetectedMarkers(corners,ids, offsetCropRect2Roi);
+    codeMarkerItem->addRejectedMarkers(rejected, offsetCropRect2Roi);
 
     // detected code markers
     for(size_t i = 0; i<ids.size(); i++)
diff --git a/src/vector.cpp b/src/vector.cpp
index 1b9fc3ea4..f0709c255 100644
--- a/src/vector.cpp
+++ b/src/vector.cpp
@@ -238,6 +238,13 @@ Vec2F::Vec2F(const QPointF& v)
       mY(v.y())
 {
 }
+
+Vec2F::Vec2F(const cv::Point2f &p)
+    : mX(p.x),
+      mY(p.y)
+{
+}
+
 Vec2F::Vec2F(const CvPoint* v)
     : mX(v->x),
       mY(v->y)
-- 
GitLab