From 49dd675d42a524688d3f1b00f9e14d6978e605b3 Mon Sep 17 00:00:00 2001 From: Ann Katrin <a.seemann@fz-juelich.de> Date: Wed, 22 Jul 2020 11:17:44 +0200 Subject: [PATCH] 1) Implementation of "use CodeMarker"-Button in GUI 2) Started combined detection of CodeMarker on orange head MAJOR BUG: CodeMarker is only detected if large picture is handed over to detectCodeMarker-Funktion and not if a partial image is handed over. --- include/codeMarkerItem.h | 2 + include/multiColorMarkerWidget.h | 10 + include/recognition.h | 1 + src/codeMarkerItem.cpp | 119 +++++++-- src/helper.cpp | 15 +- src/multiColorMarkerWidget.cpp | 11 + src/recognition.cpp | 245 ++++++++++++------ .../data/multiColorMarkerWithAruco.mp4 | 3 + .../data/multiColorMarkerWithAruco.pet | 84 ++++++ .../data/multiColorMarkerWithAruco_truth.trc | 107 ++++++++ .../data/multiColorMarkerWithAruco_truth.txt | 103 ++++++++ tests/regression_test/tests/conftest.py | 2 +- ui/control.ui | 18 +- ui/multiColorMarker.ui | 56 +++- 14 files changed, 643 insertions(+), 133 deletions(-) create mode 100644 tests/regression_test/data/multiColorMarkerWithAruco.mp4 create mode 100644 tests/regression_test/data/multiColorMarkerWithAruco.pet create mode 100644 tests/regression_test/data/multiColorMarkerWithAruco_truth.trc create mode 100644 tests/regression_test/data/multiColorMarkerWithAruco_truth.txt diff --git a/include/codeMarkerItem.h b/include/codeMarkerItem.h index 350054f72..1fd656651 100644 --- a/include/codeMarkerItem.h +++ b/include/codeMarkerItem.h @@ -18,6 +18,7 @@ private: std::vector<int> mIds; std::vector<std::vector<cv::Point2f> > mCorners, mRejected; Vec2F mUlc; // upper left corner to draw + Vec2F mOffsetCropRect2Roi; // public: CodeMarkerItem(QWidget *wParent, QGraphicsItem * parent = NULL); @@ -26,6 +27,7 @@ public: 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); }; #endif diff --git a/include/multiColorMarkerWidget.h b/include/multiColorMarkerWidget.h index 92f62cf7d..2a6bce4b7 100644 --- a/include/multiColorMarkerWidget.h +++ b/include/multiColorMarkerWidget.h @@ -6,6 +6,7 @@ #include "petrack.h" #include "multiColorMarkerItem.h" +#include "codeMarkerWidget.h" #include "imageItem.h" #include "control.h" @@ -34,6 +35,15 @@ private slots: mMainWindow->setRecognitionChanged(true);// flag indicates that changes of recognition parameters happens mMainWindow->updateImage(); } + void on_useCodeMarker_stateChanged(int /* i */) + { + mMainWindow->setRecognitionChanged(true); + mMainWindow->updateImage(); + } + void on_CodeMarkerParameter_clicked() + { + mMainWindow->getCodeMarkerWidget()->show(); + } void on_ignoreWithoutDot_stateChanged(int i) { mMainWindow->setRecognitionChanged(true);// flag indicates that changes of recognition parameters happens diff --git a/include/recognition.h b/include/recognition.h index 11fd07c16..126d62c73 100644 --- a/include/recognition.h +++ b/include/recognition.h @@ -18,4 +18,5 @@ Vec2F autoCorrectColorMarker(Vec2F &boxImageCentre, Control *controlWidget); //void getMarkerPos(IplImage *iplImg, QRect roi, QList<TrackPoint> *crossList, int markerBrightness, int borderSize, bool ignoreWithoutMarker, bool autoWB, BackgroundFilter *bgFilter, int recoMethod); void getMarkerPos(cv::Mat &img, QRect &roi, QList<TrackPoint> *crossList, Control *controlWidget, int borderSize, BackgroundFilter *bgFilter); +void findCodeMarker(cv::Mat &img, QList<TrackPoint> *crossList, Control *controlWidget, Vec2F offsetCropRect2Roi=Vec2F{0,0}); #endif diff --git a/src/codeMarkerItem.cpp b/src/codeMarkerItem.cpp index 762415fa4..779dd10d0 100644 --- a/src/codeMarkerItem.cpp +++ b/src/codeMarkerItem.cpp @@ -6,6 +6,7 @@ #include "codeMarkerWidget.h" #include "tracker.h" #include "animation.h" +#include "control.h" using namespace::cv; using namespace std; @@ -54,48 +55,103 @@ void CodeMarkerItem::setRect(Vec2F& v) mUlc = v; // upper left corner to draw } +/** + * @brief draws colored shapes at heads in image to indicate detection status + * + * differnet calculations of position depending on whether function is called out of findCodeMarker() Function + * only (== recoMethod 6) or if findCodeMarker() Function is called out of findMulticolorMarker() Function (== recoMethod 5). + * In the first case the offset is added automatically via 'offset' and 'v'. + * In the second case the offset from cropRect to ROI has to be added manually. + * + * @param painter + * @param option + * @param widget + */ void CodeMarkerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (mMainWindow->getCodeMarkerWidget()->showDetectedCandidates->isChecked()) { - QColor textColor = QColor(255,0,0), - cornerColor = QColor(0,0,255), - borderColor = QColor(0,255,0); + 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(); // debout << "#markers: " << nMarkers << " #rejected: " << nRejected << endl; Point2f p0, p1; - for(int i = 0; i < nMarkers; i++) + for(int i = 0; i < nMarkers; i++) // draws green square/ circle around head if person recognized { - 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)); + 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)); } - 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)); + } for(int i = 0; i < nRejected; i++) { - 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)); + 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)); } - 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 (false) // Show min/max marker size @@ -143,3 +199,16 @@ void CodeMarkerItem::setRejectedMarkers(vector<vector<Point2f> > rejected) { mRejected = rejected; } + +/** + * @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) +{ + mOffsetCropRect2Roi = offsetCropRect2Roi; +} diff --git a/src/helper.cpp b/src/helper.cpp index 27c3f9980..b869b11df 100644 --- a/src/helper.cpp +++ b/src/helper.cpp @@ -171,10 +171,17 @@ void showImg(QLabel *l, IplImage *i) } #endif -// get roi -// no copy of data, only new header which allows to access rect -// copys roi to rect by set values of roi to correct values inside rect -// rect wird veraendert, roi nicht +/** +@brief get roi: copys roi to rect by setting values of roi to correct values inside rect + +no copy of data, only new header which allows to access rect +rect wird veraendert, roi nicht + +@param[in] img Mat &img +@param[in] const QRect &roi +@param[in] Rect &rect +@return img(rect) +*/ Mat getRoi(Mat &img, const QRect &roi, Rect &rect, bool evenPixelNumber) { // Mat tImg; diff --git a/src/multiColorMarkerWidget.cpp b/src/multiColorMarkerWidget.cpp index 9f30643ab..6917a7a46 100644 --- a/src/multiColorMarkerWidget.cpp +++ b/src/multiColorMarkerWidget.cpp @@ -22,6 +22,10 @@ void MultiColorMarkerWidget::setXml(QDomElement &elem) subElem.setAttribute("RESTRICT_POSITION", restrictPosition->isChecked()); elem.appendChild(subElem); + subElem = (elem.ownerDocument()).createElement("CODE_MARKER"); + subElem.setAttribute("USE", useCodeMarker->isChecked()); + elem.appendChild(subElem); + subElem = (elem.ownerDocument()).createElement("AUTO_CORRECT"); subElem.setAttribute("USE", autoCorrect->isChecked()); subElem.setAttribute("ONLY_EXPORT", autoCorrectOnlyExport->isChecked()); @@ -75,6 +79,13 @@ void MultiColorMarkerWidget::getXml(QDomElement &elem) if (subElem.hasAttribute("RESTRICT_POSITION")) restrictPosition->setCheckState(subElem.attribute("RESTRICT_POSITION").toInt() ? Qt::Checked : Qt::Unchecked); } + if (subElem.tagName() == "CODE_MARKER") + { + if (subElem.hasAttribute("USE")) + useCodeMarker->setCheckState(subElem.attribute("USE").toInt() ? Qt::Checked : Qt::Unchecked); + if (subElem.hasAttribute("IGNORE_WITHOUT")) + ignoreWithoutDot->setCheckState(subElem.attribute("IGNORE_WITHOUT").toInt() ? Qt::Checked : Qt::Unchecked); + } if (subElem.tagName() == "AUTO_CORRECT") { if (subElem.hasAttribute("USE")) diff --git a/src/recognition.cpp b/src/recognition.cpp index 9b58c06b7..ff7a8bbac 100644 --- a/src/recognition.cpp +++ b/src/recognition.cpp @@ -201,9 +201,16 @@ void setColorParameter(const QColor &fromColor, const QColor &toColor, bool inve //// DWORD PeakPagefileUsage; //// } PROCESS_MEMORY_COUNTERS,*PPROCESS_MEMORY_COUNTERS; -// berechnet pixelverschiebung aufgrund von schraegsicht bei einem farbmarker -// Maik Dissertation Seite 138 -// boxImageCentre ohne Border + +/** + * @brief calculates pixel-displacement due to oblique/angular view + * + * Relevant for Color Markers. boxImageCentre without border. More information: Dissertation Maik pp. 138 + * + * @param boxImageCentre + * @param controlWidget + * @return + */ Vec2F autoCorrectColorMarker(Vec2F &boxImageCentre, Control *controlWidget) { Petrack *mainWindow = controlWidget->getMainWindow(); @@ -237,10 +244,20 @@ Vec2F autoCorrectColorMarker(Vec2F &boxImageCentre, Control *controlWidget) return (0.12*angle/cmPerPixel.length())*moveDir; // Maik Dissertation Seite 138 } -// Run color blob detection on an image to find features. -// Runs color thresholding to binarize the image and computes connected components. -// The features are the center of gravity of each connected component. -// offset is corner of roi + +/** + * @brief Run color blob detection on an image to find features + * + * Runs color thresholding to binarize the image and computes connected components. + * The features are the center of gravity of each connected component. + * offset is corner of roi. + * + * @param img + * @param crossList + * @param controlWidget + * @param ignoreWithoutMarker + * @param offset + */ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidget, bool ignoreWithoutMarker, Vec2F &offset) { ColorParameters param; @@ -264,6 +281,7 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr int minArea = cmWidget->minArea->value(), maxArea = cmWidget->maxArea->value(); double maxRatio = cmWidget->maxRatio->value(); bool useBlackDot = cmWidget->useDot->isChecked(); + bool useCodeMarker = cmWidget->useCodeMarker->isChecked(); bool restrictPosition = cmWidget->restrictPosition->isChecked(); ignoreWithoutMarker = cmWidget->ignoreWithoutDot->isChecked(); // ueberschreiben von uebergeordnetem ignoreWithoutMarker bool autoCorrect = cmWidget->autoCorrect->isChecked(); @@ -423,7 +441,7 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr if (useBlackDot) { - oriRect = cv::Rect(Point(0,0),Size(img.cols,img.rows));// img.cvGetImageROI(img);; + // oriRect = cv::Rect(Point(0,0),Size(img.cols,img.rows));// img.cvGetImageROI(img);; // cropRect ist orthogonal und verzichtet auf rotation, genauer waere: // http://answers.opencv.org/question/38452/how-to-extract-pixels-from-a-rotated-box2d/ // max wegen bildrand @@ -621,7 +639,7 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr // find contours and store them all as a list cv::findContours(subBW,subContours,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE); -// cvFindContours(subBW, subStorage, &subFirstContour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); // gray wird auch veraendert!!! +// cvFindContours(subBW, subStorage, &subFirstContour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); // gray wird auch veraendert!!! // test each contour while (!subContours.empty()) @@ -727,7 +745,76 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr ////} } // debout << "contours.size(): " << contours.size() << "Color: " << col << endl; - if (!useBlackDot && foundHead) + if (useCodeMarker && foundHead) + { + // Goal of the following part: implement useage of ArucoCode instead of "useBlackDot" + // Output of findCodeMarker-Funktion: crossList->append(TrackPoint(Vec2F(x,y), 100, ids.at(i))); + // where x,y are coordinates of the CodeMarkers and i is the running index over all detected marker + // missing frames where Code is not recognized are interpolated in trackerReal.cpp and Marker ID is set to -1 + + // cropRect has coordinates of rechtangele around color blob with respect to lower left corner (as in the beginning of useBlackDot) + cropRect.x = max(1, myRound(box.center.x-box.size.width/2.-border)); + cropRect.y = max(1, myRound(box.center.y-box.size.height/2.-border)); + cropRect.width = min(img.cols-cropRect.x-1, 2*border+(myRound(maxExpansion) & -2)); + cropRect.height = min(img.rows-cropRect.y-1, 2*border+(myRound(maxExpansion) & -2)); + subImg=img(cropRect); // --> shallow copy (points to original data) + + int lengthini = crossList->size(); // initial length of crossList (before findCodeMarker() is called) + + Vec2F offsetCropRect2Roi; // needed for drawing detected ArucoCode-Candidates correctly -> passed on to findCodeMarker()-Function + offsetCropRect2Roi.setX(cropRect.x); + offsetCropRect2Roi.setY(cropRect.y); + + if (subImg.empty()) + return; + findCodeMarker(subImg, crossList, controlWidget, offsetCropRect2Roi); + + // The next tree statements each: + // - set the offset of subImg with regards to ROI //(ROI to original image is archieved later in the code for all methods) + // - add the functionality of autocorrection + // - deal with functionality of ignore/not ignore heads without identified ArucoMarker + if (ignoreWithoutMarker && lengthini<crossList->size()) // if CodeMarker-Call returns crossList containing a new element (identified the ArucoMarker) + { + size_t ii = crossList->size()-1; + if (autoCorrect && !autoCorrectOnlyExport) + { + moveDir = autoCorrectColorMarker(boxImageCentre, controlWidget); + } + else + { + moveDir = Vec2F(0, 0); + } + (*crossList)[ii] = (*crossList)[ii] + (TrackPoint(Vec2F(cropRect.x, cropRect.y) + moveDir)); + } + else if(!ignoreWithoutMarker && (lengthini==crossList->size())) // in case ignoreWithoutMarker is checked and CodeMarker-Call returns empty crossList (could not identify a marker) the center of the smallest rectangle around the colorblobb is used as position + { + if (autoCorrect && !autoCorrectOnlyExport) + { + moveDir = autoCorrectColorMarker(boxImageCentre, controlWidget); + + crossList->append(TrackPoint(Vec2F(box.center.x, box.center.y)+moveDir, 100, Vec2F(box.center.x, box.center.y), col)); // 100 beste qualitaet + } + else + { + crossList->append(TrackPoint(Vec2F(box.center.x, box.center.y), 90, Vec2F(box.center.x, box.center.y), col)); // 100 beste qualitaet + } + } + else if(!ignoreWithoutMarker && (crossList->size()!=lengthini)) // in case ignoreWithoutMarker is checked and CodeMarker-Call returns non-empty crossList (could identify a marker) + { + size_t ii = crossList->size()-1; + if (autoCorrect && !autoCorrectOnlyExport) + { + moveDir = autoCorrectColorMarker(boxImageCentre, controlWidget); + } + else + { + moveDir = Vec2F(0, 0); + } + (*crossList)[ii] = (*crossList)[ii] + (TrackPoint(Vec2F(cropRect.x, cropRect.y) + moveDir)); + } + + } + if (!useBlackDot && foundHead && !useCodeMarker) { if (autoCorrect && !autoCorrectOnlyExport) { @@ -738,9 +825,11 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr else crossList->append(TrackPoint(Vec2F(box.center.x, box.center.y), 100, Vec2F(box.center.x, box.center.y), col)); // 100 beste qualitaet } - else if (minGrey <260) // mit gefundenem schwarzem punkt + else if (minGrey <260 && !useCodeMarker) // mit gefundenem schwarzem punkt + { crossList->append(TrackPoint(subCenter, 100, Vec2F(box.center.x, box.center.y), col)); // 100 beste qualitaet - else if (!ignoreWithoutMarker && foundHead) + } + else if (!ignoreWithoutMarker && foundHead && !useCodeMarker) { if (autoCorrect && !autoCorrectOnlyExport) { @@ -752,9 +841,7 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr crossList->append(TrackPoint(Vec2F(box.center.x, box.center.y), 90, Vec2F(box.center.x, box.center.y), col)); // 100 beste qualitaet } } - // take the next contour -// contour = contour->h_next; contours.pop_back(); } // if (firstContour) @@ -768,10 +855,16 @@ void findMultiColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *contr // cvReleaseStructuringElement(&openKernel); } - -// Run color blob detection on an image to find features. -// Runs color thresholding to binarize the image and computes connected components. -// The features are the center of gravity of each connected component. +/** + * @brief Run color blob detection on an image to find features. + * + * Runs color thresholding to binarize the image and computes connected components. + * The features are the center of gravity of each connected component. + * + * @param img + * @param crossList + * @param controlWidget + */ void findColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidget) { ColorParameters param; @@ -976,18 +1069,19 @@ void findColorMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWid //cout << "Found " << crossList->size() << " features.\n"; } -void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidget) +/** + * @brief uses openCV libraries to detect Aruco CodeMarkers + * @param img + * @param crossList + * @param controlWidget + */ +void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidget, Vec2F offsetCropRect2Roi) { //#if 0 // Maik temporaer, damit es auf dem Mac laeuft CodeMarkerItem* codeMarkerItem = controlWidget->getMainWindow()->getCodeMarkerItem(); CodeMarkerWidget* codeMarkerWidget = controlWidget->getMainWindow()->getCodeMarkerWidget(); -// Mat mat = cvarrToMat(img);//.clone(); // for marker detection and debug output (show detected candidates) - -// debout << "w: " << img->width << " h: " << img->height << endl; -// IplImage* binary = codeMarkerItem->createMask(img->width, img->height); // create binary mask with size of img - Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(codeMarkerWidget->dictList->currentIndex())); Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create(); @@ -997,54 +1091,57 @@ void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidg Petrack *mainWindow = controlWidget->getMainWindow(); int bS = mainWindow->getImageBorderSize(); - - //debout << "Image w=" << mainWindow->getImage()->width() << ", h=" << mainWindow->getImage()->height() << " bS=" << bS << endl; + int recoMethod = controlWidget->getRecoMethod(); if (controlWidget->getCalibCoordDimension() == 0) // 3D { - QRect rect(myRound(mainWindow->getRecoRoiItem()->rect().x()),//+controlWidget->getMainWindow()->getImageBorderSize()), - myRound(mainWindow->getRecoRoiItem()->rect().y()),//+controlWidget->getMainWindow()->getImageBorderSize()), - myRound(mainWindow->getRecoRoiItem()->rect().width()), - myRound(mainWindow->getRecoRoiItem()->rect().height())); - 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()); - -// QPointF p1 = mainWindow->getImageItem()->getCmPerPixel(0,0,controlWidget->mapDefaultHeight->value()), -// p2 = mainWindow->getImageItem()->getCmPerPixel(mainWindow->getImage()->width()-bS,0,controlWidget->mapDefaultHeight->value()), -// p3 = mainWindow->getImageItem()->getCmPerPixel(0,mainWindow->getImage()->height()-bS,controlWidget->mapDefaultHeight->value()), -// p4 = mainWindow->getImageItem()->getCmPerPixel(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS,controlWidget->mapDefaultHeight->value()); - - double cmPerPixel_min = min(min(min(p1.x(), p1.y()), min(p2.x(), p2.y())), - min(min(p3.x(), p3.y()), min(p4.x(), p4.y()))); - double cmPerPixel_max = max(max(max(p1.x(), p1.y()), max(p2.x(), p2.y())), - max(max(p3.x(), p3.y()), max(p4.x(), p4.y()))); - -// minMarkerPerimeterRate = (codeMarkerWidget->minMarkerPerimeter->value()*4/cmPerPixel_max)/max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS); -// maxMarkerPerimeterRate = (codeMarkerWidget->maxMarkerPerimeter->value()*4/cmPerPixel_min)/max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS); - - minMarkerPerimeterRate = (codeMarkerWidget->minMarkerPerimeter->value()*4/cmPerPixel_max)/max(rect.width(),rect.height()); - maxMarkerPerimeterRate = (codeMarkerWidget->maxMarkerPerimeter->value()*4/cmPerPixel_min)/max(rect.width(),rect.height()); + if (recoMethod == 6) // for usage of codemarker with CodeMarker-function (-> without MulticolorMarker) + { + QRect rect(myRound(mainWindow->getRecoRoiItem()->rect().x()),//+controlWidget->getMainWindow()->getImageBorderSize()), + myRound(mainWindow->getRecoRoiItem()->rect().y()),//+controlWidget->getMainWindow()->getImageBorderSize()), + myRound(mainWindow->getRecoRoiItem()->rect().width()), + myRound(mainWindow->getRecoRoiItem()->rect().height())); + 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 = min(min(min(p1.x(), p1.y()), min(p2.x(), p2.y())), + min(min(p3.x(), p3.y()), min(p4.x(), p4.y()))); + double cmPerPixel_max = max(max(max(p1.x(), p1.y()), max(p2.x(), p2.y())), + max(max(p3.x(), p3.y()), max(p4.x(), p4.y()))); + + minMarkerPerimeterRate = (codeMarkerWidget->minMarkerPerimeter->value()*4./cmPerPixel_max)/max(rect.width(),rect.height()); + maxMarkerPerimeterRate = (codeMarkerWidget->maxMarkerPerimeter->value()*4./cmPerPixel_min)/max(rect.width(),rect.height()); + } + + if (recoMethod == 5) // for usage of codemarker with MulticolorMarker + { + QRect rect(0,0, img.rows, img.cols); + 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()); + + // from Aruco Documentation values 0 + 4 all info is considered (low performance issues expected due to small image size) + minMarkerPerimeterRate = 0.02; + maxMarkerPerimeterRate = 4.; + } minCornerDistanceRate = codeMarkerWidget->minCornerDistance->value(); minMarkerDistanceRate = codeMarkerWidget->minMarkerDistance->value(); - //debout << "image w=" << mainWindow->getImage()->width() << ", h=" << mainWindow->getImage()->height() << ", bS=" << bS << endl; - //debout << "cm/px: min=" << cmPerPixel_min << " max=" << cmPerPixel_max << " minRate: " << minMarkerPerimeterRate << " maxRate: " << maxMarkerPerimeterRate << endl; - }else // 2D + } + else // 2D { double cmPerPixel = mainWindow->getImageItem()->getCmPerPixel(); minMarkerPerimeterRate = (codeMarkerWidget->minMarkerPerimeter->value()*4/cmPerPixel)/max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS); maxMarkerPerimeterRate = (codeMarkerWidget->maxMarkerPerimeter->value()*4/cmPerPixel)/max(mainWindow->getImage()->width()-bS,mainWindow->getImage()->height()-bS); -// debout << "cm/px: " << cmPerPixel << " minRate: " << minMarkerPerimeterRate << " maxRate: " << maxMarkerPerimeterRate << endl; minCornerDistanceRate = codeMarkerWidget->minCornerDistance->value(); minMarkerDistanceRate = codeMarkerWidget->minMarkerDistance->value(); } -// debout << "MinMarkerPerimeterRate: " << minMarkerPerimeterRate << " MaxMarkerPerimeterRate: " << maxMarkerPerimeterRate << endl; - detectorParams->adaptiveThreshWinSizeMin = codeMarkerWidget->adaptiveThreshWinSizeMin->value(); detectorParams->adaptiveThreshWinSizeMax = codeMarkerWidget->adaptiveThreshWinSizeMax->value(); detectorParams->adaptiveThreshWinSizeStep = codeMarkerWidget->adaptiveThreshWinSizeStep->value(); @@ -1071,8 +1168,6 @@ void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidg detectorParams->minOtsuStdDev = codeMarkerWidget->minOtsuStdDev->value(); detectorParams->errorCorrectionRate = codeMarkerWidget->errorCorrectionRate->value(); - //debout << "findCodeMarker: dictID: " << codeMarkerWidget->dictList->currentIndex() << endl; // used dictionary - vector<int> ids; vector<vector<Point2f> > corners, rejected; ids.clear(); @@ -1084,26 +1179,28 @@ void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidg debout << "start detectCodeMarkers : " << getElapsedTime() <<endl; #endif -// Mat copy = cvarrToMat(img).clone(); -// debout << "img(" << bS << "): " << img << " channels: " << img->nChannels << " depth: " << img->depth << endl; -// debout << "test" << endl; + //debout << "XXX: " << img.locateROI(); aruco::detectMarkers(img/*copy.clone()*/, dictionary, corners, ids, detectorParams, rejected); -// debout << " --> ok " << endl; -// aruco::detectMarkers(cvarrToMat(img),dictionary,corners,ids); + debout << "findCodeMarker: dictID: " << codeMarkerWidget->dictList->currentIndex() << endl; // used dictionary + #ifdef TIME_MEASUREMENT // "==========: " debout << "end detectCodeMarkers : " << getElapsedTime() <<endl; #endif + + if (offsetCropRect2Roi.length()!=0) + { + codeMarkerItem->setOffsetCropRect2Roi(offsetCropRect2Roi); + } + codeMarkerItem->setDetectedMarkers(corners,ids); codeMarkerItem->setRejectedMarkers(rejected); double x,y; int i; - - - // detected code markers + // write detected code markers in crossList for(i = 0; i<ids.size(); i++) { // debout << "Detected MarkerID: " << ids.at(i) << " [( " << corners.at(i).at(0).x << "," << corners.at(i).at(0).y << "),( " @@ -1111,21 +1208,10 @@ void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidg // << corners.at(i).at(2).x << "," << corners.at(i).at(2).y << "),( " // << corners.at(i).at(3).x << "," << corners.at(i).at(3).y << ")]" << endl; -// if (codeMarkerWidget->showMask->isChecked()) -// { -// detected_points[0] = CvPoint(corners.at(i).at(0).x, corners.at(i).at(0).y); -// detected_points[1] = CvPoint(corners.at(i).at(1).x, corners.at(i).at(1).y); -// detected_points[2] = CvPoint(corners.at(i).at(2).x, corners.at(i).at(2).y); -// detected_points[3] = CvPoint(corners.at(i).at(3).x, corners.at(i).at(3).y); - -// cvFillConvexPoly(binary,detected_points,4,RGB(255,255,255)); -// } - x = (corners.at(i).at(0).x+corners.at(i).at(1).x+corners.at(i).at(2).x+corners.at(i).at(3).x)*0.25; y = (corners.at(i).at(0).y+corners.at(i).at(1).y+corners.at(i).at(2).y+corners.at(i).at(3).y)*0.25; crossList->append(TrackPoint(Vec2F(x,y), 100, ids.at(i))); // 100 beste qualitaet - } #ifdef TIME_MEASUREMENT @@ -1138,7 +1224,6 @@ void findCodeMarker(Mat &img, QList<TrackPoint> *crossList, Control *controlWidg void findContourMarker(Mat &img, QList<TrackPoint> *crossList, int markerBrightness, bool ignoreWithoutMarker, bool autoWB, int recoMethod, float headSize) { - int i, threshold, plus, count; double angle; //MarkerCasernList markerList; @@ -1562,10 +1647,8 @@ imShow("img2", tmpAusgabe2); // returns list of mid point of black crosses on white ground in region of interest roi // in image iplImg -void getMarkerPos(Mat &img, QRect &roi, QList<TrackPoint> *crossList, Control *controlWidget, - int borderSize, BackgroundFilter *bgFilter) +void getMarkerPos(Mat &img, QRect &roi, QList<TrackPoint> *crossList, Control *controlWidget, int borderSize, BackgroundFilter *bgFilter) { - int markerBrightness = controlWidget->markerBrightness->value(); bool ignoreWithoutMarker = (controlWidget->markerIgnoreWithout->checkState() == Qt::Checked); bool autoWB = (controlWidget->recoAutoWB->checkState() == Qt::Checked); diff --git a/tests/regression_test/data/multiColorMarkerWithAruco.mp4 b/tests/regression_test/data/multiColorMarkerWithAruco.mp4 new file mode 100644 index 000000000..42ad9de37 --- /dev/null +++ b/tests/regression_test/data/multiColorMarkerWithAruco.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2beb14212fb7c38b6f3d71fb213472abf79b6eb45b7a1c3e840ce72c2e2fc31c +size 961964 diff --git a/tests/regression_test/data/multiColorMarkerWithAruco.pet b/tests/regression_test/data/multiColorMarkerWithAruco.pet new file mode 100644 index 000000000..0bcad8b25 --- /dev/null +++ b/tests/regression_test/data/multiColorMarkerWithAruco.pet @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE PETRACK> +<PETRACK VERSION="0.8"> + <MAIN SRC="./multiColorMarkerWithAruco.mp4" STATUS_HEIGHT="0"/> + <CONTROL TAB="1"> + <CALIBRATION> + <BRIGHTNESS ENABLED="0" VALUE="0"/> + <CONTRAST ENABLED="0" VALUE="0"/> + <BORDER COLOR="#000000" ENABLED="0" VALUE="0"/> + <SWAP ENABLED="0" HORIZONTALLY="0" VERTICALLY="0"/> + <BG_SUB DELETE="1" DELETE_NUMBER="3" ENABLED="0" FILE="" SHOW="0" UPDATE="0"/> + <PATTERN BOARD_SIZE_X="6" BOARD_SIZE_Y="8" SQUARE_SIZE="4.5999999"/> + <INTRINSIC_PARAMETERS CX="983.10000000000002" CY="572.13" ENABLED="1" FIX_CENTER="0" FX="1860.1700000000001" FY="1862.24" K4="0" K5="0" K6="0" QUAD_ASPECT_RATIO="0" R2="-0.37733299999999997" R4="0.242947" R6="-0.15323500000000001" TANG_DIST="1" TX="-0.0040350000000000004" TY="-0.001372"/> + <EXTRINSIC_PARAMETERS ALTITUDE="535" COORD3D_AXIS_LEN="200" COORD3D_SWAP_X="0" COORD3D_SWAP_Y="0" COORD3D_SWAP_Z="0" COORD3D_TRANS_X="0" COORD3D_TRANS_Y="0" COORD3D_TRANS_Z="0" COORD_DIMENSION="0" EXTERNAL_CALIB_FILE="" EXTR_ROT_1="-2.1299999999999999" EXTR_ROT_2="2.1579999999999999" EXTR_ROT_3="-0.036999999999999998" EXTR_TRANS_1="14.253" EXTR_TRANS_2="14.198" EXTR_TRANS_3="-528.09799999999996" FIX="0" ROTATE="0" SCALE="100" SHOW="0" SHOW_CALIB_POINTS="0" TRANS_X="0" TRANS_Y="0" UNIT="100" USE_INTRINSIC_CENTER="0"/> + <ALIGNMENT_GRID FIX="0" GRID3D_RESOLUTION="100" GRID3D_TRANS_X="0" GRID3D_TRANS_Y="0" GRID3D_TRANS_Z="0" GRID_DIMENSION="0" ROTATE="0" SCALE="100" SHOW="0" TRANS_X="0" TRANS_Y="0"/> + </CALIBRATION> + <RECOGNITION> + <PERFORM ENABLED="0" METHOD="5" STEP="1"/> + <REGION_OF_INTEREST FIX="0" HEIGHT="1080" SHOW="1" WIDTH="1920" X="0" Y="0"/> + <MARKER BRIGHTNESS="50" IGNORE_WITHOUT="1"/> + <SIZE_COLOR AUTO_WB="0" DEFAULT_HEIGHT="180" GREY_LEVEL="50" MAP_NUMBER="0" MODEL="0" SHOW="1" SYMBOL_SIZE="10" X="0" Y="1" Z="255"> + <MAP COLORED="1" FROM_HUE="351" FROM_SAT="255" FROM_VAL="255" HEIGHT="188" INV_HUE="1" MAP_HEIGHT="180" TO_HUE="8" TO_SAT="67" TO_VAL="98" WIDTH="343" X="8" Y="67"/> + </SIZE_COLOR> + </RECOGNITION> + <TRACKING> + <ONLINE_CALCULATION ENABLED="0"/> + <REPEAT_BELOW ENABLED="1" QUALITY="50"/> + <EXTRAPOLATION ENABLED="1"/> + <MERGE ENABLED="0"/> + <ONLY_VISIBLE ENABLED="1"/> + <REGION_OF_INTEREST FIX="0" HEIGHT="1080" SHOW="0" WIDTH="1920" X="0" Y="0"/> + <SEARCH_MISSING_FRAMES ENABLED="1"/> + <RECALCULATE_MEDIAN_HEIGHT ENABLED="1"/> + <ALLOW_ALTERNATE_HEIGHT ENABLED="0"/> + <EXPORT_ELIMINATE_TRACKPOINT_WITHOUT_HEIGHT ENABLED="0"/> + <EXPORT_ELIMINATE_TRAJECTORY_WITHOUT_HEIGHT ENABLED="0"/> + <EXPORT_SMOOTH ENABLED="1"/> + <EXPORT_VIEWING_DIRECTION ENABLED="0"/> + <EXPORT_ANGLE_OF_VIEW ENABLED="0"/> + <EXPORT_USE_METER ENABLED="0"/> + <EXPORT_COMMENT ENABLED="0"/> + <EXPORT_MARKERID ENABLED="1"/> + <TEST_EQUAL ENABLED="1"/> + <TEST_VELOCITY ENABLED="1"/> + <TEST_INSIDE ENABLED="1"/> + <TEST_LENGTH ENABLED="1"/> + <TRACK_FILE FILENAME=""/> + <SEARCH_REGION LEVELS="3" MAX_ERROR="0" SCALE="16" SHOW="0"/> + <PATH AFTER="1500" BEFORE="1500" COLLECTIVE_COLOR_SIZE="11" COLOR_MARKER_SIZE="14" CURRENT_POINT_SIZE="60" FIX="0" GROUND_PATH_SIZE="1" GROUND_POSITION_SIZE="1" HEAD_SIZE="1" NUMBER_BOLD="1" NUMBER_SIZE="14" ONLY_PEOPLE="0" ONLY_PEOPLE_LIST="0" ONLY_PEOPLE_NR="1" ONLY_PEOPLE_NR_LIST="1" ONLY_VISIBLE="0" PATH_SIZE="2" POINTS_COLORED="1" POINTS_SIZE="7" SHOW="1" SHOW_COLLECTIVE_COLOR="1" SHOW_COLOR_MARKER="1" SHOW_CURRENT_POINT="1" SHOW_GROUND_PATH="0" SHOW_GROUND_POSITION="0" SHOW_NUMBER="1" SHOW_PATH="1" SHOW_POINTS="0" TRACK_GROUND_PATH_COLOR="#00ff00" TRACK_PATH_COLOR="#ff0000"/> + </TRACKING> + <ANALYSIS> + <SEARCH_MISSING_FRAMES ENABLED="1"/> + <MARK_ACTUAL ENABLED="0"/> + <CALCULATION ABSOLUTE="0" CONSIDER_X="0" CONSIDER_Y="1" REVERSE="0" SHOW_VORONOI="0" STEP_SIZE="25"/> + </ANALYSIS> + </CONTROL> + <STEREO> + <DISPARITY ALGO="0" COLOR="0" HIDE_INVALID="1" OPACITY="100" SHOW="0"> + <VALUES MAX="100" MIN="0"/> + <MASK EDGE_SIZE="5" SIZE="7" USE_EDGE="0"/> + <USE CALIB_CENTER="1" EXPORT="0" HEIGHT="0" HEIGHT_EVER="1" RECO="0"/> + </DISPARITY> + </STEREO> + <COLOR_MARKER> + <MASK MASK="1" OPACITY="100" SHOW="0"/> + <FROM_COLOR HUE="0" SATURATION="0" VALUE="0"/> + <TO_COLOR HUE="359" SATURATION="255" VALUE="255"/> + <PARAM CLOSE_RADIUS="5" CLOSE_USED="1" INVERS_HUE="0" MAX_AREA="5000" MAX_RATIO="2" MIN_AREA="1000" OPEN_RADIUS="5" OPEN_USED="1"/> + </COLOR_MARKER> + <CODE_MARKER> + <DICTIONARY ID="11"/> + <PARAM ADAPTIVE_THRESH_CONSTANT="7" ADAPTIVE_THRESH_WIN_SIZE_MAX="23" ADAPTIVE_THRESH_WIN_SIZE_MIN="3" ADAPTIVE_THRESH_WIN_SIZE_STEP="10" CORNER_REFINEMENT="0" CORNER_REFINEMENT_MAX_ITERATIONS="30" CORNER_REFINEMENT_MIN_ACCURACY="0.10000000000000001" CORNER_REFINEMENT_WIN_SIZE="5" ERROR_CORRECTION_RATE="0.59999999999999998" MARKER_BORDER_BITS="1" MAX_ERRONEOUS_BITS_IN_BORDER_RATE="0.34999999999999998" MAX_MARKER_PERIMETER="10" MAX_RATIO_ERROR="0.029999999999999999" MIN_CORNER_DISTANCE="0.050000000000000003" MIN_DISTANCE_TO_BORDER="3" MIN_MARKER_DISTANCE="0.050000000000000003" MIN_MARKER_PERIMETER="6" MIN_OTSU_STD_DEV="5" PERSPECTIVE_REMOVE_IGNORED_MARGIN_PER_CELL="0.13" PERSPECTIVE_REMOVE_PIXEL_PER_CELL="4" SHOW_DETECTED_CANDIDATES="1"/> + </CODE_MARKER> + <MULTI_COLOR_MARKER> + <BLACK_DOT IGNORE_WITHOUT="1" RESTRICT_POSITION="0" SIZE="5" USE="0" USE_COLOR="0"/> + <CODE_MARKER USE="1"/> + <AUTO_CORRECT ONLY_EXPORT="0" USE="1"/> + <MASK MASK="1" OPACITY="100" SHOW="0"/> + <PARAM CLOSE_RADIUS="5" CLOSE_USED="1" MAX_AREA="18000" MAX_RATIO="2" MIN_AREA="3000" OPEN_RADIUS="5" OPEN_USED="1" USE_HEAD_SIZE="0"/> + </MULTI_COLOR_MARKER> + <PLAYER FPS="50" FRAME="3" PLAYER_SPEED_FIXED="0" SOURCE_FRAME_IN="0" SOURCE_FRAME_OUT="33"/> + <VIEW ANTIALIAS="0" CAMERA="2" HIDE_CONTROLS="0" OPENGL="0" SAVE_TRANSFORMED="0" TRANSFORMATION="229 0 0 0"/> + <AUTO_TRACK BACK_TRACK="1" OPTIMZE_COLOR="0"/> +</PETRACK> diff --git a/tests/regression_test/data/multiColorMarkerWithAruco_truth.trc b/tests/regression_test/data/multiColorMarkerWithAruco_truth.trc new file mode 100644 index 000000000..74f36f022 --- /dev/null +++ b/tests/regression_test/data/multiColorMarkerWithAruco_truth.trc @@ -0,0 +1,107 @@ +version 3 +3 +0 -100000 0 33 1 -1 -1 -1 34 + +900.784 33.8529 -1 -1 -1 79 0 0 -1 -1 -1 -1 +896.631 46.038 -1 -1 -1 79 0 0 -1 -1 -1 -1 +892.569 57.9397 -1 -1 -1 100 0 0 -1 -1 -1 995 +888.478 69.6511 -1 -1 -1 100 0 0 -1 -1 -1 995 +884.19 81.1103 -1 -1 -1 100 0 0 -1 -1 -1 995 +879.625 92.0508 -1 -1 -1 100 0 0 -1 -1 -1 995 +875.245 103.532 -1 -1 -1 100 0 0 -1 -1 -1 995 +870.435 114.729 -1 -1 -1 100 0 0 -1 -1 -1 995 +865.585 125.211 -1 -1 -1 100 0 0 -1 -1 -1 995 +860.228 136.17 -1 -1 -1 100 0 0 -1 -1 -1 995 +855.134 146.879 -1 -1 -1 100 0 0 -1 -1 -1 995 +849.278 156.587 -1 -1 -1 100 0 0 -1 -1 -1 995 +843.666 166.782 -1 -1 -1 100 0 0 -1 -1 -1 995 +837.8 176.983 -1 -1 -1 100 0 0 -1 -1 -1 995 +831.702 186.424 -1 -1 -1 100 0 0 -1 -1 -1 995 +825.064 195.871 -1 -1 -1 100 0 0 -1 -1 -1 995 +818.424 204.631 -1 -1 -1 79 0 0 -1 -1 -1 -1 +811.343 212.987 -1 -1 -1 100 0 0 -1 -1 -1 995 +804.717 221.667 -1 -1 -1 100 0 0 -1 -1 -1 995 +797.839 229.823 -1 -1 -1 100 0 0 -1 -1 -1 995 +791.431 237.982 -1 -1 -1 100 0 0 -1 -1 -1 995 +784.537 245.64 -1 -1 -1 100 0 0 -1 -1 -1 995 +777.4 253.545 -1 -1 -1 100 0 0 -1 -1 -1 995 +770.513 261.181 -1 -1 -1 100 0 0 -1 -1 -1 995 +762.857 268.066 -1 -1 -1 100 0 0 -1 -1 -1 995 +754.961 274.928 -1 -1 -1 100 0 0 -1 -1 -1 995 +746.559 281.546 -1 -1 -1 100 0 0 -1 -1 -1 995 +737.911 287.42 -1 -1 -1 100 0 0 -1 -1 -1 995 +729.507 293.25 -1 -1 -1 100 0 0 -1 -1 -1 995 +721.098 298.109 -1 -1 -1 100 0 0 -1 -1 -1 995 +712.434 303.45 -1 -1 -1 100 0 0 -1 -1 -1 995 +703.771 308.076 -1 -1 -1 100 0 0 -1 -1 -1 995 +694.867 312.361 -1 -1 -1 100 0 0 -1 -1 -1 995 +686.169 316.745 -1 -1 -1 100 0 0 -1 -1 -1 995 + +0 -100000 0 33 1 -1 -1 -1 34 + +1267.33 1055.12 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1260.08 1043.24 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1253.1 1031.09 -1 -1 -1 100 0 0 -1 -1 -1 999 +1246.03 1018.41 -1 -1 -1 100 0 0 -1 -1 -1 999 +1239.17 1005.49 -1 -1 -1 100 0 0 -1 -1 -1 999 +1233.34 993.063 -1 -1 -1 100 0 0 -1 -1 -1 999 +1227.26 980.141 -1 -1 -1 100 0 0 -1 -1 -1 999 +1221.93 967.201 -1 -1 -1 100 0 0 -1 -1 -1 999 +1216.35 954.78 -1 -1 -1 100 0 0 -1 -1 -1 999 +1211.01 941.569 -1 -1 -1 100 0 0 -1 -1 -1 999 +1205.68 928.894 -1 -1 -1 100 0 0 -1 -1 -1 999 +1199.59 916.202 -1 -1 -1 100 0 0 -1 -1 -1 999 +1194 903.999 -1 -1 -1 100 0 0 -1 -1 -1 999 +1187.91 891.288 -1 -1 -1 100 0 0 -1 -1 -1 999 +1181.81 878.597 -1 -1 -1 100 0 0 -1 -1 -1 999 +1175.71 866.398 -1 -1 -1 100 0 0 -1 -1 -1 999 +1169.36 853.184 -1 -1 -1 100 0 0 -1 -1 -1 999 +1162.51 841.215 -1 -1 -1 100 0 0 -1 -1 -1 999 +1156.17 828.474 -1 -1 -1 100 0 0 -1 -1 -1 999 +1149.3 816.547 -1 -1 -1 100 0 0 -1 -1 -1 999 +1142.45 804.047 -1 -1 -1 100 0 0 -1 -1 -1 999 +1135.84 791.868 -1 -1 -1 100 0 0 -1 -1 -1 999 +1128.72 779.899 -1 -1 -1 100 0 0 -1 -1 -1 999 +1121.1 767.884 -1 -1 -1 100 0 0 -1 -1 -1 999 +1114.24 755.197 -1 -1 -1 100 0 0 -1 -1 -1 999 +1106.37 742.221 -1 -1 -1 100 0 0 -1 -1 -1 999 +1099 730.248 -1 -1 -1 100 0 0 -1 -1 -1 999 +1090.88 718.514 -1 -1 -1 100 0 0 -1 -1 -1 999 +1083.49 706.8 -1 -1 -1 100 0 0 -1 -1 -1 999 +1074.61 695.602 -1 -1 -1 100 0 0 -1 -1 -1 999 +1066.22 685.161 -1 -1 -1 100 0 0 -1 -1 -1 999 +1056.83 674.73 -1 -1 -1 100 0 0 -1 -1 -1 999 +1047.42 665.8 -1 -1 -1 100 0 0 -1 -1 -1 999 +1037.77 656.89 -1 -1 -1 100 0 0 -1 -1 -1 999 + +0 -100000 6 33 1 -1 -1 -1 28 + +1910.71 405.338 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1896.54 404.094 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1883.16 402.965 -1 -1 -1 100 0 0 -1 -1 -1 997 +1870.03 401.696 -1 -1 -1 100 0 0 -1 -1 -1 997 +1857.13 400.935 -1 -1 -1 100 0 0 -1 -1 -1 997 +1844.46 399.39 -1 -1 -1 100 0 0 -1 -1 -1 997 +1831.76 397.767 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1818.64 396.132 -1 -1 -1 100 0 0 -1 -1 -1 997 +1805.5 394.541 -1 -1 -1 100 0 0 -1 -1 -1 997 +1792.38 393.357 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1779.55 392.039 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1765.97 390.794 -1 -1 -1 100 0 0 -1 -1 -1 997 +1752.43 389.784 -1 -1 -1 79 0 0 -1 -1 -1 -1 +1737.87 389.258 -1 -1 -1 100 0 0 -1 -1 -1 997 +1723.67 389.24 -1 -1 -1 100 0 0 -1 -1 -1 997 +1708.71 388.477 -1 -1 -1 100 0 0 -1 -1 -1 997 +1693.8 387.976 -1 -1 -1 100 0 0 -1 -1 -1 997 +1678.3 388.733 -1 -1 -1 100 0 0 -1 -1 -1 997 +1662.85 388.989 -1 -1 -1 100 0 0 -1 -1 -1 997 +1646.88 388.962 -1 -1 -1 100 0 0 -1 -1 -1 997 +1631.15 389.467 -1 -1 -1 100 0 0 -1 -1 -1 997 +1614.93 389.973 -1 -1 -1 100 0 0 -1 -1 -1 997 +1599.44 390.728 -1 -1 -1 100 0 0 -1 -1 -1 997 +1583.74 391.26 -1 -1 -1 100 0 0 -1 -1 -1 997 +1567.98 391.756 -1 -1 -1 100 0 0 -1 -1 -1 997 +1552.5 392.773 -1 -1 -1 100 0 0 -1 -1 -1 997 +1537.5 394.785 -1 -1 -1 100 0 0 -1 -1 -1 997 +1522.74 396.056 -1 -1 -1 100 0 0 -1 -1 -1 997 + diff --git a/tests/regression_test/data/multiColorMarkerWithAruco_truth.txt b/tests/regression_test/data/multiColorMarkerWithAruco_truth.txt new file mode 100644 index 000000000..54d8b71e5 --- /dev/null +++ b/tests/regression_test/data/multiColorMarkerWithAruco_truth.txt @@ -0,0 +1,103 @@ +# PeTrack project: multiColorMarkerWithAruco.pet +# raw trajectory file: multiColorMarkerWithAruco_truth.trc +# framerate: 50 fps +# z: can be 3d position or height of person (alternating or not) +# id frame x/cm y/cm z/cm markerID +1 0 64.0957 -32.8595 180 -1 +1 1 61.8771 -32.065 180 -1 +1 2 59.7093 -31.2876 180 995 +1 3 57.5753 -30.5049 180 995 +1 4 55.4861 -29.6864 180 995 +1 5 53.4902 -28.8179 180 995 +1 6 51.3958 -27.9817 180 995 +1 7 49.3518 -27.067 180 995 +1 8 47.4376 -26.1464 180 995 +1 9 45.4357 -25.131 180 995 +1 10 43.4793 -24.1646 180 995 +1 11 41.7043 -23.0603 180 995 +1 12 39.8405 -21.9996 180 995 +1 13 37.9754 -20.892 180 995 +1 14 36.249 -19.7437 180 995 +1 15 34.5209 -18.4963 180 995 +1 16 32.9185 -17.2503 180 -1 +1 17 31.3898 -15.9245 180 995 +1 18 29.8023 -14.6818 180 995 +1 19 28.3107 -13.3945 180 995 +1 20 26.819 -12.1937 180 995 +1 21 25.4188 -10.9054 180 995 +1 22 23.9739 -9.57197 180 995 +1 23 22.5785 -8.28553 180 995 +1 24 21.3206 -6.86069 180 995 +1 25 20.0674 -5.3926 180 995 +1 26 18.8594 -3.83325 180 995 +1 27 17.7879 -2.2319 180 995 +1 28 16.7251 -0.676197 180 995 +1 29 15.8401 0.876465 180 995 +1 30 14.8676 2.47645 180 995 +1 31 14.0262 4.07291 180 995 +1 32 13.2476 5.71113 180 995 +1 33 12.4516 7.31118 180 995 +2 0 -130.147 -101.549 180 -1 +2 1 -127.743 -100.118 180 -1 +2 2 -125.296 -98.7426 180 999 +2 3 -122.744 -97.3508 180 999 +2 4 -120.153 -96.0033 180 999 +2 5 -117.67 -94.8595 180 999 +2 6 -115.091 -93.6703 180 999 +2 7 -112.518 -92.6287 180 999 +2 8 -110.048 -91.5395 180 999 +2 9 -107.429 -90.5008 180 999 +2 10 -104.919 -89.4635 180 999 +2 11 -102.404 -88.2802 180 999 +2 12 -99.9904 -87.1949 180 999 +2 13 -97.4787 -86.0141 180 999 +2 14 -94.9744 -84.8335 180 999 +2 15 -92.5693 -83.6533 180 999 +2 16 -89.9693 -82.4276 180 999 +2 17 -87.6115 -81.106 180 999 +2 18 -85.1109 -79.8863 180 999 +2 19 -82.7681 -78.5632 180 999 +2 20 -80.3185 -77.2475 180 999 +2 21 -77.9358 -75.9796 180 999 +2 22 -75.5943 -74.616 180 999 +2 23 -73.245 -73.1571 180 999 +2 24 -70.7741 -71.8482 180 999 +2 25 -68.2469 -70.3471 180 999 +2 26 -65.9181 -68.9433 180 999 +2 27 -63.6354 -67.3955 180 999 +2 28 -61.3633 -65.9929 180 999 +2 29 -59.1865 -64.3039 180 999 +2 30 -57.16 -62.712 180 999 +2 31 -55.1343 -60.9307 180 999 +2 32 -53.3974 -59.1473 180 999 +2 33 -51.6659 -57.3185 180 999 +3 4 -5.58845 -225.291 180 -1 +3 5 -5.48353 -226.078 180 -1 +3 6 -5.37857 -226.865 180 -1 +3 7 -5.27357 -227.652 180 -1 +3 8 -5.03274 -224.882 180 997 +3 9 -4.7651 -222.165 180 997 +3 10 -4.59735 -219.502 180 997 +3 11 -4.27741 -216.887 180 997 +3 12 -3.94262 -214.27 180 -1 +3 13 -3.60555 -211.57 180 997 +3 14 -3.27728 -208.87 180 997 +3 15 -3.02887 -206.18 180 -1 +3 16 -2.75494 -203.552 180 -1 +3 17 -2.49464 -200.776 180 997 +3 18 -2.28043 -198.012 180 -1 +3 19 -2.15891 -195.048 180 997 +3 20 -2.13635 -192.161 180 997 +3 21 -1.96884 -189.124 180 997 +3 22 -1.85218 -186.101 180 997 +3 23 -1.97774 -182.969 180 997 +3 24 -2.00668 -179.849 180 997 +3 25 -1.98034 -176.63 180 997 +3 26 -2.05672 -173.465 180 997 +3 27 -2.13244 -170.207 180 997 +3 28 -2.257 -167.1 180 997 +3 29 -2.33831 -163.957 180 997 +3 30 -2.41245 -160.806 180 997 +3 31 -2.5867 -157.719 180 997 +3 32 -2.95226 -154.732 180 997 +3 33 -3.1756 -151.795 180 997 diff --git a/tests/regression_test/tests/conftest.py b/tests/regression_test/tests/conftest.py index adc13b6ce..1eb34e81b 100644 --- a/tests/regression_test/tests/conftest.py +++ b/tests/regression_test/tests/conftest.py @@ -9,7 +9,7 @@ def pytest_addoption(parser): # "codeMarker" -@pytest.fixture(params=["markerCasern", "multicolor", "markerJapan"], scope='session') +@pytest.fixture(params=["markerCasern", "multicolor", "markerJapan", "multiColorMarkerWithAruco"], scope='session') def petrack_on_testdata(request, pytestconfig): petrack_path = pytestconfig.getoption("path") diff --git a/ui/control.ui b/ui/control.ui index 5a3791752..e64b965b1 100644 --- a/ui/control.ui +++ b/ui/control.ui @@ -71,7 +71,7 @@ <enum>Qt::LeftToRight</enum> </property> <property name="currentIndex"> - <number>2</number> + <number>1</number> </property> <property name="tabsClosable"> <bool>false</bool> @@ -121,8 +121,8 @@ <rect> <x>0</x> <y>0</y> - <width>337</width> - <height>1028</height> + <width>342</width> + <height>1081</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_13"> @@ -3211,8 +3211,8 @@ <rect> <x>0</x> <y>0</y> - <width>337</width> - <height>874</height> + <width>342</width> + <height>876</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_16"> @@ -4447,8 +4447,8 @@ <rect> <x>0</x> <y>0</y> - <width>337</width> - <height>843</height> + <width>342</width> + <height>863</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_17"> @@ -7199,8 +7199,8 @@ <rect> <x>0</x> <y>0</y> - <width>354</width> - <height>558</height> + <width>356</width> + <height>310</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_18"> diff --git a/ui/multiColorMarker.ui b/ui/multiColorMarker.ui index 796613f64..4a6e46f5d 100644 --- a/ui/multiColorMarker.ui +++ b/ui/multiColorMarker.ui @@ -7,14 +7,37 @@ <x>0</x> <y>0</y> <width>369</width> - <height>370</height> + <height>390</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="dotSize"> + <property name="minimum"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>5.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> <item row="0" column="0"> <widget class="QCheckBox" name="useDot"> <property name="toolTip"> @@ -28,18 +51,18 @@ </property> </widget> </item> - <item row="0" column="1"> - <widget class="QDoubleSpinBox" name="dotSize"> - <property name="minimum"> - <double>0.100000000000000</double> + <item row="1" column="0"> + <widget class="QCheckBox" name="useCodeMarker"> + <property name="toolTip"> + <string>using Code Marker on top of the head for tracking</string> </property> - <property name="value"> - <double>5.000000000000000</double> + <property name="text"> + <string>use Code Marker</string> </property> </widget> </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer_2"> + <item row="1" column="2"> + <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -51,9 +74,16 @@ </property> </spacer> </item> + <item row="1" column="1"> + <widget class="QPushButton" name="CodeMarkerParameter"> + <property name="text"> + <string>parameter</string> + </property> + </widget> + </item> </layout> </item> - <item> + <item row="1" column="0"> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="1"> <widget class="QCheckBox" name="ignoreWithoutDot"> @@ -61,7 +91,7 @@ <string>ignore head without black dot, if not visible / surrounded by color</string> </property> <property name="text"> - <string>ignore head without black dot</string> + <string>ignore head without black dot or Code Marker</string> </property> <property name="checked"> <bool>true</bool> -- GitLab