diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a8c16936cebf4110bc42dcd3534ba1e4789ded4..b4fe811d50f5dac5f0b4e03c2a5b83ea4f199e94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -393,9 +393,12 @@ target_sources(petrack_core PRIVATE include/logwindow.h include/extrinsicBox.h include/extrinsicParameters.h + include/coordinateSystemBox.h + include/worldImageCorrespondence.h include/autosaveSettings.h include/editMoCapDialog.h include/moCapEditingWidget.h + include/coordinateStructs.h ) target_sources(petrack_core PRIVATE @@ -465,8 +468,10 @@ target_sources(petrack_core PRIVATE src/logwindow.cpp src/extrinsicBox.cpp src/autosaveSettings.cpp + src/coordinateSystemBox.cpp src/editMoCapDialog.cpp src/moCapEditingWidget.cpp + ui/coordinateSystemBox.ui ui/moCapEditingWidget.ui ui/editMoCapDialog.ui ui/about.ui diff --git a/include/control.h b/include/control.h index 1d060350d24c4ac4a23b67316848d43f674ac3c0..bcec87127fa3764c239ac8014ba7f0365e897414 100644 --- a/include/control.h +++ b/include/control.h @@ -19,11 +19,8 @@ #ifndef CONTROL_H #define CONTROL_H -#include "analysePlot.h" -#include "colorPlot.h" -#include "extrinsicParameters.h" +#include "coordinateStructs.h" #include "intrinsicCameraParams.h" -#include "petrack.h" #include "recognition.h" #include <Qt> @@ -33,7 +30,16 @@ class QGraphicsScene; class QDomElement; class IntrinsicBox; class ExtrinsicBox; +struct ExtrinsicParameters; class FilterBeforeBox; +class Petrack; +class RoiItem; +class RectPlotItem; +class CoordinateSystemBox; +class ColorPlot; +class AnalysePlot; +class MissingFrames; +class WorldImageCorrespondence; namespace Ui { class Control; @@ -45,22 +51,28 @@ class Control : public QWidget public: Control( - QWidget &parent, - QGraphicsScene &scene, - reco::Recognizer &recognizer, - RoiItem &trackRoiItem, - RoiItem &recoRoiItem, - MissingFrames &missingFrames, - FilterBeforeBox *filterBefore); + QWidget &parent, + QGraphicsScene &scene, + reco::Recognizer &recognizer, + RoiItem &trackRoiItem, + RoiItem &recoRoiItem, + MissingFrames &missingFrames, + FilterBeforeBox *filterBefore, + IntrinsicBox *intrinsicBox, + ExtrinsicBox *extrinsicBox, + CoordinateSystemBox *coordSysBox); Control( - QWidget &parent, - QGraphicsScene &scene, - reco::Recognizer &recognizer, - RoiItem &trackRoiItem, - RoiItem &recoRoiItem, - Ui::Control *ui, - MissingFrames &missingFrames, - FilterBeforeBox *filterBefore); + QWidget &parent, + QGraphicsScene &scene, + reco::Recognizer &recognizer, + RoiItem &trackRoiItem, + RoiItem &recoRoiItem, + Ui::Control *ui, + MissingFrames &missingFrames, + FilterBeforeBox *filterBefore, + IntrinsicBox *intrinsicBox, + ExtrinsicBox *extrinsicBox, + CoordinateSystemBox *coordSysBox); void setScene(QGraphicsScene *sc); @@ -152,53 +164,20 @@ public: double getCalibReprError() const; void setCalibReprError(double d); - void imageSizeChanged(int width, int height, int borderDiff); const ExtrinsicParameters &getExtrinsicParameters() const; - int getCalibCoordDimension(); - bool getCalibExtrCalibPointsShow(); - bool getCalibExtrVanishPointsShow(); - bool getCalibCoordShow(); - void setCalibCoordShow(bool b); - bool getCalibCoordFix(); - void setCalibCoordFix(bool b); - bool getIs3DView(); - void setIs3DView(bool b); - int getCalibCoordRotate(); - void setCalibCoordRotate(int i); - int getCalibCoordTransX(); - void setCalibCoordTransX(int i); - int getCalibCoordTransXMax(); - void setCalibCoordTransXMax(int i); - int getCalibCoordTransXMin(); - void setCalibCoordTransXMin(int i); - int getCalibCoordTransY(); - void setCalibCoordTransY(int i); - int getCalibCoordTransYMax(); - void setCalibCoordTransYMax(int i); - int getCalibCoordTransYMin(); - void setCalibCoordTransYMin(int i); - int getCalibCoordScale(); - void setCalibCoordScale(int i); - double getCalibCoordUnit(); - void setCalibCoordUnit(double d); - bool isCoordUseIntrinsicChecked() const; - - int getCalibCoord3DTransX(); - void setCalibCoord3DTransX(int i); - int getCalibCoord3DTransY(); - void setCalibCoord3DTransY(int i); - int getCalibCoord3DTransZ(); - void setCalibCoord3DTransZ(int i); - int getCalibCoord3DAxeLen(); - void setCalibCoord3DAxeLen(int i); - bool getCalibCoord3DSwapX(); - void setCalibCoord3DSwapX(bool b); - bool getCalibCoord3DSwapY(); - void setCalibCoord3DSwapY(bool b); - bool getCalibCoord3DSwapZ(); - void setCalibCoord3DSwapZ(bool b); + const WorldImageCorrespondence &getWorldImageCorrespondence() const; + void setCalibCoord2DTransMinMax(Vec2F min, Vec2F max); + Vec2F getCalibCoord2DTrans(); + + Vec3F getCalibCoord3DTrans() const; + SwapAxis getCalibCoord3DSwap() const; + + int getCalibCoordDimension(); + bool getCalibCoordShow(); + int getCalibCoordScale(); + int getCalibGridDimension(); bool getCalibGridShow(); @@ -233,7 +212,7 @@ public: void setXml(QDomElement &elem); void getXml(const QDomElement &elem); - bool isLoading() const { return mMainWindow->isLoading(); } + bool isLoading() const; ColorPlot *getColorPlot() const; void replotColorplot(); @@ -542,18 +521,6 @@ private slots: void on_intrinsicParamsChanged(IntrinsicCameraParams params); - void on_coordShow_stateChanged(int i); - void on_coordFix_stateChanged(int i); - void on_coordRotate_valueChanged(int i); - void on_coordTransX_valueChanged(int i); - void on_coordTransY_valueChanged(int i); - void on_coordScale_valueChanged(int i); - void on_coordAltitude_valueChanged(double d); - void on_coordUnit_valueChanged(double d); - void on_coordUseIntrinsic_stateChanged(int i); - - void setMeasuredAltitude(); - void on_gridShow_stateChanged(int i); void on_gridFix_stateChanged(int i); void on_gridRotate_valueChanged(int i); @@ -562,23 +529,11 @@ private slots: void on_gridScale_valueChanged(int i); void on_gridTab_currentChanged(int index); - void on_coordTab_currentChanged(int index); - - void on_extCalibPointsShow_stateChanged(int arg1); - void on_extVanishPointsShow_stateChanged(int arg1); void on_grid3DTransX_valueChanged(int value); void on_grid3DTransY_valueChanged(int value); void on_grid3DTransZ_valueChanged(int value); void on_grid3DResolution_valueChanged(int value); - void on_coord3DTransX_valueChanged(int value); - void on_coord3DTransY_valueChanged(int value); - void on_coord3DTransZ_valueChanged(int value); - void on_coord3DAxeLen_valueChanged(int value); - - void on_coord3DSwapX_stateChanged(int arg1); - void on_coord3DSwapY_stateChanged(int arg1); - void on_coord3DSwapZ_stateChanged(int arg1); void on_trackPathColorButton_clicked(); void on_trackGroundPathColorButton_clicked(); @@ -604,17 +559,23 @@ private slots: void toggleRecoROIButtons(); void toggleTrackROIButtons(); +public slots: + void imageSizeChanged(int width, int height, int borderDiff); + + signals: void userChangedRecoMethod(reco::RecognitionMethod method); + private: - Petrack *mMainWindow; - Ui::Control *mUi; - IntrinsicBox *mIntr; - FilterBeforeBox *mFilterBefore; - ExtrinsicBox *mExtr; - QGraphicsScene *mScene; - bool mColorChanging; + Petrack *mMainWindow; + Ui::Control *mUi; + IntrinsicBox *mIntr; + FilterBeforeBox *mFilterBefore; + ExtrinsicBox *mExtr; + CoordinateSystemBox *mCoordSys; + QGraphicsScene *mScene; + bool mColorChanging; bool mIndexChanging; // shows, if the index of the color model is really changing; nor while constructor (initialer // durchlauf) and may be while loading xml file bool mLoading; // shows, if new project is just loading diff --git a/include/coordItem.h b/include/coordItem.h index 937b786d706573b59b315573746cc8ec4b73a45a..8da4f07f9a0ac1fd6133fb3446167d96cb10cadf 100644 --- a/include/coordItem.h +++ b/include/coordItem.h @@ -26,37 +26,42 @@ class Petrack; class Control; class ExtrCalibration; +class CoordinateSystemBox; +struct CoordPose2D; +struct CoordPose3D; -class CoordItem : public QGraphicsItem +class CoordItem : public QGraphicsObject { private: - Petrack *mMainWindow; - ExtrCalibration *extCalib; - Control *mControlWidget; - cv::Point2f ursprung, x, y, z; - cv::Point2f calibPointsMin, calibPointsMax; - cv::Point3f x3D, y3D, z3D; - float mouse_x, mouse_y; - int coordTrans_x, coordTrans_y; - int coordDimension; + Petrack *mMainWindow; + ExtrCalibration *extCalib; + Control *mControlWidget; + CoordinateSystemBox *mCoordSys; + QRectF mBoundingRect; + cv::Point3f x3D, y3D, z3D; + float mouse_x, mouse_y; + int coordTrans_x, coordTrans_y; + int coordDimension; public: inline void setCoordDimension(int dim) { this->coordDimension = dim; } inline int getCoordDimension() const { return this->coordDimension; } - CoordItem(QWidget *wParent, QGraphicsItem *parent = nullptr); + CoordItem(QWidget *wParent, QGraphicsItem *parent, CoordinateSystemBox *coordSys); - void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; - // Update the transformation matrix - void updateData(); // defines the minimal rect which contains the coordinate system - QRectF boundingRect() const; + QRectF boundingRect() const override; // paint method to draw the perspectiv coordinate-system - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + +private slots: + // Update the transformation matrix + void updateData(); }; #endif diff --git a/include/coordinateStructs.h b/include/coordinateStructs.h new file mode 100644 index 0000000000000000000000000000000000000000..85a3f3871388e7f82d6eb5aace41ae2c6b21a757 --- /dev/null +++ b/include/coordinateStructs.h @@ -0,0 +1,50 @@ +/* + * PeTrack - Software for tracking pedestrians movement in videos + * Copyright (C) 2023 Forschungszentrum JĂĽlich GmbH, IAS-7 + * + * 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/>. + */ + +#ifndef COORDINATESTRUCTS_H +#define COORDINATESTRUCTS_H + +#include "vector.h" + +struct CoordPose2D +{ + Vec2F position; + double angle; + double scale; + double unit; +}; + +struct SwapAxis +{ + bool x; + bool y; + bool z; +}; + +inline bool operator==(const SwapAxis &lhs, const SwapAxis &rhs) +{ + return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); +} + +struct CoordPose3D +{ + Vec3F position; + SwapAxis swap; +}; + +#endif // COORDINATESTRUCTS_H diff --git a/include/coordinateSystemBox.h b/include/coordinateSystemBox.h new file mode 100644 index 0000000000000000000000000000000000000000..88061777318d43b49074b1d1be909275a5475e6e --- /dev/null +++ b/include/coordinateSystemBox.h @@ -0,0 +1,173 @@ +/* + * PeTrack - Software for tracking pedestrians movement in videos + * Copyright (C) 2023 Forschungszentrum JĂĽlich GmbH, IAS-7 + * + * 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/>. + */ + +#ifndef COORDINATESYSTEMBOX_H +#define COORDINATESYSTEMBOX_H + +#include "coordinateStructs.h" +#include "vector.h" +#include "worldImageCorrespondence.h" + +#include <QGroupBox> +#include <QRectF> +#include <QTransform> +#include <opencv2/core/base.hpp> + +namespace Ui +{ +class CoordinateSystemBox; +} +class IntrinsicBox; +class ExtrinsicBox; +class ImageItem; +class CoordItem; +class ExtrCalibration; +class QDomElement; + +struct CoordItemState +{ + bool isMovable; + QTransform matrix; + QRectF boundingRect; + int coordDimension; + cv::Point3f x3D; + cv::Point3f y3D; + cv::Point3f z3D; +}; + +class CoordinateSystemBox : public QGroupBox, public WorldImageCorrespondence +{ + Q_OBJECT + +public: + explicit CoordinateSystemBox( + QWidget *parent, + std::function<void()> updateStatusPos, + std::function<void()> updateHeadSize, + std::function<int()> getBorderSizeCallback, + const IntrinsicBox &intrinsicBox, + ExtrinsicBox &extrinsicBox, + const ImageItem &imageItem, + const ExtrCalibration &extrCalib); + explicit CoordinateSystemBox( + QWidget *parent, + Ui::CoordinateSystemBox *ui, + std::function<void()> updateStatusPos, + std::function<void()> updateHeadSize, + std::function<int()> getBorderSizeCallback, + const IntrinsicBox &intrinsicBox, + ExtrinsicBox &extrinsicBox, + const ImageItem &imageItem, + const ExtrCalibration &extrCalib); + CoordinateSystemBox(const CoordinateSystemBox &) = delete; + CoordinateSystemBox(CoordinateSystemBox &&) = delete; + CoordinateSystemBox &operator=(const CoordinateSystemBox &) = delete; + CoordinateSystemBox &operator=(CoordinateSystemBox &&) = delete; + ~CoordinateSystemBox() override; + + const CoordPose2D &getCoordPose2D() const { return mPose2D; } + Vec2F getCoordTrans2D() const { return mPose2D.position; } + void setCoordTrans2D(Vec2F trans); + std::pair<Vec2F, Vec2F> getCoordTrans2DMinMax() const; + void setCoordTrans2DMinMax(const Vec2F &min, const Vec2F &max); + void setCoordPose2D(const CoordPose2D &pose); + double getCameraAltitude() const; + bool isCoordUseIntrinsicChecked() const; + + Vec3F getCoordTrans3D() const { return mPose3D.position; } + void setCoordTrans3D(Vec3F trans); + SwapAxis getSwap3D() const { return mPose3D.swap; } + int getCoord3DAxeLen() const; + void setCoord3DAxeLen(int newLength); + + int getCalibCoordDimension() const; + bool getCalibExtrCalibPointsShow() const; + bool getCalibExtrVanishPointsShow() const; + bool getCalibCoordShow() const; + bool getCalibCoordFix() const; + int getCalibCoordRotate() const; + void setCalibCoordRotate(int newVal); + void setMeasuredAltitude(); + + // WorldImageCorrespondence Interface + double getCmPerPixel() const override; + QPointF getCmPerPixel(float px, float py, float h = 0.) const override; + double getAngleToGround(float px, float py, float h = 0) const override; + QPointF getPosImage(QPointF pos, float height = 0.) const override; + QPointF getPosReal(QPointF pos, double height = 0.) const override; + + bool getXml(const QDomElement &subSubElem); + void setXml(QDomElement &subSubElem) const; + + CoordItemState getCoordItemState(); + +private: + void setCalibCoordTransXMax(int max); + void setCalibCoordTransYMax(int max); + +public slots: + void updateCoordItem(); + +private slots: + // selection + void on_coordTab_currentChanged(int index); + void on_coordShow_stateChanged(int i); + void on_coordFix_stateChanged(int i); + + // 2D + void on_coordRotate_valueChanged(int newAngle); + void on_coordTransX_valueChanged(int newX); + void on_coordTransY_valueChanged(int newY); + void on_coordScale_valueChanged(int newScale); + void on_coordAltitude_valueChanged(double d); + void on_coordUnit_valueChanged(double newUnit); + void on_coordUseIntrinsic_stateChanged(int i); + + + // 3D + void on_coord3DTransX_valueChanged(int newX); + void on_coord3DTransY_valueChanged(int newY); + void on_coord3DTransZ_valueChanged(int newZ); + void on_coord3DAxeLen_valueChanged(int value); + + void on_coord3DSwapX_stateChanged(int newSwap); + void on_coord3DSwapY_stateChanged(int newSwap); + void on_coord3DSwapZ_stateChanged(int newSwap); + + // display of extrinsic calibration + void on_extCalibPointsShow_stateChanged(int arg1); + void on_extVanishPointsShow_stateChanged(int arg1); + +signals: + void coordDataChanged(); + +private: + Ui::CoordinateSystemBox *mUi; + std::function<void()> mUpdateStatusPos; + std::function<void()> mUpdateHeadSize; + std::function<int()> mGetBorderSize; + const IntrinsicBox &mIntr; + ExtrinsicBox &mExtrBox; + const ImageItem &mImageItem; + const ExtrCalibration &mExtrCalib; + QTransform mCoordTransform; + CoordPose2D mPose2D; + CoordPose3D mPose3D; +}; + +#endif // COORDINATESYSTEMBOX_H diff --git a/include/extrCalibration.h b/include/extrCalibration.h index 41490d37fb2d8273a3d99a9be7fb26852c72166e..4c8915776f47edcb135793af24f6ab9eca5394cc 100644 --- a/include/extrCalibration.h +++ b/include/extrCalibration.h @@ -162,7 +162,7 @@ public: ~ExtrCalibration(); void setMainWindow(Petrack *mw); bool isEmptyExtrCalibFile(); - bool isSetExtrCalib(); + bool isSetExtrCalib() const { return true; } void setExtrCalibFile(const QString &f); QString getExtrCalibFile(); std::optional<ExtrinsicParameters> openExtrCalibFile(); @@ -171,15 +171,17 @@ public: std::optional<ExtrinsicParameters> fetch2DPoints(); std::optional<ExtrinsicParameters> calibExtrParams(); bool calcReprojectionError(); - virtual cv::Point2f getImagePoint(cv::Point3f p3d); + virtual cv::Point2f getImagePoint(cv::Point3f p3d) const; cv::Point3f get3DPoint(const cv::Point2f &p2d, double h) const; cv::Point3f transformRT(cv::Point3f p); cv::Vec3d camToWorldRotation(const cv::Vec3d &vec) const; - bool isOutsideImage(cv::Point2f p2d); + bool isOutsideImage(cv::Point2f p2d) const; inline bool isOutsideImage(cv::Point3f p3d) { return isOutsideImage(getImagePoint(p3d)); } - inline std::vector<cv::Point3f> get3DList() { return points3D; } + inline std::vector<cv::Point3f> get3DList() const { return points3D; } + inline std::vector<cv::Point3f> &get3DList() { return points3D; } inline void set3DList(std::vector<cv::Point3f> list3D) { this->points3D = list3D; } - inline std::vector<cv::Point2f> get2DList() { return points2D; } + inline std::vector<cv::Point2f> get2DList() const { return points2D; } + inline std::vector<cv::Point2f> &get2DList() { return points2D; } inline void set2DList(std::vector<cv::Point2f> list2D) { this->points2D = list2D; } inline float getCamHeight() const { return camHeight; } inline void setCamHeight(float cHeight) { this->camHeight = cHeight; } diff --git a/include/extrinsicBox.h b/include/extrinsicBox.h index fd50a615d1002dfcd8176272f472bbe57f70068e..6f4a356d1356541f1f9f5b45d2d2fba1e43fc1e9 100644 --- a/include/extrinsicBox.h +++ b/include/extrinsicBox.h @@ -36,12 +36,8 @@ class ExtrinsicBox : public QGroupBox Q_OBJECT public: - explicit ExtrinsicBox( - QWidget *parent, - Ui::extr *ui, - ExtrCalibration &extrCalib, - std::function<void()> updateCoordCallback); - explicit ExtrinsicBox(QWidget *parent, ExtrCalibration &extrCalib, std::function<void()> updateCoordCallback); + explicit ExtrinsicBox(QWidget *parent, Ui::extr *ui, ExtrCalibration &extrCalib); + explicit ExtrinsicBox(QWidget *parent, ExtrCalibration &extrCalib); ExtrinsicBox(const ExtrinsicBox &other) = delete; ExtrinsicBox(ExtrinsicBox &&other) = delete; ExtrinsicBox &operator=(const ExtrinsicBox &other) = delete; @@ -55,6 +51,10 @@ public: bool getXml(QDomElement &subSubElem); void setXml(QDomElement &subElem) const; +signals: + void enabledChanged(bool enabled); + void extrinsicChanged(); + private slots: void on_extrCalibFetch_clicked(); @@ -73,10 +73,9 @@ private slots: void on_extrCalibShowError_clicked(); private: - Ui::extr *mUi; - ExtrCalibration &mExtrCalibration; - ExtrinsicParameters mParams; - std::function<void()> mUpdateCoordCallback; + Ui::extr *mUi; + ExtrCalibration &mExtrCalibration; + ExtrinsicParameters mParams; }; #endif // EXTRINSICBOX_H diff --git a/include/gridItem.h b/include/gridItem.h index 8e71993650ef81fd939242e02ff234ae056ebe9f..40a81200c19edbf617e46dd17807ce5118f8f8a3 100644 --- a/include/gridItem.h +++ b/include/gridItem.h @@ -21,6 +21,7 @@ class Petrack; class Control; +class CoordinateSystemBox; #include "extrCalibration.h" @@ -29,17 +30,18 @@ class Control; class GridItem : public QGraphicsItem { private: - Petrack *mMainWindow; - ExtrCalibration *extCalib; - Control *mControlWidget; - float mouse_x, mouse_y; - int gridTrans_x, gridTrans_y; - int gridDimension; + Petrack *mMainWindow; + ExtrCalibration *mExtCalib; + CoordinateSystemBox *mCoordSys; + Control *mControlWidget; + float mouse_x, mouse_y; + int gridTrans_x, gridTrans_y; + int gridDimension; public: inline void setGridDimension(int gDimension) { this->gridDimension = gDimension; } inline int getGridDimension() const { return this->gridDimension; } - GridItem(QWidget *wParent, QGraphicsItem *parent = nullptr); + GridItem(QWidget *wParent, QGraphicsItem *parent, CoordinateSystemBox *coordSys); QRectF boundingRect() const; void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/include/imageItem.h b/include/imageItem.h index d6e1e3d4c50c5c760e8b050ab52c44449653a800..90efa04a077503397456b15cd5e95844a6364a10 100644 --- a/include/imageItem.h +++ b/include/imageItem.h @@ -19,35 +19,31 @@ #ifndef IMAGEITEM_H #define IMAGEITEM_H -#include <QGraphicsItem> +#include <QGraphicsObject> class Petrack; class Control; -class ImageItem : public QGraphicsItem +class ImageItem : public QGraphicsObject { + Q_OBJECT private: - Petrack *mMainWindow; - Control *mControlWidget; - QImage *mImage; - QGraphicsItem *mCoordItem; + Petrack *mMainWindow; + QImage *mImage; public: - ImageItem(QWidget *wParent, QGraphicsItem *parent = nullptr); + ImageItem(QWidget *wParent, QGraphicsItem *parent); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - void setImage(QImage *img); - void setCoordItem(QGraphicsItem *ci); - double getCmPerPixel(); - QPointF getCmPerPixel(float px, float py, float h = 0.); - double getAngleToGround(float px, float py, float h = 0); - QPointF getPosImage(QPointF pos, float height = 0.); - QPointF getPosReal(QPointF pos, double height = 0.); + void setImage(QImage *img); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + +signals: + void imageChanged(int width, int height, int borderDiff); }; #endif diff --git a/include/multiColorMarkerWidget.h b/include/multiColorMarkerWidget.h index 2ac55326ae83cb04d782268ea15262c9666aeaa3..87a5a92ee36fc5c1c4f8de646cdc7a3c9d21a075 100644 --- a/include/multiColorMarkerWidget.h +++ b/include/multiColorMarkerWidget.h @@ -25,6 +25,7 @@ #include "multiColorMarkerItem.h" #include "petrack.h" #include "ui_multiColorMarker.h" +#include "worldImageCorrespondence.h" #include <QtWidgets> @@ -151,9 +152,10 @@ private slots: { if(mMainWindow->getImageItem() && mMainWindow->getImage() && mMainWindow->getControlWidget()) { - QPointF cmPerPixel1 = mMainWindow->getImageItem()->getCmPerPixel( - 0, 0, mMainWindow->getControlWidget()->getDefaultHeight()); - QPointF cmPerPixel2 = mMainWindow->getImageItem()->getCmPerPixel( + const auto &worldImgCorr = mMainWindow->getWorldImageCorrespondence(); + QPointF cmPerPixel1 = + worldImgCorr.getCmPerPixel(0, 0, mMainWindow->getControlWidget()->getDefaultHeight()); + QPointF cmPerPixel2 = worldImgCorr.getCmPerPixel( mMainWindow->getImage()->width() - 1, mMainWindow->getImage()->height() - 1, mMainWindow->getControlWidget()->getDefaultHeight()); diff --git a/include/petrack.h b/include/petrack.h index c80fcb1fb71e1c5e3e77cccd36fde82fbed49489..d265ac27279e5cbe4736f707322cd5ccab708d4e 100644 --- a/include/petrack.h +++ b/include/petrack.h @@ -36,7 +36,6 @@ #include "borderFilter.h" #include "brightContrastFilter.h" #include "calibFilter.h" -#include "coordItem.h" #include "extrCalibration.h" #include "logwindow.h" #include "manualTrackpointMover.h" @@ -51,6 +50,7 @@ class Animation; class RoiItem; class RecognitionRoiItem; class GridItem; +class WorldImageCorrespondence; #ifdef STEREO_DISABLED enum Camera @@ -75,9 +75,12 @@ class QImage; class QString; class GraphicsView; class QGraphicsScene; +class QXmlStreamWriter; +class QSplitter; class QDoubleSpinBox; class QFrame; +class CoordItem; class ImageItem; class LogoItem; class Control; @@ -249,14 +252,6 @@ public: inline Animation *getAnimation() { return mAnimation; } inline Player *getPlayer() { return mPlayerWidget; } - inline void updateCoord() - { - if(mCoordItem) - { - mCoordItem->updateData(); - } - } - inline QPointF getMousePosOnImage() { return mMousePosOnImage; } inline void setRecognitionChanged(bool b) { mRecognitionChanged = b; } @@ -316,7 +311,8 @@ public: { return &mExtrCalibration; } - inline double getStatusFPS() const + const WorldImageCorrespondence &getWorldImageCorrespondence(); + inline double getStatusFPS() const { return mShowFPS; } @@ -487,8 +483,9 @@ private: SwapFilter mSwapFilter; BackgroundFilter mBackgroundFilter; - AutoCalib mAutoCalib; - ExtrCalibration mExtrCalibration; + AutoCalib mAutoCalib; + ExtrCalibration mExtrCalibration; + const WorldImageCorrespondence *mWorldImageCorrespondence; bool mRecognitionChanged; bool mTrackChanged; diff --git a/include/recognition.h b/include/recognition.h index 5db5625779d316b8f08ad5c8f12a90ace814a8b7..323b225a03039659bff6ad0459819ef612292f9b 100644 --- a/include/recognition.h +++ b/include/recognition.h @@ -33,6 +33,7 @@ class Control; class ImageItem; class CodeMarkerItem; struct IntrinsicCameraParams; +class WorldImageCorrespondence; namespace reco { @@ -263,11 +264,11 @@ namespace detail bool ignoreWithoutMarker = true; ///< should markers without dot be ignored? bool autoCorrect = false; ///< should perspective correction be performed bool autoCorrectOnlyExport = - false; ///< should perspective correction only be performed when exporting trajectories - ImageItem *imageItem = nullptr; ///< used for getAngleToGround and such - QColor midHue; ///< middle hue of the color map - double dotSize = 5; ///< size of the black dot - Control *controlWidget = nullptr; ///< pointer to Control used for autoCorrect + false; ///< should perspective correction only be performed when exporting trajectories + const WorldImageCorrespondence *worldImageCorr = nullptr; ///< used for getAngleToGround and such + QColor midHue; ///< middle hue of the color map + double dotSize = 5; ///< size of the black dot + Control *controlWidget = nullptr; ///< pointer to Control used for autoCorrect }; struct ArucoOptions @@ -283,13 +284,14 @@ namespace detail }; std::vector<ColorBlob> findColorBlob(const ColorBlobDetectionParams &options); - void restrictPositionBlackDot(ColorBlob &blob, ImageItem *imageItem, int bS, cv::Rect &cropRect); - cv::Mat customBgr2Gray(const cv::Mat &subImg, const QColor &midHue); - void refineWithBlackDot( - std::vector<ColorBlob> &blobs, - const cv::Mat &img, - QList<TrackPoint> &crossList, - const BlackDotOptions &options); + void + restrictPositionBlackDot(ColorBlob &blob, const WorldImageCorrespondence *imageItem, int bS, cv::Rect &cropRect); + cv::Mat customBgr2Gray(const cv::Mat &subImg, const QColor &midHue); + void refineWithBlackDot( + std::vector<ColorBlob> &blobs, + const cv::Mat &img, + QList<TrackPoint> &crossList, + const BlackDotOptions &options); void refineWithAruco( std::vector<ColorBlob> &blobs, const cv::Mat &img, diff --git a/include/trackerReal.h b/include/trackerReal.h index db8984528fcce58bcf80edab73f96a11964bf1cc..b6b79b5074b3c0a938942ba0cc9208e207eae10a 100644 --- a/include/trackerReal.h +++ b/include/trackerReal.h @@ -28,6 +28,7 @@ #include <utility> class PersonStorage; +class WorldImageCorrespondence; struct MissingFrame { @@ -180,24 +181,24 @@ public: // mControlWidget->getColorPlot() // petrack...mImageItem int calculate( - Petrack *petrack, - Tracker *tracker, - ImageItem *imageItem, - ColorPlot *colorPlot, - MissingFrames &missing, - int imageBorderSize = 0, - bool missingFramesInserted = true, - bool useTrackpoints = false, - bool alternateHeight = false, - double altitude = 0, - bool useCalibrationCenter = true, - bool exportElimTp = false, - bool exportElimTrj = false, - bool exportSmooth = true, - bool exportViewingDirection = false, - bool exportAngleOfView = false, - bool exportMarkerID = false, - bool exportAutoCorrect = false); + Petrack *petrack, + Tracker *tracker, + const WorldImageCorrespondence *worldImageCorr, + ColorPlot *colorPlot, + MissingFrames &missing, + int imageBorderSize = 0, + bool missingFramesInserted = true, + bool useTrackpoints = false, + bool alternateHeight = false, + double altitude = 0, + bool useCalibrationCenter = true, + bool exportElimTp = false, + bool exportElimTrj = false, + bool exportSmooth = true, + bool exportViewingDirection = false, + bool exportAngleOfView = false, + bool exportMarkerID = false, + bool exportAutoCorrect = false); void calcMinMax(); int largestFirstFrame(); diff --git a/include/vector.h b/include/vector.h index c025bcbdcd933275a14cf49ec8c0df4b4d8c98cf..b6e8092e1f4845459658cdfe08450da82d66b0fc 100644 --- a/include/vector.h +++ b/include/vector.h @@ -47,19 +47,41 @@ public: Vec3F(const cv::Point3f &v); - double x() const; - double y() const; - double z() const; - void setX(double x); - void setY(double y); - void setZ(double z); - void set(double x, double y, double z); + cv::Point3f toCvPoint(); + + double x() const; + double y() const; + double z() const; + void setX(double x); + void setY(double y); + void setZ(double z); + void set(double x, double y, double z); + double &operator[](size_t i) + { + if(i == 0) + { + return mX; + } + else if(i == 1) + { + return mY; + } + else if(i == 2) + { + return mZ; + } + else + { + throw std::runtime_error("Out-of-range index for Vec3F"); + } + } Vec3F &operator=(const Vec3F &v) = default; Vec3F &operator=(Vec3F &&v) = default; Vec3F &operator=(const cv::Point3f &v); + Vec3F operator+(const Vec3F &v) const; Vec3F operator-(const Vec3F &v) const; Vec3F &operator+=(const Vec3F &v); @@ -120,11 +142,26 @@ public: QPointF toQPointF() const; cv::Point2f toPoint2f() const; - double x() const; - double y() const; - void setX(double x); - void setY(double y); - void set(double x, double y); + double x() const; + double y() const; + void setX(double x); + void setY(double y); + void set(double x, double y); + double &operator[](size_t i) + { + if(i == 0) + { + return mX; + } + else if(i == 1) + { + return mY; + } + else + { + throw std::runtime_error("Out-of-range index for Vec2F"); + } + } Vec2F &operator=(const CvPoint *v); diff --git a/include/worldImageCorrespondence.h b/include/worldImageCorrespondence.h new file mode 100644 index 0000000000000000000000000000000000000000..f40625cc477a8cf467d2154345e1618ed14a168c --- /dev/null +++ b/include/worldImageCorrespondence.h @@ -0,0 +1,80 @@ +/* + * PeTrack - Software for tracking pedestrians movement in videos + * Copyright (C) 2023 Forschungszentrum JĂĽlich GmbH, IAS-7 + * + * 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/>. + */ + +#ifndef WORLDIMAGECORRESPONDENCE_H + +#include <QPoint> + +class WorldImageCorrespondence +{ +public: + /** + * @brief Returns the length of a pixel in cm + * + * This method assumes quadratic pixels. This is valid, since we + * did an intrinsic calibration beforehand. Further, it assumes that we + * are working with our "2D calibration". + * + * @return length of pixel in cm + */ + virtual double getCmPerPixel() const = 0; + + /** + * @brief Returns the side length of a pixel in cm + * @param px x-coordinate of the pixel + * @param py y-coordinate of the pixel + * @param h world-coordinate height at which the length of the pixel is probed + * @return lengths of the sides of the pixel + */ + virtual QPointF getCmPerPixel(float px, float py, float h = 0.) const = 0; + + /** + * @brief Returns the angle between the line from camera to point an from camera othogonal to ground + * + * For clarification, see Abb. 3.31 (a) or Abb. 3.75 in Maik's thesis + * + * @param px x-coordinate of probed pixel + * @param py y-coordinate of probed pixel + * @param h world-coordinate height at which the angle is probed + * @return angle between line from cam to point and from cam to ground + */ + virtual double getAngleToGround(float px, float py, float h = 0) const = 0; + + /** + * @brief Calcultaes the position of the point in image/pixel coordinates + * @param pos x and y-coord of position in world coordinates in cm + * @param height z-coord of position in world coordinates in cm + * @return image coordinate in pixels + */ + virtual QPointF getPosImage(QPointF pos, float height = 0.) const = 0; + + /** + * @brief Calculates the position of the image point in world coordinates + * @param pos pixel in image coordinates + * @param height z-coordinate in world coordinate system + * @return point in world coordinate system + */ + virtual QPointF getPosReal(QPointF pos, double height = 0.) const = 0; + + virtual ~WorldImageCorrespondence() = default; +}; + + +#define WORLDIMAGECORRESPONDENCE_H + +#endif // WORLDIMAGECORRESPONDENCE_H diff --git a/src/colorPlot.cpp b/src/colorPlot.cpp index e06b6a4d05e53b56946d38b7dcc8b4bc74774352..2ca96e16d9cdda5c4d712479255956a1705d971d 100644 --- a/src/colorPlot.cpp +++ b/src/colorPlot.cpp @@ -20,6 +20,7 @@ #include "control.h" #include "logger.h" +#include "personStorage.h" #include "tracker.h" #include <QMouseEvent> diff --git a/src/control.cpp b/src/control.cpp index f346430b296478a1e2b7ad6f752669da1d14f61c..f401d47afc240c4c00a2a530dd26a9ce147a69ea 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -20,18 +20,17 @@ #include "IO.h" #include "analysePlot.h" -#include "backgroundItem.h" #include "calibFilter.h" #include "codeMarkerWidget.h" #include "colorMarkerWidget.h" #include "colorPlot.h" #include "colorRangeWidget.h" +#include "coordinateSystemBox.h" #include "extrinsicBox.h" +#include "extrinsicParameters.h" #include "filterBeforeBox.h" -#include "imageItem.h" #include "intrinsicBox.h" #include "logger.h" -#include "moCapItem.h" #include "multiColorMarkerWidget.h" #include "pMessageBox.h" #include "petrack.h" @@ -42,32 +41,50 @@ #include "trackerItem.h" #include "ui_control.h" #include "view.h" +#include "worldImageCorrespondence.h" #include <QDomElement> #include <iomanip> #define DEFAULT_HEIGHT 180.0 Control::Control( - QWidget &parent, - QGraphicsScene &scene, - reco::Recognizer &recognizer, - RoiItem &trackRoiItem, - RoiItem &recoRoiItem, - MissingFrames &missingFrames, - FilterBeforeBox *filterBefore) : - Control(parent, scene, recognizer, trackRoiItem, recoRoiItem, new Ui::Control(), missingFrames, filterBefore) + QWidget &parent, + QGraphicsScene &scene, + reco::Recognizer &recognizer, + RoiItem &trackRoiItem, + RoiItem &recoRoiItem, + MissingFrames &missingFrames, + FilterBeforeBox *filterBefore, + IntrinsicBox *intrinsicBox, + ExtrinsicBox *extrinsicBox, + CoordinateSystemBox *coordSysBox) : + Control( + parent, + scene, + recognizer, + trackRoiItem, + recoRoiItem, + new Ui::Control(), + missingFrames, + filterBefore, + intrinsicBox, + extrinsicBox, + coordSysBox) { } Control::Control( - QWidget &parent, - QGraphicsScene &scene, - reco::Recognizer &recognizer, - RoiItem &trackRoiItem, - RoiItem &recoRoiItem, - Ui::Control *ui, - MissingFrames &missingFrames, - FilterBeforeBox *filterBefore) : + QWidget &parent, + QGraphicsScene &scene, + reco::Recognizer &recognizer, + RoiItem &trackRoiItem, + RoiItem &recoRoiItem, + Ui::Control *ui, + MissingFrames &missingFrames, + FilterBeforeBox *filterBefore, + IntrinsicBox *intrinsicBox, + ExtrinsicBox *extrinsicBox, + CoordinateSystemBox *coordSysBox) : QWidget(&parent), mUi(ui), mFilterBefore(filterBefore) { setAccessibleName("Control"); @@ -94,14 +111,6 @@ Control::Control( QObject::connect( &missingFrames, &MissingFrames::executeChanged, mUi->missingFramesCalculated, &QCheckBox::setChecked); - auto updateImageCallback = [this]() - { - if(!mMainWindow->isLoading()) - { - mMainWindow->updateImage(); - } - }; - // layout reparents widget ui->verticalLayout_13->insertWidget(0, mFilterBefore); mFilterBefore->setObjectName("filterBeforeBox"); @@ -116,32 +125,36 @@ Control::Control( filterSettings.useSwapV = mMainWindow->getSwapFilter()->getSwapVertically().getValue(); mFilterBefore->setFilterSettings(filterSettings); - mIntr = new IntrinsicBox(this, *mMainWindow->getAutoCalib(), *mMainWindow->getCalibFilter(), updateImageCallback); + mIntr = intrinsicBox; mIntr->setObjectName(QString::fromUtf8("intr")); - ui->verticalLayout_13->insertWidget(1, mIntr); - mExtr = new ExtrinsicBox( - this, - *mMainWindow->getExtrCalibration(), - [this]() - { - if(!isLoading()) - { - mMainWindow->updateCoord(); - mScene->update(); - } - }); + mExtr = extrinsicBox; mExtr->setObjectName(QString::fromUtf8("extr")); ui->verticalLayout_13->insertWidget(2, mExtr); + mCoordSys = coordSysBox; + coordSysBox->setObjectName(QString::fromUtf8("coord")); + ui->verticalLayout_13->insertWidget(3, mCoordSys); + // integrate new widgets in tabbing order - ui->calib->setFocusProxy(ui->coordShow); + ui->calib->setFocusProxy(ui->gridShow); QWidget::setTabOrder(mFilterBefore, mIntr); QWidget::setTabOrder(mIntr, mExtr); - QWidget::setTabOrder(mExtr, ui->calib); + QWidget::setTabOrder(mExtr, mCoordSys); + QWidget::setTabOrder(mCoordSys, ui->calib); + connect(mExtr, &ExtrinsicBox::extrinsicChanged, mCoordSys, &CoordinateSystemBox::updateCoordItem); connect(mIntr, &IntrinsicBox::paramsChanged, this, &Control::on_intrinsicParamsChanged); + connect( + mExtr, + &ExtrinsicBox::enabledChanged, + this, + [this](bool enabled) + { + mUi->trackShowGroundPosition->setEnabled(enabled); + mUi->trackShowGroundPath->setEnabled(enabled); + }); setFilterBorderSizeMin(mMainWindow->getBorderFilter()->getBorderSize().getMinimum()); setFilterBorderSizeMax(mMainWindow->getBorderFilter()->getBorderSize().getMaximum()); @@ -666,6 +679,12 @@ int Control::getFilterBgDeleteNumber() const void Control::imageSizeChanged(int width, int height, int borderDiff) { mIntr->imageSizeChanged(width, height, borderDiff); + // trans nicht setzen, da mgl mehrere videos mit gleicher scene und gleichem koord sinnvoll + const Vec2F min(-10 * mMainWindow->getImageBorderSize(), -10 * mMainWindow->getImageBorderSize()); + const Vec2F max( + 10 * (width - mMainWindow->getImageBorderSize()), 10 * (height - mMainWindow->getImageBorderSize())); + setCalibCoord2DTransMinMax(min, max); + mMainWindow->updateSceneRect(); } const ExtrinsicParameters &Control::getExtrinsicParameters() const @@ -673,6 +692,31 @@ const ExtrinsicParameters &Control::getExtrinsicParameters() const return mExtr->getExtrinsicParameters(); } +const WorldImageCorrespondence &Control::getWorldImageCorrespondence() const +{ + return *mCoordSys; +} + +void Control::setCalibCoord2DTransMinMax(Vec2F min, Vec2F max) +{ + mCoordSys->setCoordTrans2DMinMax(min, max); +} + +Vec2F Control::getCalibCoord2DTrans() +{ + return mCoordSys->getCoordTrans2D(); +} + +Vec3F Control::getCalibCoord3DTrans() const +{ + return mCoordSys->getCoordTrans3D(); +} + +SwapAxis Control::getCalibCoord3DSwap() const +{ + return mCoordSys->getSwap3D(); +} + int Control::getCalibGridDimension() { @@ -797,206 +841,18 @@ void Control::setCalibGrid3DResolution(int i) int Control::getCalibCoordDimension() { - return mUi->coordTab->currentIndex(); + return mCoordSys->getCalibCoordDimension(); } -bool Control::getCalibExtrCalibPointsShow() -{ - return mUi->extCalibPointsShow->isChecked(); -} - -bool Control::getCalibExtrVanishPointsShow() -{ - return mUi->extVanishPointsShow->isChecked(); -} bool Control::getCalibCoordShow() { - return mUi->coordShow->isChecked(); -} - -void Control::setCalibCoordShow(bool b) -{ - mUi->coordShow->setChecked(b); -} - -bool Control::getCalibCoordFix() -{ - return mUi->coordFix->isChecked(); -} - -void Control::setCalibCoordFix(bool b) -{ - mUi->coordFix->setChecked(b); -} - -int Control::getCalibCoordRotate() -{ - return mUi->coordRotate->value(); -} - -void Control::setCalibCoordRotate(int i) -{ - mUi->coordRotate->setValue(i); -} - -int Control::getCalibCoordTransX() -{ - return mUi->coordTransX->value(); -} - -void Control::setCalibCoordTransX(int i) -{ - mUi->coordTransX->setValue(i); -} - -int Control::getCalibCoordTransXMax() -{ - return mUi->coordTransX->maximum(); -} - -void Control::setCalibCoordTransXMax(int i) -{ - mUi->coordTransX->setMaximum(i); - mUi->coordTransX_spin->setMaximum(i); -} - -int Control::getCalibCoordTransXMin() -{ - return mUi->coordTransX->minimum(); -} - -void Control::setCalibCoordTransXMin(int i) -{ - mUi->coordTransX->setMinimum(i); - mUi->coordTransX_spin->setMinimum(i); -} - -int Control::getCalibCoordTransY() -{ - return mUi->coordTransY->value(); -} - -void Control::setCalibCoordTransY(int i) -{ - mUi->coordTransY->setValue(i); -} - -int Control::getCalibCoordTransYMax() -{ - return mUi->coordTransY->maximum(); -} - -void Control::setCalibCoordTransYMax(int i) -{ - mUi->coordTransY->setMaximum(i); - mUi->coordTransY_spin->setMaximum(i); -} - -int Control::getCalibCoordTransYMin() -{ - return mUi->coordTransY->minimum(); -} - -void Control::setCalibCoordTransYMin(int i) -{ - mUi->coordTransY->setMinimum(i); - mUi->coordTransY_spin->setMinimum(i); + return mCoordSys->getCalibCoordShow(); } int Control::getCalibCoordScale() { - return mUi->coordScale->value(); -} - -void Control::setCalibCoordScale(int i) -{ - mUi->coordScale->setValue(i); -} - -double Control::getCalibCoordUnit() -{ - return mUi->coordUnit->value(); -} - -void Control::setCalibCoordUnit(double d) -{ - mUi->coordUnit->setValue(d); -} - -bool Control::isCoordUseIntrinsicChecked() const -{ - return mUi->coordUseIntrinsic->isChecked(); -} - -int Control::getCalibCoord3DTransX() -{ - return mUi->coord3DTransX->value(); -} - -void Control::setCalibCoord3DTransX(int i) -{ - mUi->coord3DTransX->setValue(i); -} - -int Control::getCalibCoord3DTransY() -{ - return mUi->coord3DTransY->value(); -} - -void Control::setCalibCoord3DTransY(int i) -{ - mUi->coord3DTransY->setValue(i); -} - -int Control::getCalibCoord3DTransZ() -{ - return mUi->coord3DTransZ->value(); -} - -void Control::setCalibCoord3DTransZ(int i) -{ - mUi->coord3DTransZ->setValue(i); -} - -int Control::getCalibCoord3DAxeLen() -{ - return mUi->coord3DAxeLen->value(); -} - -void Control::setCalibCoord3DAxeLen(int i) -{ - mUi->coord3DAxeLen->setValue(i); -} - -bool Control::getCalibCoord3DSwapX() -{ - return mUi->coord3DSwapX->isChecked(); -} - -void Control::setCalibCoord3DSwapX(bool b) -{ - mUi->coord3DSwapX->setChecked(b); -} - -bool Control::getCalibCoord3DSwapY() -{ - return mUi->coord3DSwapY->isChecked(); -} - -void Control::setCalibCoord3DSwapY(bool b) -{ - mUi->coord3DSwapY->setChecked(b); -} - -bool Control::getCalibCoord3DSwapZ() -{ - return mUi->coord3DSwapZ->isChecked(); -} - -void Control::setCalibCoord3DSwapZ(bool b) -{ - mUi->coord3DSwapZ->setChecked(b); + return mCoordSys->getCoordPose2D().scale; } //-------------------- analysis @@ -1873,31 +1729,14 @@ void Control::on_intrinsicParamsChanged(IntrinsicCameraParams params) if(!mMainWindow->isLoading()) { mMainWindow->updateImage(); - mMainWindow->updateCoord(); + mCoordSys->updateCoordItem(); } - setMeasuredAltitude(); + mCoordSys->setMeasuredAltitude(); } //--------------------------------------- -void Control::on_extCalibPointsShow_stateChanged(int /*arg1*/) -{ - if(!isLoading()) - { - mScene->update(); - } -} - - -void Control::on_extVanishPointsShow_stateChanged(int /*arg1*/) -{ - if(!isLoading()) - { - mScene->update(); - } -} - //--------------------------------------- void Control::on_gridTab_currentChanged(int /*index*/) @@ -1968,165 +1807,7 @@ void Control::on_grid3DResolution_valueChanged(int /*value*/) } //--------------------------------------- -void Control::on_coordTab_currentChanged(int index) -{ - if(index == 1) - { - mExtr->setEnabledExtrParams(false); - mUi->trackShowGroundPosition->setEnabled(false); - mUi->trackShowGroundPath->setEnabled(false); - } - else - { - mExtr->setEnabledExtrParams(true); - mUi->trackShowGroundPosition->setEnabled(true); - mUi->trackShowGroundPath->setEnabled(true); - } - if(!isLoading()) - { - mMainWindow->updateCoord(); - mScene->update(); - } -} - -void Control::on_coordShow_stateChanged(int /*i*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - mScene->update(); - setMeasuredAltitude(); // da measured nicht aktualisiert wird, waehrend scale verschoben und show - // deaktiviert und beim aktivieren sonst ein falscher wert zum angezeigten koord - // waere - } - // mScene->update(); //mScene->sceneRect() // ging auch, aber dann wurde zu oft matrix berechnet etc - // mMainWindow->getImageWidget()->update(); // repaint() zeichnet sofort - schneller aber mgl flicker -} - -void Control::on_coordFix_stateChanged(int /*i*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coordRotate_valueChanged(int /*i*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coordTransX_valueChanged(int /*i*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coordTransY_valueChanged(int /*i*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coordScale_valueChanged(int /*i*/) -{ - mMainWindow->updateCoord(); - setMeasuredAltitude(); - mMainWindow->setHeadSize(); -} - -void Control::on_coordAltitude_valueChanged(double /*d*/) -{ - mMainWindow->setHeadSize(); - mScene->update(); // fuer kreis um kopf, der mgl der realen kopfgroesse angepasst wird -} - -void Control::on_coordUnit_valueChanged(double /*d*/) -{ - setMeasuredAltitude(); - mMainWindow->setHeadSize(); - mScene->update(); // fuer kreis um kopf, der mgl der realen kopfgroesse angepasst wird -} - -void Control::on_coordUseIntrinsic_stateChanged(int /*i*/) -{ - mMainWindow->setStatusPosReal(); -} - -void Control::on_coord3DTransX_valueChanged(int /*value*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coord3DTransY_valueChanged(int /*value*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coord3DTransZ_valueChanged(int /*value*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coord3DAxeLen_valueChanged(int /*value*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coord3DSwapX_stateChanged(int /*arg1*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::on_coord3DSwapY_stateChanged(int /*arg1*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} -void Control::on_coord3DSwapZ_stateChanged(int /*arg1*/) -{ - if(!isLoading()) - { - mMainWindow->updateCoord(); - } -} - -void Control::setMeasuredAltitude() -{ - if(mMainWindow->getImageItem()) - { - auto camMat = mIntr->getIntrinsicCameraParams(); - const auto fx = camMat.getFx(); - const auto fy = camMat.getFy(); - mUi->coordAltitudeMeasured->setText( - QString("(measured: %1)").arg((fx + fy) / 2. * mMainWindow->getImageItem()->getCmPerPixel(), 6, 'f', 1)); - } -} //--------------------------------------- // store data in xml node @@ -2160,7 +1841,6 @@ void Control::setXml(QDomElement &elem) subSubElem = (subElem.ownerDocument()).createElement("EXTRINSIC_PARAMETERS"); mExtr->setXml(subSubElem); - subSubElem.setAttribute("SHOW_CALIB_POINTS", mUi->extCalibPointsShow->isChecked()); QString ef = mMainWindow->getExtrCalibration()->getExtrCalibFile(); if(ef != "") @@ -2169,24 +1849,8 @@ void Control::setXml(QDomElement &elem) } subSubElem.setAttribute("EXTERNAL_CALIB_FILE", ef); - subSubElem.setAttribute("COORD_DIMENSION", mUi->coordTab->currentIndex()); - - subSubElem.setAttribute("SHOW", mUi->coordShow->isChecked()); - subSubElem.setAttribute("FIX", mUi->coordFix->isChecked()); - subSubElem.setAttribute("ROTATE", mUi->coordRotate->value()); - subSubElem.setAttribute("TRANS_X", mUi->coordTransX->value()); - subSubElem.setAttribute("TRANS_Y", mUi->coordTransY->value()); - subSubElem.setAttribute("SCALE", mUi->coordScale->value()); - subSubElem.setAttribute("ALTITUDE", mUi->coordAltitude->value()); - subSubElem.setAttribute("UNIT", mUi->coordUnit->value()); - subSubElem.setAttribute("USE_INTRINSIC_CENTER", mUi->coordUseIntrinsic->isChecked()); - subSubElem.setAttribute("COORD3D_TRANS_X", mUi->coord3DTransX->value()); - subSubElem.setAttribute("COORD3D_TRANS_Y", mUi->coord3DTransY->value()); - subSubElem.setAttribute("COORD3D_TRANS_Z", mUi->coord3DTransZ->value()); - subSubElem.setAttribute("COORD3D_AXIS_LEN", mUi->coord3DAxeLen->value()); - subSubElem.setAttribute("COORD3D_SWAP_X", mUi->coord3DSwapX->isChecked()); - subSubElem.setAttribute("COORD3D_SWAP_Y", mUi->coord3DSwapY->isChecked()); - subSubElem.setAttribute("COORD3D_SWAP_Z", mUi->coord3DSwapZ->isChecked()); + mCoordSys->setXml(subSubElem); + subElem.appendChild(subSubElem); subSubElem = (elem.ownerDocument()).createElement("ALIGNMENT_GRID"); @@ -2488,6 +2152,10 @@ void Control::getXml(const QDomElement &elem) { // intentionally left blank } + else if(mCoordSys->getXml(subSubElem)) + { + // intentionally left blank + } else if(subSubElem.tagName() == "BORDER") { if(subSubElem.hasAttribute("COLOR")) @@ -2517,105 +2185,6 @@ void Control::getXml(const QDomElement &elem) } } } - else if(subSubElem.tagName() == "EXTRINSIC_PARAMETERS") - { - if(subSubElem.hasAttribute("SHOW_CALIB_POINTS")) - { - mUi->extCalibPointsShow->setCheckState( - subSubElem.attribute("SHOW_CALIB_POINTS").toInt() ? Qt::Checked : Qt::Unchecked); - } - - if(subSubElem.hasAttribute("COORD_DIMENSION")) - { - mUi->coordTab->setCurrentIndex(subSubElem.attribute("COORD_DIMENSION").toInt()); - } - else - { - mUi->coordTab->setCurrentIndex(1); // = 2D - mExtr->setEnabledExtrParams(false); - } - - if(subSubElem.hasAttribute("SHOW")) - { - mUi->coordShow->setCheckState( - subSubElem.attribute("SHOW").toInt() ? Qt::Checked : Qt::Unchecked); - } - if(subSubElem.hasAttribute("FIX")) - { - mUi->coordFix->setCheckState(subSubElem.attribute("FIX").toInt() ? Qt::Checked : Qt::Unchecked); - } - if(subSubElem.hasAttribute("ROTATE")) - { - mUi->coordRotate->setValue(subSubElem.attribute("ROTATE").toInt()); - } - if(subSubElem.hasAttribute("TRANS_X")) - { - int trans_x = subSubElem.attribute("TRANS_X").toInt(); - if(trans_x > mUi->coordTransX->maximum()) - { - setCalibCoordTransXMax(trans_x); - } - mUi->coordTransX->setValue(trans_x); - } - if(subSubElem.hasAttribute("TRANS_Y")) - { - int trans_y = subSubElem.attribute("TRANS_Y").toInt(); - if(trans_y > mUi->coord3DTransY->maximum()) - { - setCalibCoordTransYMax(trans_y); - } - mUi->coordTransY->setValue(trans_y); - } - mUi->coordTransY->setValue(subSubElem.attribute("TRANS_Y").toInt()); - if(subSubElem.hasAttribute("SCALE")) - { - mUi->coordScale->setValue(subSubElem.attribute("SCALE").toInt()); - } - if(subSubElem.hasAttribute("ALTITUDE")) - { - mUi->coordAltitude->setValue(subSubElem.attribute("ALTITUDE").toDouble()); - } - if(subSubElem.hasAttribute("UNIT")) - { - mUi->coordUnit->setValue(subSubElem.attribute("UNIT").toDouble()); - } - if(subSubElem.hasAttribute("USE_INTRINSIC_CENTER")) - { - mUi->coordUseIntrinsic->setCheckState( - subSubElem.attribute("USE_INTRINSIC_CENTER").toInt() ? Qt::Checked : Qt::Unchecked); - } - if(subSubElem.hasAttribute("COORD3D_TRANS_X")) - { - mUi->coord3DTransX->setValue(subSubElem.attribute("COORD3D_TRANS_X").toInt()); - } - if(subSubElem.hasAttribute("COORD3D_TRANS_Y")) - { - mUi->coord3DTransY->setValue(subSubElem.attribute("COORD3D_TRANS_Y").toInt()); - } - if(subSubElem.hasAttribute("COORD3D_TRANS_Z")) - { - mUi->coord3DTransZ->setValue(subSubElem.attribute("COORD3D_TRANS_Z").toInt()); - } - if(subSubElem.hasAttribute("COORD3D_AXIS_LEN")) - { - mUi->coord3DAxeLen->setValue(subSubElem.attribute("COORD3D_AXIS_LEN").toInt()); - } - if(subSubElem.hasAttribute("COORD3D_SWAP_X")) - { - mUi->coord3DSwapX->setCheckState( - subSubElem.attribute("COORD3D_SWAP_X").toInt() ? Qt::Checked : Qt::Unchecked); - } - if(subSubElem.hasAttribute("COORD3D_SWAP_Y")) - { - mUi->coord3DSwapY->setCheckState( - subSubElem.attribute("COORD3D_SWAP_Y").toInt() ? Qt::Checked : Qt::Unchecked); - } - if(subSubElem.hasAttribute("COORD3D_SWAP_Z")) - { - mUi->coord3DSwapZ->setCheckState( - subSubElem.attribute("COORD3D_SWAP_Z").toInt() ? Qt::Checked : Qt::Unchecked); - } - } else if(subSubElem.tagName() == "ALIGNMENT_GRID") { if(subSubElem.hasAttribute("GRID_DIMENSION")) @@ -3393,8 +2962,12 @@ void Control::getXml(const QDomElement &elem) SPDLOG_WARN("Unknown CONTROL tag: {}", subSubElem.tagName()); } } + mCoordSys->updateCoordItem(); +} - mMainWindow->updateCoord(); +bool Control::isLoading() const +{ + return mMainWindow->isLoading(); } ColorPlot *Control::getColorPlot() const @@ -3683,7 +3256,7 @@ double Control::getDefaultHeight() const double Control::getCameraAltitude() const { - return mUi->coordAltitude->value(); + return mCoordSys->getCameraAltitude(); } /** diff --git a/src/coordItem.cpp b/src/coordItem.cpp index 0ec31b02d2ee361ae0ebc2f8fd8d2305a1f59e6a..3596eb8aceabf9c16aa5752e1501bc6c1d0d1aea 100644 --- a/src/coordItem.cpp +++ b/src/coordItem.cpp @@ -19,6 +19,7 @@ #include "coordItem.h" #include "control.h" +#include "coordinateSystemBox.h" #include "extrCalibration.h" #include "petrack.h" @@ -28,17 +29,14 @@ // in x und y gleichermassen skaliertes koordinatensystem, // da von einer vorherigen intrinsischen kamerakalibrierung ausgegenagen wird, // so dass pixel quadratisch -CoordItem::CoordItem(QWidget *wParent, QGraphicsItem *parent) : QGraphicsItem(parent) +CoordItem::CoordItem(QWidget *wParent, QGraphicsItem *parent, CoordinateSystemBox *coordSys) : + QGraphicsObject(parent), mCoordSys(coordSys) { mMainWindow = (class Petrack *) wParent; extCalib = mMainWindow->getExtrCalibration(); mControlWidget = mMainWindow->getControlWidget(); - // Set Min and Max - calibPointsMin.x = 50000; - calibPointsMax.x = 0; - calibPointsMin.y = 50000; - calibPointsMax.y = 0; + QObject::connect(coordSys, &CoordinateSystemBox::coordDataChanged, this, &CoordItem::updateData); updateData(); // um zB setFlags(ItemIsMovable) je nach anzeige zu aendern } @@ -53,43 +51,14 @@ CoordItem::CoordItem(QWidget *wParent, QGraphicsItem *parent) : QGraphicsItem(pa */ QRectF CoordItem::boundingRect() const { - // bounding box wird in lokalen koordinaten angegeben!!! (+-10 wegen zahl "1") - if(mControlWidget->getCalibCoordShow()) - { - if(mControlWidget->getCalibCoordDimension() != 0) // 2D view - { - return QRectF(-110., -110., 220., 220.); - } - else // 3D view - { - double min_x = std::min(std::min(x.x, y.x), std::min(z.x, ursprung.x)); - double max_x = std::max(std::max(x.x, y.x), std::max(z.x, ursprung.x)); - - double min_y = std::min(std::min(x.y, y.y), std::min(z.y, ursprung.y)); - double max_y = std::max(std::max(x.y, y.y), std::max(z.y, ursprung.y)); - - if(mControlWidget->getCalibExtrCalibPointsShow()) - { - min_x = std::min(float(min_x), calibPointsMin.x); - max_x = std::max(float(max_x), calibPointsMax.x); - - min_y = std::min(float(min_y), calibPointsMin.y); - max_y = std::max(float(max_y), calibPointsMax.y); - } - return QRectF(min_x - 25, min_y - 25, max_x - min_x + 50, max_y - min_y + 50); - } - } - else - { - return QRectF(0., 0., 0., 0.); - } + return mBoundingRect; } // event, of moving mouse while button is pressed void CoordItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { // if coordinate system position is not fixed - if(!mControlWidget->getCalibCoordFix()) + if(!mCoordSys->getCalibCoordFix()) { setCursor(Qt::ClosedHandCursor); @@ -97,19 +66,18 @@ void CoordItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) event->lastScenePos(); // screenPos()-buttonDownScreenPos(Qt::RightButton) also interesting if(event->buttons() == Qt::RightButton) // event->button() doesnt work { - mControlWidget->setCalibCoordRotate( - mControlWidget->getCalibCoordRotate() - - (int) (3. * (diff.x() + diff.y()))); // 10* nicht noetig, da eh nur relativ + auto pose2D = mCoordSys->getCoordPose2D(); + pose2D.angle -= (int) (3. * (diff.x() + diff.y())); + mCoordSys->setCoordPose2D(pose2D); } else if(event->buttons() == Qt::LeftButton) { - if(mControlWidget->getCalibCoordDimension() == 0) // 3D + if(mCoordSys->getCalibCoordDimension() == 0) // 3D { - cv::Point3f p_cur = extCalib->get3DPoint( - cv::Point2f(event->scenePos().x(), event->scenePos().y()), mControlWidget->getCalibCoord3DTransZ()); - cv::Point3f p_last = extCalib->get3DPoint( - cv::Point2f(mouse_x /*event->lastScenePos().x()*/, mouse_y /*event->lastScenePos().y()*/), - mControlWidget->getCalibCoord3DTransZ()); + auto trans = mCoordSys->getCoordTrans3D(); + cv::Point3f p_cur = + extCalib->get3DPoint(cv::Point2f(event->scenePos().x(), event->scenePos().y()), trans.z()); + cv::Point3f p_last = extCalib->get3DPoint(cv::Point2f(mouse_x, mouse_y), trans.z()); // ToDo: // Problem: Die Mouse Bewegungen, die erfasst werden sind zu gering, sodass viele Werte als 0 gewertet // werden und nicht als Bewegung bercksichtigt werden, obwohl man die Maus bewegt. D.h. die Maus bewegt @@ -117,28 +85,32 @@ void CoordItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) // und das Kooridnatensystem bewegt sich nicht. Effekt wird noch verstrkt, da das stndig passiert // Besonders schnelle Mausbewegungen lindern den Effekt - mControlWidget->setCalibCoord3DTransX( - coordTrans_x - (mControlWidget->getCalibCoord3DSwapX() ? -1 : 1) * round(p_last.x - p_cur.x)); - mControlWidget->setCalibCoord3DTransY( - coordTrans_y - (mControlWidget->getCalibCoord3DSwapY() ? -1 : 1) * round(p_last.y - p_cur.y)); + auto swap = mCoordSys->getSwap3D(); + trans[0] = coordTrans_x - (swap.x ? -1 : 1) * round(p_last.x - p_cur.x); + trans[1] = coordTrans_y - (swap.y ? -1 : 1) * round(p_last.y - p_cur.y); + mCoordSys->setCoordTrans3D(trans); } else { - mControlWidget->setCalibCoordTransX(mControlWidget->getCalibCoordTransX() + (int) (10. * diff.x())); - mControlWidget->setCalibCoordTransY(mControlWidget->getCalibCoordTransY() + (int) (10. * diff.y())); + auto pose = mCoordSys->getCoordPose2D(); + pose.position[0] += 10. * diff.x(); + pose.position[1] += 10. * diff.y(); + mCoordSys->setCoordPose2D(pose); } } else if(event->buttons() == Qt::MiddleButton) { - if(mControlWidget->getCalibCoordDimension() == 0) + if(mCoordSys->getCalibCoordDimension() == 0) { - mControlWidget->setCalibCoord3DAxeLen( - mControlWidget->getCalibCoord3DAxeLen() + (int) (10. * (diff.x() - diff.y()))); + int axeLen = mCoordSys->getCoord3DAxeLen(); + axeLen += (int) (10. * (diff.x() - diff.y())); + mCoordSys->setCoord3DAxeLen(axeLen); } else { - mControlWidget->setCalibCoordScale( - mControlWidget->getCalibCoordScale() + (int) (10. * (diff.x() - diff.y()))); + auto pose2D = mCoordSys->getCoordPose2D(); + pose2D.scale += (int) (10. * (diff.x() - diff.y())); + mCoordSys->setCoordPose2D(pose2D); } } } @@ -150,15 +122,16 @@ void CoordItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void CoordItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if(!mControlWidget->getCalibCoordFix()) + if(!mCoordSys->getCalibCoordFix()) { if(event->button() == Qt::LeftButton) { mouse_x = event->scenePos().x(); mouse_y = event->scenePos().y(); - coordTrans_x = mControlWidget->getCalibCoord3DTransX(); - coordTrans_y = mControlWidget->getCalibCoord3DTransY(); + auto trans = mCoordSys->getCoordTrans3D(); + coordTrans_x = trans.x(); + coordTrans_y = trans.y(); } } else @@ -169,7 +142,8 @@ void CoordItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void CoordItem::updateData() { - if(!mControlWidget->getCalibCoordFix()) + auto state = mCoordSys->getCoordItemState(); + if(state.isMovable) { setFlag( ItemIsMovable); // noetig, damit mouseEvent leftmousebutton weitergegeben wird, aber drag mach ich selber @@ -181,84 +155,14 @@ void CoordItem::updateData() false); // noetig, damit mouseEvent leftmousebutton weitergegeben wird, aber drag mach ich selber } - if(mControlWidget->getCalibCoordDimension() == 1) // 2D - { - double sc = mControlWidget->getCalibCoordScale() / 10.; - double tX = mControlWidget->getCalibCoordTransX() / 10.; - double tY = mControlWidget->getCalibCoordTransY() / 10.; - double ro = mControlWidget->getCalibCoordRotate() / 10.; - - // aktualisierung der transformationsmatrix - QTransform matrix; - // matrix wird nur bei aenderungen neu bestimmt - matrix.translate(tX, tY); - matrix.rotate(ro); - matrix.scale(sc / 100., sc / 100.); - // matrix.shear(tX,tY); - setTransform(matrix); - } - else // 3D - { - //////////////////////////////////////// - // 3D World-Coordinate-System // - //////////////////////////////////////// - if(mMainWindow->getImage()) - { - // Reset Matrix - No Matrix Transformations for 3D Coordsystem - // aktualisierung der transformationsmatrix - QTransform matrix; - // matrix wird nur bei aenderungen neu bestimmt - matrix.translate(0, 0); - matrix.rotate(0); - matrix.scale(1, 1); - setTransform(matrix); - - const double axeLen = mControlWidget->getCalibCoord3DAxeLen(); - const int bS = mMainWindow->getImageBorderSize(); - - // Coordinate-system origin at (tX,tY,tZ) - if(extCalib->isSetExtrCalib()) - { - ursprung = extCalib->getImagePoint(cv::Point3f(0, 0, 0)); + setTransform(state.matrix); + x3D = state.x3D; + y3D = state.y3D; + z3D = state.z3D; - x3D = cv::Point3f(axeLen, 0, 0); - y3D = cv::Point3f(0, axeLen, 0); - z3D = cv::Point3f(0, 0, axeLen); + prepareGeometryChange(); + mBoundingRect = state.boundingRect; - // Tests if the origin-point of the coordinate-system is outside the image - if(extCalib->isOutsideImage(ursprung)) - { - return; - } - x3D.x++; - y3D.y++; - z3D.z++; - - // Kuerzt die Koordinaten-Achsen, falls sie aus dem angezeigten Bild raus laufen wuerden - do - { - x3D.x--; - x = extCalib->getImagePoint(x3D); - // tests if the coord system axis are inside the view or outside, if outside short them till they - // are inside the image - } while(x.x < -bS || x.x > mMainWindow->getImage()->width() - bS || x.y < -bS || - x.y > mMainWindow->getImage()->height() - bS); - do - { - y3D.y--; - y = extCalib->getImagePoint(y3D); - } while(y.x < -bS || y.x > mMainWindow->getImage()->width() - bS || y.y < -bS || - y.y > mMainWindow->getImage()->height() - bS); - do - { - z3D.z--; - z = extCalib->getImagePoint(z3D); - } while(z.x < -bS || z.x > mMainWindow->getImage()->width() - bS || z.y < -bS || - z.y > mMainWindow->getImage()->height() - bS); - } - } - prepareGeometryChange(); - } if(!mMainWindow->isLoading()) { mMainWindow->updateImage(); @@ -270,14 +174,13 @@ void CoordItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*opti //////////////////////////////// // Drawing Calibration Points // //////////////////////////////// - if(mControlWidget->getCalibExtrCalibPointsShow() && mControlWidget->getCalibCoordDimension() == 0) + if(mCoordSys->getCalibExtrCalibPointsShow() && mCoordSys->getCalibCoordDimension() == 0) { if(extCalib->isSetExtrCalib()) { QFont font; font.setBold(mControlWidget->isTrackNumberBoldChecked()); font.setPixelSize(mControlWidget->getTrackNumberSize()); - painter->setFont(font); for(size_t i = 0; i < extCalib->get2DList().size(); i++) @@ -293,14 +196,14 @@ void CoordItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*opti painter->setBrush(Qt::blue); // Projected 3D-Points - cv::Point3f p3d = extCalib->get3DList().at(i); - p3d.x -= mControlWidget->getCalibCoord3DTransX(); - p3d.y -= mControlWidget->getCalibCoord3DTransY(); - p3d.z -= mControlWidget->getCalibCoord3DTransZ(); + cv::Point3f p3d = extCalib->get3DList().at(i); + auto trans = mCoordSys->getCoordTrans3D(); + p3d -= trans.toCvPoint(); - p3d.x *= (mControlWidget->getCalibCoord3DSwapX() ? -1 : 1); - p3d.y *= (mControlWidget->getCalibCoord3DSwapY() ? -1 : 1); - p3d.z *= (mControlWidget->getCalibCoord3DSwapZ() ? -1 : 1); + auto swap = mCoordSys->getSwap3D(); + p3d.x *= (swap.x ? -1 : 1); + p3d.y *= (swap.y ? -1 : 1); + p3d.z *= (swap.z ? -1 : 1); cv::Point2f p3 = extCalib->getImagePoint(p3d); @@ -313,22 +216,17 @@ void CoordItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*opti painter->setPen(Qt::black); painter->setBrush(Qt::black); painter->drawText(QPointF(p2.x + 10, p2.y + font.pixelSize()), QObject::tr("%1").arg((i + 1))); - - calibPointsMin.x = std::min({calibPointsMin.x, p2.x, p3.x}); - calibPointsMin.y = std::min({calibPointsMin.y, p2.y, p3.y}); - calibPointsMax.x = std::max({calibPointsMax.x, p2.x, p3.x}); - calibPointsMax.y = std::max({calibPointsMax.y, p2.y, p3.y}); } } } - if(mControlWidget->getCalibCoordShow()) + if(mCoordSys->getCalibCoordShow()) { // general configuration painter->setPen(Qt::blue); painter->setBrush(QBrush(Qt::blue, Qt::SolidPattern)); - if(mControlWidget->getCalibCoordDimension() == 1) // 2D + if(mCoordSys->getCalibCoordDimension() == 1) // 2D { ////////////////////////// // 2D Coordinate-System // @@ -365,7 +263,7 @@ void CoordItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*opti } else { - double axeLen = mControlWidget->getCalibCoord3DAxeLen(); + double axeLen = mCoordSys->getCoord3DAxeLen(); qreal coordLineWidth = 2.0; diff --git a/src/coordinateSystemBox.cpp b/src/coordinateSystemBox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6985311669898da34c3eaf293352f9ead112db91 --- /dev/null +++ b/src/coordinateSystemBox.cpp @@ -0,0 +1,794 @@ +/* + * PeTrack - Software for tracking pedestrians movement in videos + * Copyright (C) 2023 Forschungszentrum JĂĽlich GmbH, IAS-7 + * + * 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 "coordinateSystemBox.h" + +#include "coordItem.h" +#include "extrCalibration.h" +#include "extrinsicBox.h" +#include "imageItem.h" +#include "intrinsicBox.h" +#include "ui_coordinateSystemBox.h" + +#include <opencv2/core/base.hpp> + +CoordinateSystemBox::CoordinateSystemBox( + QWidget *parent, + std::function<void()> updateStatusPos, + std::function<void()> updateHeadSize, + std::function<int()> getBorderSizeCallback, + const IntrinsicBox &intrinsicBox, + ExtrinsicBox &extrinsicBox, + const ImageItem &imageItem, + const ExtrCalibration &extrCalib) : + CoordinateSystemBox( + parent, + new Ui::CoordinateSystemBox, + updateStatusPos, + updateHeadSize, + getBorderSizeCallback, + intrinsicBox, + extrinsicBox, + imageItem, + extrCalib) +{ +} + +CoordinateSystemBox::CoordinateSystemBox( + QWidget *parent, + Ui::CoordinateSystemBox *ui, + std::function<void()> updateStatusPos, + std::function<void()> updateHeadSize, + std::function<int()> getBorderSizeCallback, + const IntrinsicBox &intrinsicBox, + ExtrinsicBox &extrinsicBox, + const ImageItem &imageItem, + const ExtrCalibration &extrCalib) : + QGroupBox(parent), + mUi(ui), + mUpdateStatusPos(std::move(updateStatusPos)), + mUpdateHeadSize(std::move(updateHeadSize)), + mGetBorderSize(getBorderSizeCallback), + mIntr(intrinsicBox), + mExtrBox(extrinsicBox), + mImageItem(imageItem), + mExtrCalib(extrCalib) +{ + mUi->setupUi(this); + setFocusProxy(mUi->coordShow); + + mPose3D.swap.x = mUi->coord3DSwapX->isChecked(); + mPose3D.swap.y = mUi->coord3DSwapY->isChecked(); + mPose3D.swap.z = mUi->coord3DSwapZ->isChecked(); + + mPose3D.position[0] = mUi->coord3DTransX->value(); + mPose3D.position[1] = mUi->coord3DTransY->value(); + mPose3D.position[2] = mUi->coord3DTransZ->value(); + + mPose2D.angle = mUi->coordRotate->value(); + mPose2D.scale = mUi->coordScale->value(); + mPose2D.unit = mUi->coordUnit->value(); + mPose2D.position[0] = mUi->coordTransX->value(); + mPose2D.position[1] = mUi->coordTransY->value(); +} + +CoordinateSystemBox::~CoordinateSystemBox() +{ + delete mUi; +} + +void CoordinateSystemBox::setCoordTrans2DMinMax(const Vec2F &min, const Vec2F &max) +{ + mUi->coordTransX->setMinimum(static_cast<int>(min.x())); + mUi->coordTransX_spin->setMinimum(static_cast<int>(min.x())); + mUi->coordTransY->setMinimum(static_cast<int>(min.y())); + mUi->coordTransY_spin->setMinimum(static_cast<int>(min.y())); + + mUi->coordTransX->setMaximum(static_cast<int>(max.x())); + mUi->coordTransX_spin->setMaximum(static_cast<int>(max.x())); + mUi->coordTransY->setMaximum(static_cast<int>(max.y())); + mUi->coordTransY_spin->setMaximum(static_cast<int>(max.y())); +} + +std::pair<Vec2F, Vec2F> CoordinateSystemBox::getCoordTrans2DMinMax() const +{ + Vec2F min(mUi->coordTransX->minimum(), mUi->coordTransY->minimum()); + Vec2F max(mUi->coordTransX->maximum(), mUi->coordTransY->maximum()); + return {min, max}; +} + +void CoordinateSystemBox::setCoordPose2D(const CoordPose2D &pose) +{ + mUi->coordTransX->setValue(pose.position.x()); + mUi->coordTransY->setValue(pose.position.y()); + mUi->coordScale->setValue(pose.scale); + mUi->coordUnit->setValue(pose.unit); + mUi->coordRotate->setValue(pose.angle); +} + +double CoordinateSystemBox::getCameraAltitude() const +{ + return mUi->coordAltitude->value(); +} + +void CoordinateSystemBox::setCoordTrans2D(Vec2F trans) +{ + mUi->coordTransX->setValue(trans.x()); + mUi->coordTransY->setValue(trans.y()); +} + +bool CoordinateSystemBox::isCoordUseIntrinsicChecked() const +{ + return mUi->coordUseIntrinsic->isChecked(); +} + +void CoordinateSystemBox::setCoordTrans3D(Vec3F trans) +{ + mUi->coord3DTransX->setValue(trans.x()); + mUi->coord3DTransY->setValue(trans.y()); + mUi->coord3DTransZ->setValue(trans.z()); +} + +int CoordinateSystemBox::getCoord3DAxeLen() const +{ + return mUi->coord3DAxeLen->value(); +} + +void CoordinateSystemBox::setCoord3DAxeLen(int newLength) +{ + mUi->coord3DAxeLen->setValue(newLength); +} + +int CoordinateSystemBox::getCalibCoordDimension() const +{ + return mUi->coordTab->currentIndex(); +} + +bool CoordinateSystemBox::getCalibExtrCalibPointsShow() const +{ + return mUi->extCalibPointsShow->isChecked(); +} + +bool CoordinateSystemBox::getCalibExtrVanishPointsShow() const +{ + return mUi->extVanishPointsShow->isChecked(); +} + +bool CoordinateSystemBox::getCalibCoordShow() const +{ + return mUi->coordShow->isChecked(); +} + +bool CoordinateSystemBox::getCalibCoordFix() const +{ + return mUi->coordFix->isChecked(); +} + +int CoordinateSystemBox::getCalibCoordRotate() const +{ + return mUi->coordRotate->value(); +} + +void CoordinateSystemBox::setCalibCoordRotate(int newVal) +{ + mUi->coordRotate->setValue(newVal); +} + +// in x und y richtung identisch, da vorher intrinsische kamerakalibrierung geschehen ist +double CoordinateSystemBox::getCmPerPixel() const +{ + // das sollte nur einmal berechne werden, wenn einfliessende daten sich aendern + auto boderTransform = QTransform::fromTranslate(-mGetBorderSize(), -mGetBorderSize()); + auto imgToWorld = boderTransform * mCoordTransform.inverted(); + QPointF p1 = imgToWorld * QPointF(0, 0); + QPointF p2 = imgToWorld * QPointF(1, 0); + const auto coordUnit = mUi->coordUnit->value(); + return coordUnit * sqrt(pow(p1.x() - p2.x(), 2) + pow(p1.y() - p2.y(), 2)) / 100.; + // durch 100., da coordsys so gezeichnet, dass 1 bei 100 liegt +} + +// Liefert zum Pixelpunkt (px,py) die Anzahl der Zentimeter in x- und y-Richtung +QPointF CoordinateSystemBox::getCmPerPixel(float px, float py, float h) const +{ + // ToDo: + // 3D Punkte an (px-0.5, py) und (px+0.5, py) berechnen und Auswirkung in x-Richtung + // und (px, py-0.5) und (px, py+0.5) berechnen und Auswirkung in y-Richtung untersuchen + // + // Unterscheiden nach x- und y-Richtung? + // Wie fliesst die Hoehe mit ein? + + cv::Point3f p3x1 = mExtrCalib.get3DPoint(cv::Point2f(px - 0.5, py), h); + cv::Point3f p3x2 = mExtrCalib.get3DPoint(cv::Point2f(px + 0.5, py), h); + + cv::Point3f p3y1 = mExtrCalib.get3DPoint(cv::Point2f(px, py - 0.5), h); + cv::Point3f p3y2 = mExtrCalib.get3DPoint(cv::Point2f(px, py + 0.5), h); + + double x_dir = norm(p3x1 - p3x2); + double y_dir = norm(p3y1 - p3y2); + + QPointF res(x_dir, y_dir); + + return res; +} + +///* +/// Liefert den Winkel zwischen der Geraden von der Kamera +/// zum uebergebenen Punkt mit der Hoehe height +/// zur Grundflaeche [0-90] 90 => senkrecht unter der Kamera +/// Punktkoordinaten beinhalten die Border +///* +double CoordinateSystemBox::getAngleToGround(float px, float py, float height) const +{ + const auto &extrParams = mExtrBox.getExtrinsicParameters(); + cv::Point3f cam( + -mUi->coord3DTransX->value() - extrParams.trans1, + -mUi->coord3DTransY->value() - extrParams.trans2, + -mUi->coord3DTransZ->value() - extrParams.trans3); + + cv::Point3f posInImage = mExtrCalib.get3DPoint(cv::Point2f(px - mGetBorderSize(), py - mGetBorderSize()), height); + + cv::Point3f a(cam.x - posInImage.x, cam.y - posInImage.y, cam.z - posInImage.z), b(0, 0, 1); + + return asin( + (a.x * b.x + a.y * b.y + a.z * b.z) / (abs(sqrt(pow(a.x, 2) + pow(a.y, 2) + pow(a.z, 2))) * + abs(sqrt(pow(b.x, 2) + pow(b.y, 2) + pow(b.z, 2))))) * + 180 / PI; +} + +QPointF CoordinateSystemBox::getPosImage(QPointF pos, float height) const +{ + auto imageSize = mImageItem.boundingRect(); + cv::Point2f p2d; + if(imageSize != QRectF{0, 0, 0, 0}) + { + if(getCalibCoordDimension() == 0) // Tab coordinate system is on 3D + { + p2d = mExtrCalib.getImagePoint(cv::Point3f(pos.x(), pos.y(), height)); + pos.setX(p2d.x); + pos.setY(p2d.y); + } + else + { + ////////////// + + // Fehlerhaft funktioniert nicht wie gewollt + + ////////////// + // Old 2D mapping of Pixelpoints to RealPositions + pos.setY(-pos.y()); + pos /= mUi->coordUnit->value() / 100.; // durch 100., da coordsys so gezeichnet, dass 1 bei 100 liegt + + auto borderTransforms = QTransform::fromTranslate(-mGetBorderSize(), -mGetBorderSize()); + auto imgToWorld = borderTransforms * mCoordTransform.inverted(); + pos = imgToWorld.inverted() * pos; + // mImageItem.mapFromItem(&mCoordItem, pos); // Einheit anpassen... + if(isCoordUseIntrinsicChecked()) + { + const auto camMat = mIntr.getIntrinsicCameraParams(); + pos.rx() -= camMat.getCx(); + pos.ry() -= camMat.getCy(); + } + else + { + pos.rx() -= imageSize.width() / 2. - .5; // Bildmitte + pos.ry() -= imageSize.height() / 2. - .5; // Bildmitte + } + const auto altitude = mUi->coordAltitude->value(); + pos = (altitude / (altitude - height)) * pos; + + + if(isCoordUseIntrinsicChecked()) + { + const auto camMat = mIntr.getIntrinsicCameraParams(); + pos.rx() += camMat.getCx(); + pos.ry() += camMat.getCy(); + } + else + { + pos.rx() += imageSize.width() / 2. - .5; // Bildmitte + pos.ry() += imageSize.height() / 2. - .5; // Bildmitte + } + } + } + return pos; +} + +// eingabe pos als pixelkoordinate des bildes +// result in cm (mit y-Achse nach oben gerichtet) +// default height = 0. in Headerdatei (in cm) +// wenn kein Bild vorliegt, wird eingabeposition durchgereicht - kommt nicht vor, da kein mouseevent +QPointF CoordinateSystemBox::getPosReal(QPointF pos, double height) const +{ + auto imageSize = mImageItem.boundingRect(); + + if(imageSize != QRectF{0, 0, 0, 0}) + { + int bS = mGetBorderSize(); + + // Switch between 2D and 3D CameraCalibration/Position calculation + if(getCalibCoordDimension() == 0) + { + // New 3D mapping of Pixelpoints to RealPositions + cv::Point3f p3d = mExtrCalib.get3DPoint(cv::Point2f(pos.x() - bS, pos.y() - bS), height); + + // ToDo: Getting the floor point of the Person! (Only the x/y-coordinates?) + pos = QPointF(p3d.x, p3d.y); + } + else + { + // statt mControlWidget->getCalibFx() muesste spaeter wert stehen, der im verzerrten Bild fX=fY angibt + // a = mControlWidget->getCalibFx()*getMeterPerPixel(); + // a = mControlWidget->getCameraAltitude(); + // -.5 da pixel von 0..1023 (in skala bis 1024 anfaengt) laufen + if(isCoordUseIntrinsicChecked()) + { + const auto camMat = mIntr.getIntrinsicCameraParams(); + pos.rx() -= camMat.getCx(); + pos.ry() -= camMat.getCy(); + } + else + { + pos.rx() -= imageSize.width() / 2. - .5; // Bildmitte + pos.ry() -= imageSize.height() / 2. - .5; // Bildmitte + } + + const auto altitude = mUi->coordAltitude->value(); + pos = ((altitude - height) / altitude) * pos; //((a-height)/a)*pos; + + if(isCoordUseIntrinsicChecked()) + { + const auto camMat = mIntr.getIntrinsicCameraParams(); + pos.rx() += camMat.getCx(); + pos.ry() += camMat.getCy(); + } + else + { + pos.rx() += imageSize.width() / 2. - .5; // Bildmitte + pos.ry() += imageSize.height() / 2. - .5; // Bildmitte + } + + // Old 2D mapping of Pixelpoints to RealPositions + auto borderTransform = QTransform::fromTranslate(-mGetBorderSize(), -mGetBorderSize()); + auto imgToWorld = borderTransform * mCoordTransform.inverted(); + pos = imgToWorld * pos; + pos *= mUi->coordUnit->value() / 100.; // durch 100., da coordsys so gezeichnet, dass 1 bei 100 liegt + pos.setY(-pos.y()); + } + } + return pos; +} + +bool CoordinateSystemBox::getXml(const QDomElement &subSubElem) +{ + if(subSubElem.tagName() == "EXTRINSIC_PARAMETERS") + { + if(subSubElem.hasAttribute("SHOW_CALIB_POINTS")) + { + mUi->extCalibPointsShow->setCheckState( + subSubElem.attribute("SHOW_CALIB_POINTS").toInt() ? Qt::Checked : Qt::Unchecked); + } + + if(subSubElem.hasAttribute("COORD_DIMENSION")) + { + mUi->coordTab->setCurrentIndex(subSubElem.attribute("COORD_DIMENSION").toInt()); + } + else + { + mUi->coordTab->setCurrentIndex(1); // = 2D + mExtrBox.setEnabledExtrParams(false); + } + + if(subSubElem.hasAttribute("SHOW")) + { + mUi->coordShow->setCheckState(subSubElem.attribute("SHOW").toInt() ? Qt::Checked : Qt::Unchecked); + } + if(subSubElem.hasAttribute("FIX")) + { + mUi->coordFix->setCheckState(subSubElem.attribute("FIX").toInt() ? Qt::Checked : Qt::Unchecked); + } + if(subSubElem.hasAttribute("ROTATE")) + { + mUi->coordRotate->setValue(subSubElem.attribute("ROTATE").toInt()); + } + if(subSubElem.hasAttribute("TRANS_X")) + { + int trans_x = subSubElem.attribute("TRANS_X").toInt(); + if(trans_x > mUi->coordTransX->maximum()) + { + setCalibCoordTransXMax(trans_x); + } + mUi->coordTransX->setValue(trans_x); + } + if(subSubElem.hasAttribute("TRANS_Y")) + { + int trans_y = subSubElem.attribute("TRANS_Y").toInt(); + if(trans_y > mUi->coord3DTransY->maximum()) + { + setCalibCoordTransYMax(trans_y); + } + mUi->coordTransY->setValue(trans_y); + } + mUi->coordTransY->setValue(subSubElem.attribute("TRANS_Y").toInt()); + if(subSubElem.hasAttribute("SCALE")) + { + mUi->coordScale->setValue(subSubElem.attribute("SCALE").toInt()); + } + if(subSubElem.hasAttribute("ALTITUDE")) + { + mUi->coordAltitude->setValue(subSubElem.attribute("ALTITUDE").toDouble()); + } + if(subSubElem.hasAttribute("UNIT")) + { + mUi->coordUnit->setValue(subSubElem.attribute("UNIT").toDouble()); + } + if(subSubElem.hasAttribute("USE_INTRINSIC_CENTER")) + { + mUi->coordUseIntrinsic->setCheckState( + subSubElem.attribute("USE_INTRINSIC_CENTER").toInt() ? Qt::Checked : Qt::Unchecked); + } + if(subSubElem.hasAttribute("COORD3D_TRANS_X")) + { + mUi->coord3DTransX->setValue(subSubElem.attribute("COORD3D_TRANS_X").toInt()); + } + if(subSubElem.hasAttribute("COORD3D_TRANS_Y")) + { + mUi->coord3DTransY->setValue(subSubElem.attribute("COORD3D_TRANS_Y").toInt()); + } + if(subSubElem.hasAttribute("COORD3D_TRANS_Z")) + { + mUi->coord3DTransZ->setValue(subSubElem.attribute("COORD3D_TRANS_Z").toInt()); + } + if(subSubElem.hasAttribute("COORD3D_AXIS_LEN")) + { + mUi->coord3DAxeLen->setValue(subSubElem.attribute("COORD3D_AXIS_LEN").toInt()); + } + if(subSubElem.hasAttribute("COORD3D_SWAP_X")) + { + mUi->coord3DSwapX->setCheckState( + subSubElem.attribute("COORD3D_SWAP_X").toInt() ? Qt::Checked : Qt::Unchecked); + } + if(subSubElem.hasAttribute("COORD3D_SWAP_Y")) + { + mUi->coord3DSwapY->setCheckState( + subSubElem.attribute("COORD3D_SWAP_Y").toInt() ? Qt::Checked : Qt::Unchecked); + } + if(subSubElem.hasAttribute("COORD3D_SWAP_Z")) + { + mUi->coord3DSwapZ->setCheckState( + subSubElem.attribute("COORD3D_SWAP_Z").toInt() ? Qt::Checked : Qt::Unchecked); + } + + return true; + } + return false; +} + +void CoordinateSystemBox::setXml(QDomElement &subSubElem) const +{ + subSubElem.setAttribute("SHOW_CALIB_POINTS", mUi->extCalibPointsShow->isChecked()); + + subSubElem.setAttribute("COORD_DIMENSION", mUi->coordTab->currentIndex()); + + subSubElem.setAttribute("SHOW", mUi->coordShow->isChecked()); + subSubElem.setAttribute("FIX", mUi->coordFix->isChecked()); + subSubElem.setAttribute("ROTATE", mUi->coordRotate->value()); + subSubElem.setAttribute("TRANS_X", mUi->coordTransX->value()); + subSubElem.setAttribute("TRANS_Y", mUi->coordTransY->value()); + subSubElem.setAttribute("SCALE", mUi->coordScale->value()); + subSubElem.setAttribute("ALTITUDE", mUi->coordAltitude->value()); + subSubElem.setAttribute("UNIT", mUi->coordUnit->value()); + subSubElem.setAttribute("USE_INTRINSIC_CENTER", mUi->coordUseIntrinsic->isChecked()); + subSubElem.setAttribute("COORD3D_TRANS_X", mUi->coord3DTransX->value()); + subSubElem.setAttribute("COORD3D_TRANS_Y", mUi->coord3DTransY->value()); + subSubElem.setAttribute("COORD3D_TRANS_Z", mUi->coord3DTransZ->value()); + subSubElem.setAttribute("COORD3D_AXIS_LEN", mUi->coord3DAxeLen->value()); + subSubElem.setAttribute("COORD3D_SWAP_X", mUi->coord3DSwapX->isChecked()); + subSubElem.setAttribute("COORD3D_SWAP_Y", mUi->coord3DSwapY->isChecked()); + subSubElem.setAttribute("COORD3D_SWAP_Z", mUi->coord3DSwapZ->isChecked()); +} + +void CoordinateSystemBox::setCalibCoordTransXMax(int max) +{ + mUi->coordTransX->setMaximum(max); + mUi->coordTransX_spin->setMaximum(max); +} + +void CoordinateSystemBox::setCalibCoordTransYMax(int max) +{ + mUi->coordTransY->setMaximum(max); + mUi->coordTransY_spin->setMaximum(max); +} + +// may be called from other classes if sth. changed such that ExtrCalib has different results +void CoordinateSystemBox::updateCoordItem() +{ + emit coordDataChanged(); +} + + +CoordItemState CoordinateSystemBox::getCoordItemState() +{ + CoordItemState state; + state.isMovable = !mUi->coordFix->isChecked(); + + + state.coordDimension = getCalibCoordDimension(); + if(getCalibCoordDimension() == 1) // 2D + { + double sc = mPose2D.scale / 10.; + double tX = mPose2D.position.x() / 10.; + double tY = mPose2D.position.y() / 10.; + double ro = mPose2D.angle / 10.; + + // aktualisierung der transformationsmatrix + QTransform matrix; + // matrix wird nur bei aenderungen neu bestimmt + matrix.translate(tX, tY); + matrix.rotate(ro); + matrix.scale(sc / 100., sc / 100.); + state.matrix = matrix; + state.boundingRect = QRectF(-110., -110., 220., 220.); + } + else // 3D + { + //////////////////////////////////////// + // 3D World-Coordinate-System // + //////////////////////////////////////// + + auto imageSize = mImageItem.boundingRect(); + if(imageSize != QRectF{0, 0, 0, 0}) + { + // Reset Matrix - No Matrix Transformations for 3D Coordsystem + // aktualisierung der transformationsmatrix + QTransform matrix; + // matrix wird nur bei aenderungen neu bestimmt + matrix.translate(0, 0); + matrix.rotate(0); + matrix.scale(1, 1); + state.matrix = matrix; + + const double axeLen = mUi->coord3DAxeLen->value(); + const int bS = mGetBorderSize(); + + // Coordinate-system origin at (tX,tY,tZ) + if(mExtrCalib.isSetExtrCalib()) + { + auto ursprung = mExtrCalib.getImagePoint(cv::Point3f(0, 0, 0)); + + auto x3D = cv::Point3f(axeLen, 0, 0); + auto y3D = cv::Point3f(0, axeLen, 0); + auto z3D = cv::Point3f(0, 0, axeLen); + + // Tests if the origin-point of the coordinate-system is outside the image + if(mExtrCalib.isOutsideImage(ursprung)) + { + mCoordTransform = state.matrix; + return state; + } + x3D.x++; + y3D.y++; + z3D.z++; + + cv::Point2f x; + cv::Point2f y; + cv::Point2f z; + auto imgSize = mImageItem.boundingRect(); + // Kuerzt die Koordinaten-Achsen, falls sie aus dem angezeigten Bild raus laufen wuerden + do + { + x3D.x--; + x = mExtrCalib.getImagePoint(x3D); + // tests if the coord system axis are inside the view or outside, if outside short them till they + // are inside the image + } while(x.x < -bS || x.x > imgSize.width() - bS || x.y < -bS || x.y > imgSize.height() - bS); + state.x3D = x3D; + do + { + y3D.y--; + y = mExtrCalib.getImagePoint(y3D); + } while(y.x < -bS || y.x > imgSize.width() - bS || y.y < -bS || y.y > imgSize.height() - bS); + state.y3D = y3D; + do + { + z3D.z--; + z = mExtrCalib.getImagePoint(z3D); + } while(z.x < -bS || z.x > imgSize.width() - bS || z.y < -bS || z.y > imgSize.height() - bS); + state.z3D = z3D; + + // bounding box wird in lokalen koordinaten angegeben!!! (+-10 wegen zahl "1") + if(mUi->coordShow->isChecked()) + { + double min_x = std::min(std::min(x.x, y.x), std::min(z.x, ursprung.x)); + double max_x = std::max(std::max(x.x, y.x), std::max(z.x, ursprung.x)); + + double min_y = std::min(std::min(x.y, y.y), std::min(z.y, ursprung.y)); + double max_y = std::max(std::max(x.y, y.y), std::max(z.y, ursprung.y)); + + if(mUi->extCalibPointsShow->isChecked()) + { + cv::Point2f calibPointsMin{50'000, 50'000}; + cv::Point2f calibPointsMax{0, 0}; + for(const auto &p : mExtrCalib.get2DList()) + { + if(p.x > calibPointsMax.x) + { + calibPointsMax.x = p.x; + } + if(p.y > calibPointsMax.y) + { + calibPointsMax.y = p.y; + } + if(p.x < calibPointsMin.x) + { + calibPointsMin.x = p.x; + } + if(p.y < calibPointsMin.y) + { + calibPointsMin.y = p.y; + } + } + min_x = std::min(float(min_x), calibPointsMin.x); + max_x = std::max(float(max_x), calibPointsMax.x); + + min_y = std::min(float(min_y), calibPointsMin.y); + max_y = std::max(float(max_y), calibPointsMax.y); + } + state.boundingRect = QRectF(min_x - 25, min_y - 25, max_x - min_x + 50, max_y - min_y + 50); + } + else + { + state.boundingRect = QRectF(0., 0., 0., 0.); + } + } + } + } + + mCoordTransform = state.matrix; + return state; +} + +void CoordinateSystemBox::on_coordTab_currentChanged(int index) +{ + if(index == 1) + { + mExtrBox.setEnabledExtrParams(false); + } + else + { + mExtrBox.setEnabledExtrParams(true); + } + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordShow_stateChanged(int /*i*/) +{ + updateCoordItem(); + setMeasuredAltitude(); // da measured nicht aktualisiert wird, waehrend scale verschoben und show + // deaktiviert und beim aktivieren sonst ein falscher wert zum angezeigten koord + // waere +} + +void CoordinateSystemBox::on_coordFix_stateChanged(int /*i*/) +{ + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordRotate_valueChanged(int newAngle) +{ + mPose2D.angle = newAngle; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordTransX_valueChanged(int newX) +{ + mPose2D.position[0] = newX; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordTransY_valueChanged(int newY) +{ + mPose2D.position[1] = newY; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordScale_valueChanged(int newScale) +{ + mPose2D.scale = newScale; + setMeasuredAltitude(); + mUpdateHeadSize(); + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordAltitude_valueChanged(double /*d*/) +{ + mUpdateHeadSize(); + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordUnit_valueChanged(double newUnit) +{ + mPose2D.unit = newUnit; + setMeasuredAltitude(); + mUpdateHeadSize(); + updateCoordItem(); +} + +void CoordinateSystemBox::on_coordUseIntrinsic_stateChanged(int /*i*/) +{ + mUpdateStatusPos(); +} + +void CoordinateSystemBox::on_coord3DTransX_valueChanged(int newX) +{ + mPose3D.position[0] = newX; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coord3DTransY_valueChanged(int newY) +{ + mPose3D.position[1] = newY; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coord3DTransZ_valueChanged(int newZ) +{ + mPose3D.position[2] = newZ; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coord3DAxeLen_valueChanged(int /*value*/) +{ + updateCoordItem(); +} + +void CoordinateSystemBox::on_coord3DSwapX_stateChanged(int newSwap) +{ + mPose3D.swap.x = newSwap == Qt::Checked; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coord3DSwapY_stateChanged(int newSwap) +{ + mPose3D.swap.y = newSwap == Qt::Checked; + updateCoordItem(); +} + +void CoordinateSystemBox::on_coord3DSwapZ_stateChanged(int newSwap) +{ + mPose3D.swap.z = newSwap == Qt::Checked; + updateCoordItem(); +} + +void CoordinateSystemBox::setMeasuredAltitude() +{ + auto camMat = mIntr.getIntrinsicCameraParams(); + const auto fx = camMat.getFx(); + const auto fy = camMat.getFy(); + mUi->coordAltitudeMeasured->setText(QString("(measured: %1)").arg((fx + fy) / 2. * getCmPerPixel(), 6, 'f', 1)); +} + +void CoordinateSystemBox::on_extCalibPointsShow_stateChanged(int /*arg1*/) +{ + updateCoordItem(); +} + + +void CoordinateSystemBox::on_extVanishPointsShow_stateChanged(int /*arg1*/) +{ + updateCoordItem(); +} diff --git a/src/extrCalibration.cpp b/src/extrCalibration.cpp index a66488ab38e9e7f6d25503d19a9a380f6c28d444..752933162a56a838bda79f0ee86d8091f2305b7b 100644 --- a/src/extrCalibration.cpp +++ b/src/extrCalibration.cpp @@ -447,10 +447,6 @@ bool ExtrCalibration::saveExtrCalibPoints() return all_okay; } -bool ExtrCalibration::isSetExtrCalib() -{ - return true; -} /** * @brief Extrinsic calibration with help of cv::solvePnP @@ -585,11 +581,10 @@ bool ExtrCalibration::calcReprojectionError() for(size_t i = 0; i < num_points; i++) { - cv::Point2f p2d = get2DList().at(i); - cv::Point3f p3d = get3DList().at(i); - p3d.x -= mControlWidget->getCalibCoord3DTransX(); - p3d.y -= mControlWidget->getCalibCoord3DTransY(); - p3d.z -= mControlWidget->getCalibCoord3DTransZ(); + cv::Point2f p2d = get2DList().at(i); + cv::Point3f p3d = get3DList().at(i); + auto trans = mControlWidget->getCalibCoord3DTrans(); + p3d -= trans.toCvPoint(); cv::Point2f p3dTo2d = getImagePoint(p3d); // Error measurements metric (cm) @@ -626,11 +621,10 @@ bool ExtrCalibration::calcReprojectionError() } for(size_t i = 0; i < num_points; i++) { - cv::Point2f p2d = get2DList().at(i); - cv::Point3f p3d = get3DList().at(i); - p3d.x -= mControlWidget->getCalibCoord3DTransX(); - p3d.y -= mControlWidget->getCalibCoord3DTransY(); - p3d.z -= mControlWidget->getCalibCoord3DTransZ(); + cv::Point2f p2d = get2DList().at(i); + cv::Point3f p3d = get3DList().at(i); + auto trans = mControlWidget->getCalibCoord3DTrans(); + p3d -= trans.toCvPoint(); cv::Point2f p3d_to_2d = getImagePoint(p3d); // Error measurements metric (cm) @@ -720,16 +714,16 @@ bool ExtrCalibration::calcReprojectionError() * @param p3d 3D point to transform in cm * @return calculated 2D projection of p3d */ -cv::Point2f ExtrCalibration::getImagePoint(cv::Point3f p3d) +cv::Point2f ExtrCalibration::getImagePoint(cv::Point3f p3d) const { - p3d.x *= mControlWidget->getCalibCoord3DSwapX() ? -1 : 1; - p3d.y *= mControlWidget->getCalibCoord3DSwapY() ? -1 : 1; - p3d.z *= mControlWidget->getCalibCoord3DSwapZ() ? -1 : 1; + auto swap = mControlWidget->getCalibCoord3DSwap(); + p3d.x *= swap.x ? -1 : 1; + p3d.y *= swap.y ? -1 : 1; + p3d.z *= swap.z ? -1 : 1; // Adding the coordsystem translation from petrack window - p3d.x += mControlWidget->getCalibCoord3DTransX(); - p3d.y += mControlWidget->getCalibCoord3DTransY(); - p3d.z += mControlWidget->getCalibCoord3DTransZ(); + auto trans = mControlWidget->getCalibCoord3DTrans(); + p3d += trans.toCvPoint(); // ToDo: use projectPoints(); int bS = mMainWindow->getImage() ? mMainWindow->getImageBorderSize() : 0; @@ -901,18 +895,18 @@ cv::Point3f ExtrCalibration::get3DPoint(const cv::Point2f &p2d, double h) const // Coordinate Transformations - resultPoint.x -= mControlWidget->getCalibCoord3DTransX(); - resultPoint.y -= mControlWidget->getCalibCoord3DTransY(); - resultPoint.z -= mControlWidget->getCalibCoord3DTransZ(); + auto trans = mControlWidget->getCalibCoord3DTrans(); + resultPoint -= trans.toCvPoint(); - resultPoint.x *= mControlWidget->getCalibCoord3DSwapX() ? -1 : 1; - resultPoint.y *= mControlWidget->getCalibCoord3DSwapY() ? -1 : 1; - resultPoint.z *= mControlWidget->getCalibCoord3DSwapZ() ? -1 : 1; + auto swap = mControlWidget->getCalibCoord3DSwap(); + resultPoint.x *= swap.x ? -1 : 1; + resultPoint.y *= swap.y ? -1 : 1; + resultPoint.z *= swap.z ? -1 : 1; return resultPoint; } -bool ExtrCalibration::isOutsideImage(cv::Point2f p2d) +bool ExtrCalibration::isOutsideImage(cv::Point2f p2d) const { int bS = mMainWindow->getImage() ? mMainWindow->getImageBorderSize() : 0; if(mMainWindow->getImage()) diff --git a/src/extrinsicBox.cpp b/src/extrinsicBox.cpp index 7d78de8b3fa424cf69032776a2c3f5d9dbde5b4d..008351e5f9bd4676dccef55b0bc4d8afd5a0f25b 100644 --- a/src/extrinsicBox.cpp +++ b/src/extrinsicBox.cpp @@ -28,12 +28,8 @@ #include <QStyle> #include <utility> -ExtrinsicBox::ExtrinsicBox( - QWidget *parent, - Ui::extr *ui, - ExtrCalibration &extrCalib, - std::function<void()> updateCoordCallback) : - QGroupBox(parent), mUi(ui), mExtrCalibration(extrCalib), mUpdateCoordCallback(std::move(updateCoordCallback)) +ExtrinsicBox::ExtrinsicBox(QWidget *parent, Ui::extr *ui, ExtrCalibration &extrCalib) : + QGroupBox(parent), mUi(ui), mExtrCalibration(extrCalib) { mUi->setupUi(this); setFocusProxy(mUi->rot1); @@ -41,8 +37,7 @@ ExtrinsicBox::ExtrinsicBox( setExtrinsicParameters(mParams); } -ExtrinsicBox::ExtrinsicBox(QWidget *parent, ExtrCalibration &extrCalib, std::function<void()> updateCoordCallback) : - ExtrinsicBox(parent, new Ui::extr, extrCalib, std::move(updateCoordCallback)) +ExtrinsicBox::ExtrinsicBox(QWidget *parent, ExtrCalibration &extrCalib) : ExtrinsicBox(parent, new Ui::extr, extrCalib) { } @@ -54,6 +49,7 @@ void ExtrinsicBox::setEnabledExtrParams(bool enable) mUi->trans1->setEnabled(enable); mUi->trans2->setEnabled(enable); mUi->trans3->setEnabled(enable); + emit enabledChanged(enable); } const ExtrinsicParameters &ExtrinsicBox::getExtrinsicParameters() const @@ -87,43 +83,43 @@ void ExtrinsicBox::on_coordLoad3DCalibPoints_clicked() { setExtrinsicParameters(*newCalib); } - mUpdateCoordCallback(); + emit extrinsicChanged(); } void ExtrinsicBox::on_rot1_valueChanged(double newVal) { mParams.rot1 = newVal; - mUpdateCoordCallback(); + emit extrinsicChanged(); } void ExtrinsicBox::on_rot2_valueChanged(double newVal) { mParams.rot2 = newVal; - mUpdateCoordCallback(); + emit extrinsicChanged(); } void ExtrinsicBox::on_rot3_valueChanged(double newVal) { mParams.rot3 = newVal; - mUpdateCoordCallback(); + emit extrinsicChanged(); } void ExtrinsicBox::on_trans1_valueChanged(double newVal) { mParams.trans1 = newVal; - mUpdateCoordCallback(); + emit extrinsicChanged(); } void ExtrinsicBox::on_trans2_valueChanged(double newVal) { mParams.trans2 = newVal; - mUpdateCoordCallback(); + emit extrinsicChanged(); } void ExtrinsicBox::on_trans3_valueChanged(double newVal) { mParams.trans3 = newVal; - mUpdateCoordCallback(); + emit extrinsicChanged(); } void ExtrinsicBox::on_extrCalibSave_clicked() diff --git a/src/gridItem.cpp b/src/gridItem.cpp index 4bc2d7b87f6944ce7e858a516e428dc0276c90b4..bd2bcfc307023ffefa0bc796fd5a63b731a4af04 100644 --- a/src/gridItem.cpp +++ b/src/gridItem.cpp @@ -19,6 +19,7 @@ #include "gridItem.h" #include "control.h" +#include "coordinateSystemBox.h" #include "logger.h" #include "petrack.h" #include "view.h" @@ -26,10 +27,11 @@ #include <QtWidgets> #include <cmath> -GridItem::GridItem(QWidget *wParent, QGraphicsItem *parent) : QGraphicsItem(parent) +GridItem::GridItem(QWidget *wParent, QGraphicsItem *parent, CoordinateSystemBox *coordSys) : + QGraphicsItem(parent), mCoordSys(coordSys) { mMainWindow = (class Petrack *) wParent; - extCalib = mMainWindow->getExtrCalibration(); + mExtCalib = mMainWindow->getExtrCalibration(); mControlWidget = mMainWindow->getControlWidget(); } @@ -78,15 +80,15 @@ void GridItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if(mControlWidget->getCalibGridDimension() == 0) { - cv::Point3f p3d = extCalib->get3DPoint( + const auto &swap = mCoordSys->getSwap3D(); + + cv::Point3f p3d = mExtCalib->get3DPoint( cv::Point2f(event->scenePos().x(), event->scenePos().y()), mControlWidget->getCalibGrid3DTransZ()); - cv::Point3f p3d_last = extCalib->get3DPoint( + cv::Point3f p3d_last = mExtCalib->get3DPoint( cv::Point2f(mouse_x /*event->lastScenePos().x()*/, mouse_y /*event->lastScenePos().y()*/), mControlWidget->getCalibGrid3DTransZ()); - mControlWidget->setCalibGrid3DTransX( - gridTrans_x + (mControlWidget->getCalibCoord3DSwapX() ? -1 : 1) * round(p3d.x - p3d_last.x)); - mControlWidget->setCalibGrid3DTransY( - gridTrans_y + (mControlWidget->getCalibCoord3DSwapY() ? -1 : 1) * round(p3d.y - p3d_last.y)); + mControlWidget->setCalibGrid3DTransX(gridTrans_x + (swap.x ? -1 : 1) * round(p3d.x - p3d_last.x)); + mControlWidget->setCalibGrid3DTransY(gridTrans_y + (swap.y ? -1 : 1) * round(p3d.y - p3d_last.y)); } else { @@ -263,13 +265,13 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio bool vanishPointXIsInsideImage = false; cv::Point2f vanishPointY, vanishPointX; double x, y; - if(mMainWindow->getImage() && extCalib->isSetExtrCalib()) + if(mMainWindow->getImage() && mExtCalib->isSetExtrCalib()) { // create 2 parallel lines in x-direction cv::Point3f a3d = cv::Point3f(-500, -500, 0), b3d = cv::Point3f(500, -500, 0), c3d = cv::Point3f(-500, 500, 0), d3d = cv::Point3f(500, 500, 0); - cv::Point2f a2d = extCalib->getImagePoint(a3d), b2d = extCalib->getImagePoint(b3d), - c2d = extCalib->getImagePoint(c3d), d2d = extCalib->getImagePoint(d3d); + cv::Point2f a2d = mExtCalib->getImagePoint(a3d), b2d = mExtCalib->getImagePoint(b3d), + c2d = mExtCalib->getImagePoint(c3d), d2d = mExtCalib->getImagePoint(d3d); // y = m*x+n float m1 = (b2d.y - a2d.y) / (b2d.x - a2d.x), m2 = (d2d.y - c2d.y) / (d2d.x - c2d.x), n1 = a2d.y - m1 * a2d.x, @@ -283,8 +285,8 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio // create 2 parallel lines in y-direction a3d = cv::Point3f(-500, -500, 0), b3d = cv::Point3f(-500, 500, 0), c3d = cv::Point3f(500, -500, 0), d3d = cv::Point3f(500, 500, 0); - a2d = extCalib->getImagePoint(a3d), b2d = extCalib->getImagePoint(b3d), c2d = extCalib->getImagePoint(c3d), - d2d = extCalib->getImagePoint(d3d); + a2d = mExtCalib->getImagePoint(a3d), b2d = mExtCalib->getImagePoint(b3d), c2d = mExtCalib->getImagePoint(c3d), + d2d = mExtCalib->getImagePoint(d3d); // y = m*x+n m1 = (b2d.y - a2d.y) / (b2d.x - a2d.x), m2 = (d2d.y - c2d.y) / (d2d.x - c2d.x), n1 = a2d.y - m1 * a2d.x, @@ -295,13 +297,13 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio y = ((m1 * x + n1) + (m2 * x + n2)) / 2.0; vanishPointX = cv::Point2f(x, y); - vanishPointYIsInsideImage = !extCalib->isOutsideImage(vanishPointY); - vanishPointXIsInsideImage = !extCalib->isOutsideImage(vanishPointX); + vanishPointYIsInsideImage = !mExtCalib->isOutsideImage(vanishPointY); + vanishPointXIsInsideImage = !mExtCalib->isOutsideImage(vanishPointX); //////////////////////////////// // Drawing Vanish Points // //////////////////////////////// - if(mControlWidget->getCalibExtrVanishPointsShow()) + if(mCoordSys->getCalibExtrVanishPointsShow()) { painter->setPen(Qt::yellow); painter->drawLine( @@ -402,7 +404,7 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio } else { - if(extCalib->isSetExtrCalib()) + if(mExtCalib->isSetExtrCalib()) { double min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN; int y_offset = -bS; @@ -418,13 +420,13 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio cv::Point3f points[4]; // top left corner - points[0] = extCalib->get3DPoint(cv::Point2f(0 - bS, y_offset), tZ3D); + points[0] = mExtCalib->get3DPoint(cv::Point2f(0 - bS, y_offset), tZ3D); // top right corner - points[1] = extCalib->get3DPoint(cv::Point2f(iW, y_offset), tZ3D); + points[1] = mExtCalib->get3DPoint(cv::Point2f(iW, y_offset), tZ3D); // bottom left corner - points[2] = extCalib->get3DPoint(cv::Point2f(0 - bS, iH), tZ3D); + points[2] = mExtCalib->get3DPoint(cv::Point2f(0 - bS, iH), tZ3D); // bottom right corner - points[3] = extCalib->get3DPoint(cv::Point2f(iW, iH), tZ3D); + points[3] = mExtCalib->get3DPoint(cv::Point2f(iW, iH), tZ3D); painter->setPen(Qt::green); @@ -456,11 +458,11 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio // Draw simple Grid around origin point for(int i = 0; i <= 2500; i += resolution) { - p[0] = extCalib->getImagePoint(cv::Point3f(tX3D + 2500, tY3D + i, tZ3D)); - p[1] = extCalib->getImagePoint(cv::Point3f(tX3D, tY3D + i, tZ3D)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(tX3D + 2500, tY3D + i, tZ3D)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(tX3D, tY3D + i, tZ3D)); painter->drawLine(QPointF(p[0].x, p[0].y), QPointF(p[1].x, p[1].y)); - p[0] = extCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + 2500, tZ3D)); - p[1] = extCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D, tZ3D)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + 2500, tZ3D)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D, tZ3D)); painter->drawLine(QPointF(p[0].x, p[0].y), QPointF(p[1].x, p[1].y)); } } @@ -471,14 +473,14 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio { for(int j = min_x * 5; j < max_x * 5; j += resolution) { - p[0] = extCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + j, tZ3D)); - p[1] = extCalib->getImagePoint(cv::Point3f(tX3D + i + resolution, tY3D + j, tZ3D)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + j, tZ3D)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(tX3D + i + resolution, tY3D + j, tZ3D)); point[0] = QPointF(p[0].x, p[0].y); point[1] = QPointF(p[1].x, p[1].y); - p[0] = extCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + j, tZ3D)); - p[1] = extCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + j + resolution, tZ3D)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + j, tZ3D)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(tX3D + i, tY3D + j + resolution, tZ3D)); point[2] = QPointF(p[0].x, p[0].y); point[3] = QPointF(p[1].x, p[1].y); @@ -515,57 +517,50 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio } else { - int swapX = mControlWidget->getCalibCoord3DSwapX() ? -1 : 1; - int swapY = mControlWidget->getCalibCoord3DSwapY() ? -1 : 1; - int grid_height = - tZ3D - - mControlWidget - ->getCalibCoord3DTransZ(); // Da extCalibration immer vom Koordinatensystemursprung ausgeht - // (Das Grid soll aber unabhngig davon gezeichnet werden) + const auto &swap = mCoordSys->getSwap3D(); + const auto trans = mCoordSys->getCoordTrans3D(); + int swapX = swap.x ? -1 : 1; + int swapY = swap.y ? -1 : 1; + int grid_height = tZ3D - trans.z(); // Da extCalibration immer vom Koordinatensystemursprung ausgeht + // (Das Grid soll aber unabhngig davon gezeichnet werden) // horizontal lines from the left to the right on height tZ3D the lines start from origin point // (tY3D) until max_y or if tY3D < min_y it starts with min_y because otherwise it is outside the // image - for(int i = -mControlWidget->getCalibCoord3DTransY() + tY3D; i < (swapY > 0 ? max_y : -min_y); - i += resolution) + for(int i = -trans.y() + tY3D; i < (swapY > 0 ? max_y : -min_y); i += resolution) { // Bildpunkte zu den Endpunkten der Linie holen - p[0] = extCalib->getImagePoint(cv::Point3f(min_x, swapY * i, grid_height)); - p[1] = extCalib->getImagePoint(cv::Point3f(max_x, swapY * i, grid_height)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(min_x, swapY * i, grid_height)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(max_x, swapY * i, grid_height)); drawLine(painter, p, y_offset); } // see above but now the lines start from origin point (tY3D) until min_y // y- - for(int i = -mControlWidget->getCalibCoord3DTransY() + tY3D - resolution; - i > (swapY > 0 ? min_y : -max_y); - i -= resolution) + for(int i = -trans.y() + tY3D - resolution; i > (swapY > 0 ? min_y : -max_y); i -= resolution) { // Bildpunkte zu den Endpunkten der Linie holen - p[0] = extCalib->getImagePoint(cv::Point3f(min_x, swapY * i, grid_height)); - p[1] = extCalib->getImagePoint(cv::Point3f(max_x, swapY * i, grid_height)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(min_x, swapY * i, grid_height)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(max_x, swapY * i, grid_height)); drawLine(painter, p, y_offset); } // vertical lines from the top to the bottom on height tZ3D the lines start from origin point(tX3D) // until max_x of if tX3D < minx it starts with min_x because otherwise the lines are outside the // image x+ - for(int i = -mControlWidget->getCalibCoord3DTransX() + tX3D; i < (swapX > 0 ? max_x : -min_x); - i += resolution) + for(int i = -trans.x() + tX3D; i < (swapX > 0 ? max_x : -min_x); i += resolution) { // Bildpunkte zu den Endpunkten der Linie holen - p[0] = extCalib->getImagePoint(cv::Point3f(swapX * i, min_y, grid_height)); - p[1] = extCalib->getImagePoint(cv::Point3f(swapX * i, max_y, grid_height)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(swapX * i, min_y, grid_height)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(swapX * i, max_y, grid_height)); drawLine(painter, p, y_offset); } // see above but now the lines start from origin point until min_x // x- - for(int i = -mControlWidget->getCalibCoord3DTransX() + tX3D - resolution; - i > (swapX > 0 ? min_x : -max_x); - i -= resolution) + for(int i = -trans.x() + tX3D - resolution; i > (swapX > 0 ? min_x : -max_x); i -= resolution) { // Bildpunkte zu den Endpunkten der Linie holen - p[0] = extCalib->getImagePoint(cv::Point3f(swapX * i, min_y, grid_height)); - p[1] = extCalib->getImagePoint(cv::Point3f(swapX * i, max_y, grid_height)); + p[0] = mExtCalib->getImagePoint(cv::Point3f(swapX * i, min_y, grid_height)); + p[1] = mExtCalib->getImagePoint(cv::Point3f(swapX * i, max_y, grid_height)); drawLine(painter, p, y_offset); } } diff --git a/src/imageItem.cpp b/src/imageItem.cpp index 83fe5748109d3b6b3e04e7d5cf6b541ee47487e4..e0b7ea04c828c14afe3a11aee6698f7f30a9e59c 100644 --- a/src/imageItem.cpp +++ b/src/imageItem.cpp @@ -18,7 +18,6 @@ #include "imageItem.h" -#include "control.h" #include "petrack.h" #include <QGraphicsScene> @@ -26,12 +25,10 @@ #include <QPainter> #include <cmath> -ImageItem::ImageItem(QWidget *wParent, QGraphicsItem *parent) : QGraphicsItem(parent) +ImageItem::ImageItem(QWidget *wParent, QGraphicsItem *parent) : QGraphicsObject(parent) { - mMainWindow = (class Petrack *) wParent; - mControlWidget = mMainWindow->getControlWidget(); - mImage = nullptr; - mCoordItem = nullptr; + mMainWindow = (class Petrack *) wParent; + mImage = nullptr; setCursor(Qt::CrossCursor); setAcceptHoverEvents(true); } @@ -83,198 +80,7 @@ void ImageItem::setImage(QImage *img) setTransform(matrix); matrix.translate(-mMainWindow->getImageBorderSize() - 1, -mMainWindow->getImageBorderSize() - 1); setTransform(matrix); - - mControlWidget->imageSizeChanged(mImage->width(), mImage->height(), 0); - - // trans nicht setzen, da mgl mehrere videos mit gleicher scene und gleichem koord sinnvoll - mControlWidget->setCalibCoordTransXMin(-10 * mMainWindow->getImageBorderSize()); - mControlWidget->setCalibCoordTransYMin(-10 * mMainWindow->getImageBorderSize()); - mControlWidget->setCalibCoordTransXMax(10 * (mImage->width() - mMainWindow->getImageBorderSize())); - mControlWidget->setCalibCoordTransYMax(10 * (mImage->height() - mMainWindow->getImageBorderSize())); - - mMainWindow->updateSceneRect(); -} - -void ImageItem::setCoordItem(QGraphicsItem *ci) -{ - mCoordItem = ci; -} -// in x und y richtung identisch, da vorher intrinsische kamerakalibrierung geschehen ist -double ImageItem::getCmPerPixel() -{ - if(mCoordItem) - { - // das sollte nur einmal berechne werden, wenn einfliessende daten sich aendern - QPointF p1 = mapToItem(mCoordItem, QPointF(0., 0.)); - QPointF p2 = mapToItem(mCoordItem, QPointF(1., 0.)); - return mControlWidget->getCalibCoordUnit() * sqrt(pow(p1.x() - p2.x(), 2) + pow(p1.y() - p2.y(), 2)) / 100.; - // durch 100., da coordsys so gezeichnet, dass 1 bei 100 liegt - } - else - { - return 0.; - } -} -// Liefert zum Pixelpunkt (px,py) die Anzahl der Zentimeter in x- und y-Richtung -QPointF ImageItem::getCmPerPixel(float px, float py, float h) -{ - // ToDo: - // 3D Punkte an (px-0.5, py) und (px+0.5, py) berechnen und Auswirkung in x-Richtung - // und (px, py-0.5) und (px, py+0.5) berechnen und Auswirkung in y-Richtung untersuchen - // - // Unterscheiden nach x- und y-Richtung? - // Wie fliesst die Hoehe mit ein? - - cv::Point3f p3x1 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(px - 0.5, py), h); - cv::Point3f p3x2 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(px + 0.5, py), h); - - cv::Point3f p3y1 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(px, py - 0.5), h); - cv::Point3f p3y2 = mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(px, py + 0.5), h); - - double x_dir = norm(p3x1 - p3x2); - double y_dir = norm(p3y1 - p3y2); - - QPointF res(x_dir, y_dir); - - return res; -} -///* -/// Liefert den Winkel zwischen der Geraden von der Kamera -/// zum uebergebenen Punkt mit der Hoehe height -/// zur Grundflaeche [0-90] 90 => senkrecht unter der Kamera -/// Punktkoordinaten beinhalten die Border -///* -double ImageItem::getAngleToGround(float px, float py, float height) -{ - const auto &extrParams = mControlWidget->getExtrinsicParameters(); - cv::Point3f cam( - -mControlWidget->getCalibCoord3DTransX() - extrParams.trans1, - -mControlWidget->getCalibCoord3DTransY() - extrParams.trans2, - -mControlWidget->getCalibCoord3DTransZ() - extrParams.trans3); - - cv::Point3f posInImage = mMainWindow->getExtrCalibration()->get3DPoint( - cv::Point2f(px - mMainWindow->getImageBorderSize(), py - mMainWindow->getImageBorderSize()), height); - - cv::Point3f a(cam.x - posInImage.x, cam.y - posInImage.y, cam.z - posInImage.z), b(0, 0, 1); - - return asin( - (a.x * b.x + a.y * b.y + a.z * b.z) / (abs(sqrt(pow(a.x, 2) + pow(a.y, 2) + pow(a.z, 2))) * - abs(sqrt(pow(b.x, 2) + pow(b.y, 2) + pow(b.z, 2))))) * - 180 / PI; -} - -QPointF ImageItem::getPosImage(QPointF pos, float height) -{ - cv::Point2f p2d; - if(mImage) - { - if(mControlWidget->getCalibCoordDimension() == 0) // Tab coordinate system is on 3D - { - p2d = mMainWindow->getExtrCalibration()->getImagePoint(cv::Point3f(pos.x(), pos.y(), height)); - pos.setX(p2d.x); - pos.setY(p2d.y); - } - else - { - ////////////// - - // Fehlerhaft funktioniert nicht wie gewollt - - ////////////// - // Old 2D mapping of Pixelpoints to RealPositions - pos.setY(-pos.y()); - pos /= mControlWidget->getCalibCoordUnit() / - 100.; // durch 100., da coordsys so gezeichnet, dass 1 bei 100 liegt - - pos = mapFromItem(mCoordItem, pos); // Einheit anpassen... - if(mControlWidget->isCoordUseIntrinsicChecked()) - { - const auto camMat = mControlWidget->getIntrinsicCameraParams(); - pos.rx() -= camMat.getCx(); - pos.ry() -= camMat.getCy(); - } - else - { - pos.rx() -= mImage->width() / 2. - .5; // Bildmitte - pos.ry() -= mImage->height() / 2. - .5; // Bildmitte - } - pos = (mControlWidget->getCameraAltitude() / (mControlWidget->getCameraAltitude() - height)) * - pos; //((a-height)/a)*pos; - - if(mControlWidget->isCoordUseIntrinsicChecked()) - { - const auto camMat = mControlWidget->getIntrinsicCameraParams(); - pos.rx() += camMat.getCx(); - pos.ry() += camMat.getCy(); - } - else - { - pos.rx() += mImage->width() / 2. - .5; // Bildmitte - pos.ry() += mImage->height() / 2. - .5; // Bildmitte - } - } - } - return pos; -} - -// eingabe pos als pixelkoordinate des bildes -// result in cm (mit y-Achse nach oben gerichtet) -// default height = 0. in Headerdatei (in cm) -// wenn kein Bild vorliegt, wird eingabeposition durchgereicht - kommt nicht vor, da kein mouseevent -QPointF ImageItem::getPosReal(QPointF pos, double height) -{ - if(mImage) - { - int bS = mMainWindow->getImageBorderSize(); - - // Switch between 2D and 3D CameraCalibration/Position calculation - if(mControlWidget->getCalibCoordDimension() == 0) - { - // New 3D mapping of Pixelpoints to RealPositions - cv::Point3f p3d = - mMainWindow->getExtrCalibration()->get3DPoint(cv::Point2f(pos.x() - bS, pos.y() - bS), height); - - // ToDo: Getting the floor point of the Person! (Only the x/y-coordinates?) - pos = QPointF(p3d.x, p3d.y); - } - else - { - // statt mControlWidget->getCalibFx() muesste spaeter wert stehen, der im verzerrten Bild fX=fY angibt - // a = mControlWidget->getCalibFx()*getMeterPerPixel(); - // a = mControlWidget->getCameraAltitude(); - // -.5 da pixel von 0..1023 (in skala bis 1024 anfaengt) laufen - if(mControlWidget->isCoordUseIntrinsicChecked()) - { - const auto camMat = mControlWidget->getIntrinsicCameraParams(); - pos.rx() -= camMat.getCx(); - pos.ry() -= camMat.getCy(); - } - else - { - pos.rx() -= mImage->width() / 2. - .5; // Bildmitte - pos.ry() -= mImage->height() / 2. - .5; // Bildmitte - } - pos = ((mControlWidget->getCameraAltitude() - height) / mControlWidget->getCameraAltitude()) * - pos; //((a-height)/a)*pos; - if(mControlWidget->isCoordUseIntrinsicChecked()) - { - const auto camMat = mControlWidget->getIntrinsicCameraParams(); - pos.rx() += camMat.getCx(); - pos.ry() += camMat.getCy(); - } - else - { - pos.rx() += mImage->width() / 2. - .5; // Bildmitte - pos.ry() += mImage->height() / 2. - .5; // Bildmitte - } - // Old 2D mapping of Pixelpoints to RealPositions - pos = mapToItem(mCoordItem, pos); // Einheit anpassen... - pos *= mControlWidget->getCalibCoordUnit() / - 100.; // durch 100., da coordsys so gezeichnet, dass 1 bei 100 liegt - pos.setY(-pos.y()); - } - } - return pos; + emit imageChanged(mImage->width(), mImage->height(), 0); } // event, of moving mouse when mouse button is pressed (grid is over image) diff --git a/src/logoItem.cpp b/src/logoItem.cpp index 2d1d2ac79e9ac41d0b793570b9251a1b2d2f2613..4ba32718e857dbd1189e0977c214f90a3a1e3340 100644 --- a/src/logoItem.cpp +++ b/src/logoItem.cpp @@ -22,6 +22,7 @@ #include <QApplication> #include <QPainter> +#include <QPropertyAnimation> LogoItem::LogoItem(QWidget *wParent, QGraphicsItem *parent) : QGraphicsObject(parent) diff --git a/src/logwindow.cpp b/src/logwindow.cpp index 314880f746da59fd8d47efd4beecfb7a9287e7b8..875b39b336c21f26400f8e9a4d97cc585c4da402 100644 --- a/src/logwindow.cpp +++ b/src/logwindow.cpp @@ -23,6 +23,8 @@ #include "spdlog/sinks/ringbuffer_sink.h" #include "ui_logwindow.h" +#include <QFileDialog> + LogWindow::LogWindow(QWidget *parent, Ui::LogWindow *ui) : QWidget(parent) { mMainWindow = (class Petrack *) parent; diff --git a/src/moCapItem.cpp b/src/moCapItem.cpp index 8c87fc9c62c086dc8ca1af4879e7c09f732ee57e..7db8719b50e064ee1c25f53a8d5c0eac64fed7e9 100644 --- a/src/moCapItem.cpp +++ b/src/moCapItem.cpp @@ -22,6 +22,9 @@ #include "moCapController.h" #include "petrack.h" +#include <QPainter> +#include <QtMath> // for M_PI + /** * @brief Constructor of moCapItem diff --git a/src/petrack.cpp b/src/petrack.cpp index 3f3565bee4130c8dcaf901c63241c3c65b8a8963..98d9c1b5884b3fbd24d7d8b234609f4d33621952 100644 --- a/src/petrack.cpp +++ b/src/petrack.cpp @@ -23,6 +23,7 @@ // Added for Qt5 support #include "IO.h" #include "aboutDialog.h" +#include "analysePlot.h" #include "animation.h" #include "autoCalib.h" #include "autosaveSettings.h" @@ -33,11 +34,15 @@ #include "colorMarkerWidget.h" #include "colorRangeWidget.h" #include "control.h" +#include "coordItem.h" +#include "coordinateSystemBox.h" #include "editMoCapDialog.h" +#include "extrinsicBox.h" #include "filterBeforeBox.h" #include "gridItem.h" #include "helper.h" #include "imageItem.h" +#include "intrinsicBox.h" #include "logger.h" #include "logoItem.h" #include "moCapItem.h" @@ -55,6 +60,7 @@ #include "trackerItem.h" #include "trackerReal.h" #include "view.h" +#include "worldImageCorrespondence.h" #include <QtPrintSupport/QPrintDialog> #include <QtPrintSupport/QPrinter> @@ -122,6 +128,10 @@ Petrack::Petrack(QString petrackVersion) : } }; + auto updateStatusPos = [this]() { setStatusPosReal(); }; + auto updateHeadSize = [this]() { setHeadSize(); }; + auto getBorderSize = [this]() { return getImageBorderSize(); }; + auto *filterBeforeBox = new FilterBeforeBox( nullptr, // reparented when added to layout *getBackgroundFilter(), @@ -130,11 +140,37 @@ Petrack::Petrack(QString petrackVersion) : *getSwapFilter(), updateImageCallback); - mControlWidget = - new Control(*this, *mScene, mReco, *mTrackingRoiItem, *mRecognitionRoiItem, mMissingFrames, filterBeforeBox); + auto *intrinsicBox = new IntrinsicBox(this, *getAutoCalib(), *getCalibFilter(), updateImageCallback); + auto *extrinsicBox = new ExtrinsicBox(this, *getExtrCalibration()); + mImageItem = new ImageItem(this, nullptr); + auto *coordSysBox = new CoordinateSystemBox( + this, + updateStatusPos, + updateHeadSize, + getBorderSize, + *intrinsicBox, + *extrinsicBox, + *mImageItem, + mExtrCalibration); + + mControlWidget = new Control( + *this, + *mScene, + mReco, + *mTrackingRoiItem, + *mRecognitionRoiItem, + mMissingFrames, + filterBeforeBox, + intrinsicBox, + extrinsicBox, + coordSysBox); + + connect(mImageItem, &ImageItem::imageChanged, mControlWidget, &Control::imageSizeChanged); // end setup control + mWorldImageCorrespondence = &mControlWidget->getWorldImageCorrespondence(); + mStereoWidget = new StereoWidget(this); mStereoWidget->setWindowFlags(Qt::Window); mStereoWidget->setWindowTitle("Stereo parameter"); @@ -156,9 +192,6 @@ Petrack::Petrack(QString petrackVersion) : mMultiColorMarkerWidget->setWindowFlags(Qt::Window); mMultiColorMarkerWidget->setWindowTitle("MultiColor marker parameter"); - mImageItem = new ImageItem(this); // durch uebergabe von scene wird indirekt ein scene->addItem() aufgerufen - - mAnimation = new Animation(this); mLogoItem = new LogoItem(this); // durch uebergabe von scene wird indirekt ein scene->addItem() aufgerufen @@ -166,12 +199,11 @@ Petrack::Petrack(QString petrackVersion) : mExtrCalibration.setMainWindow(this); - mGridItem = new GridItem(this); + mGridItem = new GridItem(this, nullptr, coordSysBox); mGridItem->setZValue(2.5); // durch uebergabe von scene wird indirekt ein scene->addItem() aufgerufen - mCoordItem = new CoordItem(this); + mCoordItem = new CoordItem(this, nullptr, coordSysBox); mCoordItem->setZValue(3); // groesser heisst weiter oben - mImageItem->setCoordItem(mCoordItem); mViewWidget = new ViewWidget(this); mView = mViewWidget->view(); @@ -385,15 +417,14 @@ void Petrack::updateSceneRect() if(mControlWidget->getCalibCoordShow()) { double scale = mControlWidget->getCalibCoordScale() / 10.; - double tX = mControlWidget->getCalibCoordTransX() / 10.; - double tY = mControlWidget->getCalibCoordTransY() / 10.; + auto t = mControlWidget->getCalibCoord2DTrans() / 10.; // setzen der bounding box der scene // Faktor 1.1 dient dazu, dass auch Zahl "1" bei coord gut in sichtbaren Bereich passt - double xMin = (tX - 1.1 * scale < -bS) ? tX - 1.1 * scale : -bS; - double yMin = (tY - 1.1 * scale < -bS) ? tY - 1.1 * scale : -bS; - double xMax = (tX + 1.1 * scale > iW - bS) ? tX + 1.1 * scale : iW - bS; - double yMax = (tY + 1.1 * scale > iH - bS) ? tY + 1.1 * scale : iH - bS; + double xMin = (t.x() - 1.1 * scale < -bS) ? t.x() - 1.1 * scale : -bS; + double yMin = (t.y() - 1.1 * scale < -bS) ? t.y() - 1.1 * scale : -bS; + double xMax = (t.x() + 1.1 * scale > iW - bS) ? t.x() + 1.1 * scale : iW - bS; + double yMax = (t.y() + 1.1 * scale > iH - bS) ? t.y() + 1.1 * scale : iH - bS; mScene->setSceneRect(xMin, yMin, xMax - xMin, yMax - yMin); } else @@ -611,12 +642,14 @@ void Petrack::openXml(QDomDocument &doc, bool openSeq) if(frame != -1) { - if(mControlWidget->isFilterBgChecked() && - !loaded) // mit dem anfangs geladenen bild wurde bereits faelschlicherweise bg bestimmt + // used first loaded image to determine bg, should not have happened + if(mControlWidget->isFilterBgChecked() && !loaded) { - mBackgroundFilter.reset(); // erst nach dem springen zu einem frame background bestimmen + // reset background and first skip to selected frame + mBackgroundFilter.reset(); } - mPlayerWidget->skipToFrame(frame); // hier wird updateImage ausgefuehrt + // will call updateImage and update bg + mPlayerWidget->skipToFrame(frame); } else if(loaded) { @@ -971,7 +1004,6 @@ void Petrack::openCameraLiveStream(int camID /* =-1*/) updateWindowTitle(); mPlayerWidget->setFPS(mAnimation->getFPS()); mLogoItem->fadeOut(); - updateCoord(); mPlayerWidget->play(PlayerState::FORWARD); } @@ -1041,7 +1073,6 @@ void Petrack::openSequence(QString fileName) // default fileName = "" updateWindowTitle(); mPlayerWidget->setFPS(mAnimation->getFPS()); mLogoItem->fadeOut(); - updateCoord(); mMissingFrames.reset(); } } @@ -2250,7 +2281,7 @@ void Petrack::setStatusPosReal() // pos in cm { if(mImageItem) { - setStatusPosReal(mImageItem->getPosReal(mMousePosOnImage, getStatusPosRealHeight())); + setStatusPosReal(mWorldImageCorrespondence->getPosReal(mMousePosOnImage, getStatusPosRealHeight())); } } @@ -2263,7 +2294,7 @@ void Petrack::setStatusPosReal(const QPointF &pos) // pos in cm .arg(pos.x(), 6, 'f', 1) .arg(pos.y(), 6, 'f', 1) .arg( - getImageItem()->getAngleToGround( + mWorldImageCorrespondence->getAngleToGround( mMousePosOnImage.x(), mMousePosOnImage.y(), getStatusPosRealHeight()), 5, 'f', @@ -2432,7 +2463,7 @@ void Petrack::setMousePosOnImage(QPointF pos) if(mImage) { mMousePosOnImage = pos; - setStatusPosReal(mImageItem->getPosReal(pos, getStatusPosRealHeight())); + setStatusPosReal(mWorldImageCorrespondence->getPosReal(pos, getStatusPosRealHeight())); // pixel coordinate QPoint pos1((int) (pos.x()) + 1, (int) (pos.y()) + 1); @@ -2510,7 +2541,15 @@ void Petrack::updateControlImage(cv::Mat &img) const int imgWidth = img.cols; const int imgHeight = img.rows; - mControlWidget->imageSizeChanged(imgWidth, imgHeight, diffBorderSize); + // no direct invocation to have correct order of invocations + // (direct invocation gets executed immediately, i.e. before queued connection) + QMetaObject::invokeMethod( + mControlWidget, + "imageSizeChanged", + Qt::ConnectionType::QueuedConnection, + Q_ARG(int, imgWidth), + Q_ARG(int, imgHeight), + Q_ARG(int, diffBorderSize)); } void Petrack::importTracker(QString dest) // default = "" @@ -2701,7 +2740,7 @@ void Petrack::importTracker(QString dest) // default = "" else { // compute image point from 2d calibration - QPointF pos = mImageItem->getPosImage( + QPointF pos = mWorldImageCorrespondence->getPosImage( QPointF(realWorldCoordinates.x(), realWorldCoordinates.y()), realWorldCoordinates.z()); p2d.x = pos.x(); p2d.y = pos.y(); @@ -2778,7 +2817,7 @@ int Petrack::calculateRealTracker() int anz = mTrackerReal->calculate( this, mTracker, - mImageItem, + mWorldImageCorrespondence, mControlWidget->getColorPlot(), mMissingFrames, getImageBorderSize(), @@ -2939,7 +2978,7 @@ void Petrack::exportTracker(QString dest) // default = "" mTrackerReal->calculate( this, mTracker, - mImageItem, + mWorldImageCorrespondence, mControlWidget->getColorPlot(), mMissingFrames, getImageBorderSize(), @@ -3037,7 +3076,7 @@ void Petrack::exportTracker(QString dest) // default = "" mTrackerReal->calculate( this, mTracker, - mImageItem, + mWorldImageCorrespondence, mControlWidget->getColorPlot(), mMissingFrames, getImageBorderSize(), @@ -3094,7 +3133,7 @@ void Petrack::exportTracker(QString dest) // default = "" mTrackerReal->calculate( this, mTracker, - mImageItem, + mWorldImageCorrespondence, mControlWidget->getColorPlot(), mMissingFrames, getImageBorderSize(), @@ -3688,7 +3727,7 @@ void Petrack::setHeadSize(double hS) { if(hS == -1) { - mCmPerPixel = getImageItem()->getCmPerPixel(); + mCmPerPixel = mWorldImageCorrespondence->getCmPerPixel(); // debout << mCmPerPixel <<endl; mHeadSize = (HEAD_SIZE * mControlWidget->getCameraAltitude() / (mControlWidget->getCameraAltitude() - mControlWidget->getDefaultHeight())) / @@ -3736,12 +3775,13 @@ double Petrack::getHeadSize(QPointF *pos, int pers, int frame) h = mPersonStorage.at(pers).height(); if(z > 0) { - return (HEAD_SIZE * mControlWidget->getCameraAltitude() / z) / getImageItem()->getCmPerPixel(); + return (HEAD_SIZE * mControlWidget->getCameraAltitude() / z) / + mWorldImageCorrespondence->getCmPerPixel(); } else if(h > MIN_HEIGHT) { return (HEAD_SIZE * mControlWidget->getCameraAltitude() / (mControlWidget->getCameraAltitude() - h)) / - getImageItem()->getCmPerPixel(); + mWorldImageCorrespondence->getCmPerPixel(); } else { @@ -3777,6 +3817,11 @@ void Petrack::setProFileName(const QString &fileName) updateWindowTitle(); } +const WorldImageCorrespondence &Petrack::getWorldImageCorrespondence() +{ + return *mWorldImageCorrespondence; +} + /** * @brief Return the user's selection of pedestrians/trajectories * diff --git a/src/player.cpp b/src/player.cpp index b83991f514fba4f4979e3b3b5bcc0dfd355043a6..8ea02e6144b48104a6bf7e290b8f082dfde945f9 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -22,6 +22,7 @@ #include "control.h" #include "logger.h" #include "pMessageBox.h" +#include "petrack.h" #include <QApplication> #include <QIntValidator> diff --git a/src/recognition.cpp b/src/recognition.cpp index ae3d293eea74156090d837b4d35ccdb5e02419ee..d3527b42be1014325912fc9ad3576cc31b06ffb9 100644 --- a/src/recognition.cpp +++ b/src/recognition.cpp @@ -33,6 +33,7 @@ #include "pMessageBox.h" #include "roiItem.h" #include "tracker.h" +#include "worldImageCorrespondence.h" #include <QPointF> #include <QRect> @@ -164,15 +165,14 @@ Vec2F autoCorrectColorMarker(const Vec2F &boxImageCentre, Control *controlWidget { Petrack *mainWindow = controlWidget->getMainWindow(); auto extrParams = controlWidget->getExtrinsicParameters(); - cv::Point2f tp = mainWindow->getExtrCalibration()->getImagePoint(cv::Point3f( - -controlWidget->getCalibCoord3DTransX() - extrParams.trans1, - -controlWidget->getCalibCoord3DTransY() - extrParams.trans2, - 0)); - Vec2F pixUnderCam(tp.x, tp.y); // CvPoint - Vec2F boxImageCentreWithBorder = boxImageCentre; + auto trans = controlWidget->getCalibCoord3DTrans(); + cv::Point2f tp = mainWindow->getExtrCalibration()->getImagePoint( + cv::Point3f(-trans.x() - extrParams.trans1, -trans.y() - extrParams.trans2, 0)); + Vec2F pixUnderCam(tp.x, tp.y); // CvPoint + Vec2F boxImageCentreWithBorder = boxImageCentre; boxImageCentreWithBorder += Vec2F(mainWindow->getImageBorderSize(), mainWindow->getImageBorderSize()); pixUnderCam += Vec2F(mainWindow->getImageBorderSize(), mainWindow->getImageBorderSize()); - float angle = 90 - mainWindow->getImageItem()->getAngleToGround( + float angle = 90 - mainWindow->getWorldImageCorrespondence().getAngleToGround( boxImageCentreWithBorder.x(), boxImageCentreWithBorder.y(), 175); // Hoehe 175 cm ist egal, da auf jeder Hoehe gleicher Winkel @@ -320,20 +320,25 @@ Vec2F autoCorrectColorMarker(const Vec2F &boxImageCentre, Control *controlWidget * @brief Restricts the position in which the black dot should be according to position in image. * * @param[in] blob ColorBlob for which to restrict the position - * @param[in] mainWindow pointer to Petrack for getImageItem + * @param[in] worldImageCorr reference to world to image correspondence * @param[in] bS bordersize * @param[in,out] cropRect cropRect to restrict/resize */ -void detail::restrictPositionBlackDot(ColorBlob &blob, ImageItem *imageItem, int bS, cv::Rect &cropRect) +void detail::restrictPositionBlackDot( + ColorBlob &blob, + const WorldImageCorrespondence *worldImageCorr, + int bS, + cv::Rect &cropRect) { double xy, x1, x2, y1, y2; Vec2F &boxImageCentre = blob.imageCenter; - xy = imageItem->getAngleToGround(boxImageCentre.x() + bS, boxImageCentre.y() + bS, 175); - x1 = imageItem->getAngleToGround(boxImageCentre.x() + bS + 10, boxImageCentre.y() + bS, 175); - x2 = imageItem->getAngleToGround(boxImageCentre.x() + bS - 10, boxImageCentre.y() + bS, 175); - y1 = imageItem->getAngleToGround(boxImageCentre.x() + bS, boxImageCentre.y() + bS + 10, 175); - y2 = imageItem->getAngleToGround(boxImageCentre.x() + bS, boxImageCentre.y() + bS - 10, 175); + + xy = worldImageCorr->getAngleToGround(boxImageCentre.x() + bS, boxImageCentre.y() + bS, 175); + x1 = worldImageCorr->getAngleToGround(boxImageCentre.x() + bS + 10, boxImageCentre.y() + bS, 175); + x2 = worldImageCorr->getAngleToGround(boxImageCentre.x() + bS - 10, boxImageCentre.y() + bS, 175); + y1 = worldImageCorr->getAngleToGround(boxImageCentre.x() + bS, boxImageCentre.y() + bS + 10, 175); + y2 = worldImageCorr->getAngleToGround(boxImageCentre.x() + bS, boxImageCentre.y() + bS - 10, 175); double subFactorBig = 1. - .75 * (90. - xy) / 90.; // -.5 //in 1.0..0.25 // xy in 0..90 constexpr double subFactorSmall = .85; // .9 @@ -457,16 +462,16 @@ void detail::refineWithBlackDot( QList<TrackPoint> &crossList, const BlackDotOptions &options) { - constexpr int border = 4; // zusaetzlicher rand um subrects - const int bS = options.borderSize; - const bool restrictPosition = options.restrictPosition; - ImageItem *imageItem = options.imageItem; - const QColor midHue = options.midHue; - const double dotSize = options.dotSize; - const bool ignoreWithoutMarker = options.ignoreWithoutMarker; - const bool autoCorrect = options.autoCorrect; - const bool autoCorrectOnlyExport = options.autoCorrectOnlyExport; - Control *controlWidget = options.controlWidget; + constexpr int border = 4; // zusaetzlicher rand um subrects + const int bS = options.borderSize; + const bool restrictPosition = options.restrictPosition; + const WorldImageCorrespondence *worldImageCorr = options.worldImageCorr; + const QColor midHue = options.midHue; + const double dotSize = options.dotSize; + const bool ignoreWithoutMarker = options.ignoreWithoutMarker; + const bool autoCorrect = options.autoCorrect; + const bool autoCorrectOnlyExport = options.autoCorrectOnlyExport; + Control *controlWidget = options.controlWidget; for(ColorBlob &blob : blobs) { @@ -483,7 +488,7 @@ void detail::refineWithBlackDot( if(restrictPosition) { - restrictPositionBlackDot(blob, imageItem, bS, cropRect); + restrictPositionBlackDot(blob, worldImageCorr, bS, cropRect); } // cvtColor results in really dark images, especially with red shades @@ -527,7 +532,7 @@ void detail::refineWithBlackDot( subMaxExpansion = subBox.size.width; } - QPointF cmPerPixel = imageItem->getCmPerPixel( + QPointF cmPerPixel = worldImageCorr->getCmPerPixel( cropRect.x + subBox.center.x, cropRect.y + subBox.center.y, controlWidget->getDefaultHeight()); double cmPerPixelAvg = (cmPerPixel.x() + cmPerPixel.y()) / 2.; double markerSize = @@ -865,7 +870,7 @@ void findMultiColorMarker( options.midHue = midHue; options.dotSize = dotSize; options.controlWidget = controlWidget; - options.imageItem = mainWindow->getImageItem(); + options.worldImageCorr = &mainWindow->getWorldImageCorrespondence(); // adds to crosslist refineWithBlackDot(blobs, img, crossList, options); @@ -1064,12 +1069,13 @@ QList<TrackPoint> detail::findCodeMarker( myRound(mainWindow->getRecoRoiItem()->rect().y()), myRound(mainWindow->getRecoRoiItem()->rect().width()), myRound(mainWindow->getRecoRoiItem()->rect().height())); - QPointF p1 = mainWindow->getImageItem()->getCmPerPixel(rect.x(), rect.y(), controlWidget->getDefaultHeight()); - QPointF p2 = mainWindow->getImageItem()->getCmPerPixel( + QPointF p1 = mainWindow->getWorldImageCorrespondence().getCmPerPixel( + rect.x(), rect.y(), controlWidget->getDefaultHeight()); + QPointF p2 = mainWindow->getWorldImageCorrespondence().getCmPerPixel( rect.x() + rect.width(), rect.y(), controlWidget->getDefaultHeight()); - QPointF p3 = mainWindow->getImageItem()->getCmPerPixel( + QPointF p3 = mainWindow->getWorldImageCorrespondence().getCmPerPixel( rect.x(), rect.y() + rect.height(), controlWidget->getDefaultHeight()); - QPointF p4 = mainWindow->getImageItem()->getCmPerPixel( + QPointF p4 = mainWindow->getWorldImageCorrespondence().getCmPerPixel( rect.x() + rect.width(), rect.y() + rect.height(), controlWidget->getDefaultHeight()); double cmPerPixelMin = std::min({p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y(), p4.x(), p4.y()}); @@ -1093,7 +1099,7 @@ QList<TrackPoint> detail::findCodeMarker( } else // 2D { - double cmPerPixel = mainWindow->getImageItem()->getCmPerPixel(); + double cmPerPixel = mainWindow->getWorldImageCorrespondence().getCmPerPixel(); minMarkerPerimeterRate = (parameters.getMinMarkerPerimeter() * 4 / cmPerPixel) / std::max(mainWindow->getImage()->width() - borderSize, mainWindow->getImage()->height() - borderSize); diff --git a/src/roiItem.cpp b/src/roiItem.cpp index 964c822a09197c6427d0866459a8a9bd72cea0ee..fa265fb24412d852cdecb4de3d5f016280686855 100644 --- a/src/roiItem.cpp +++ b/src/roiItem.cpp @@ -20,6 +20,7 @@ #include "petrack.h" +#include <QGraphicsSceneMouseEvent> RoiItem::RoiItem(QWidget *wParent, const QColor &color) : QObject(wParent) { diff --git a/src/tracker.cpp b/src/tracker.cpp index a3add973b5926f262967bf8dc922b05fbb04cefd..bba7bd866c6fcaa3ba6c5fc7070260bd027aa903 100644 --- a/src/tracker.cpp +++ b/src/tracker.cpp @@ -19,7 +19,6 @@ #include "tracker.h" #include "animation.h" -#include "control.h" #include "helper.h" #include "logger.h" #include "multiColorMarkerWidget.h" diff --git a/src/trackerItem.cpp b/src/trackerItem.cpp index c9ff3a2227cc9e6a1638569ababd6362d2f30848..1ba9a7f120739e68029e55667ae717c9022a79ee 100644 --- a/src/trackerItem.cpp +++ b/src/trackerItem.cpp @@ -26,6 +26,7 @@ #include "roiItem.h" #include "tracker.h" #include "view.h" +#include "worldImageCorrespondence.h" #include <QInputDialog> #include <QtWidgets> @@ -648,7 +649,8 @@ void TrackerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*op } p3d_height.z = 0; cv::Point2f p2d_ground = mMainWindow->getExtrCalibration()->getImagePoint(p3d_height); - QPointF axis = mMainWindow->getImageItem()->getCmPerPixel(p2d_ground.x, p2d_ground.y, 0); + QPointF axis = + mMainWindow->getWorldImageCorrespondence().getCmPerPixel(p2d_ground.x, p2d_ground.y, 0); painter->drawLine(QLineF( p2d_ground.x - cross_size * 0.5 * pow(axis.x(), -1), p2d_ground.y - cross_size * 0.5 * pow(axis.y(), -1), diff --git a/src/trackerReal.cpp b/src/trackerReal.cpp index 3773b98d7b051e9f2978f3e0e71f85ce3a5b2573..aa0cdf82e7b5bc7bf286036710446e2d7111e226 100644 --- a/src/trackerReal.cpp +++ b/src/trackerReal.cpp @@ -27,6 +27,7 @@ #include "petrack.h" #include "player.h" #include "recognition.h" +#include "worldImageCorrespondence.h" #include <fstream> #include <opencv2/highgui.hpp> @@ -124,26 +125,26 @@ TrackerReal::TrackerReal(QWidget *wParent, PersonStorage &storage) : // default: int imageBorderSize = 0, bool missingFramesInserted = true, bool useTrackpoints = false int TrackerReal::calculate( - Petrack *petrack, - Tracker *tracker, - ImageItem *imageItem, - ColorPlot *colorPlot, - MissingFrames &missingFrames, - int imageBorderSize, - bool missingFramesInserted, - bool useTrackpoints, - bool alternateHeight, - double altitude, - bool useCalibrationCenter, - bool exportElimTp, - bool exportElimTrj, - bool exportSmooth, - bool exportViewingDirection, - bool exportAngleOfView, - bool exportMarkerID, - bool exportAutoCorrect) + Petrack *petrack, + Tracker *tracker, + const WorldImageCorrespondence *worldImageCorr, + ColorPlot *colorPlot, + MissingFrames &missingFrames, + int imageBorderSize, + bool missingFramesInserted, + bool useTrackpoints, + bool alternateHeight, + double altitude, + bool useCalibrationCenter, + bool exportElimTp, + bool exportElimTrj, + bool exportSmooth, + bool exportViewingDirection, + bool exportAngleOfView, + bool exportMarkerID, + bool exportAutoCorrect) { - if(tracker || imageItem || colorPlot) + if(tracker || colorPlot) { if(size() > 0) { @@ -182,13 +183,13 @@ int TrackerReal::calculate( QList<int> tmpMissingList; // frame nr QList<int> tmpMissingListAnz; // anzahl frames TrackPersonReal trackPersonReal; - QPointF center = imageItem->getPosReal( - QPointF(imageItem->boundingRect().width() / 2., imageItem->boundingRect().height() / 2.), 0.); - Vec3F sp; - int tsize; - int extrapolated; - QPointF colPos; - float angle; + auto imgRect = mMainWindow->getImage()->size(); + QPointF center = worldImageCorr->getPosReal(QPointF(imgRect.width() / 2., imgRect.height() / 2.), 0.); + Vec3F sp; + int tsize; + int extrapolated; + QPointF colPos; + float angle; const auto &persons = mPersonStorage.getPersons(); for(size_t i = 0; i < persons.size(); ++i) // ueber trajektorien @@ -320,7 +321,7 @@ int TrackerReal::calculate( moveDir += reco::autoCorrectColorMarker(person.at(j), mMainWindow->getControlWidget()); } - pos = imageItem->getPosReal((person.at(j) + moveDir + br).toQPointF(), bestZ); + pos = worldImageCorr->getPosReal((person.at(j) + moveDir + br).toQPointF(), bestZ); trackPersonReal.addEnd(Vec3F(pos.x(), pos.y(), bestZ), firstFrame + j); } } @@ -331,11 +332,11 @@ int TrackerReal::calculate( moveDir += reco::autoCorrectColorMarker(person.at(j), mMainWindow->getControlWidget()); } - pos = imageItem->getPosReal((person.at(j) + moveDir + br).toQPointF(), height); + pos = worldImageCorr->getPosReal((person.at(j) + moveDir + br).toQPointF(), height); trackPersonReal.addEnd(pos, firstFrame + j); if(exportAngleOfView) { - angle = (90. - imageItem->getAngleToGround( + angle = (90. - worldImageCorr->getAngleToGround( (person.at(j) + br).x(), (person.at(j) + br).y(), height)) * PI / 180.; trackPersonReal.last().setAngleOfView(angle); @@ -369,8 +370,8 @@ int TrackerReal::calculate( if((exportViewingDirection) && (person.at(j).color().isValid())) // wenn blickrichtung mit ausgegeben werden soll { - colPos = - imageItem->getPosReal((person.at(j).colPoint() + moveDir + br).toQPointF(), height); + colPos = worldImageCorr->getPosReal( + (person.at(j).colPoint() + moveDir + br).toQPointF(), height); trackPersonReal.last().setViewDirection(colPos - pos); } } @@ -418,9 +419,10 @@ int TrackerReal::calculate( reco::autoCorrectColorMarker(person.at(j), mMainWindow->getControlWidget()); } - pos2 = (imageItem->getPosReal((person.at(j + 1) + moveDir + br).toQPointF(), height) - - pos) / - (anz + 1); + pos2 = + (worldImageCorr->getPosReal((person.at(j + 1) + moveDir + br).toQPointF(), height) - + pos) / + (anz + 1); for(f = 1; f <= anz; ++f) { trackPersonReal.addEnd(pos + f * pos2, -1); // -1 zeigt an, dass nur interpoliert @@ -887,7 +889,7 @@ std::vector<std::unordered_map<int, double>> utils::computeDisplacement( std::vector<std::unordered_map<int, double>> displacementsPerFrame(maxFrameNum + 1); // compute window size - auto cmPerPixelXYMiddle = petrack->getImageItem()->getCmPerPixel( + auto cmPerPixelXYMiddle = petrack->getWorldImageCorrespondence().getCmPerPixel( static_cast<float>(prevFrame.cols / 2), static_cast<float>(prevFrame.rows / 2), static_cast<float>(petrack->getControlWidget()->getDefaultHeight())); @@ -936,7 +938,7 @@ std::vector<std::unordered_map<int, double>> utils::computeDisplacement( { auto id = idsInFrame[frame - 1][i]; - auto cmPerPixelXY = petrack->getImageItem()->getCmPerPixel( + auto cmPerPixelXY = petrack->getWorldImageCorrespondence().getCmPerPixel( nextFeaturePoint[i].x, nextFeaturePoint[i].y, petrack->getControlWidget()->getDefaultHeight()); auto mPerPixel = (cmPerPixelXY.x() + cmPerPixelXY.y()) / 2. / 100.; diff --git a/src/vector.cpp b/src/vector.cpp index 2af71bcec3145596173216eb7358b558ef61f021..bf45926255d7b159f9a96b96e9f72d44a8ab1814 100644 --- a/src/vector.cpp +++ b/src/vector.cpp @@ -30,6 +30,11 @@ Vec3F::Vec3F(double x, double y, double z) : mX(x), mY(y), mZ(z) {} Vec3F::Vec3F(const cv::Point3f &v) : mX(v.x), mY(v.y), mZ(v.z) {} +cv::Point3f Vec3F::toCvPoint() +{ + return cv::Point3f(static_cast<float>(mX), static_cast<float>(mY), static_cast<float>(mZ)); +} + double Vec3F::x() const { return mX; diff --git a/tests/unit_test/CMakeLists.txt b/tests/unit_test/CMakeLists.txt index a08afa24da8342568149e58420541a0a1cb2f4f5..71f689b799abc92ffcf26d09e09b5f84e20d328d 100644 --- a/tests/unit_test/CMakeLists.txt +++ b/tests/unit_test/CMakeLists.txt @@ -16,5 +16,6 @@ target_sources(petrack_tests PRIVATE tst_intrinsicBox.cpp util.h tst_extrinsicBox.cpp + tst_coordinateSystemBox.cpp tst_tracker.cpp ) diff --git a/tests/unit_test/tst_control.cpp b/tests/unit_test/tst_control.cpp index ba7e074d72cc82c74ca2d4aff6e79b091126effe..e8caf348eb8c1484390d5c4e64ac51e872fb4364 100644 --- a/tests/unit_test/tst_control.cpp +++ b/tests/unit_test/tst_control.cpp @@ -18,6 +18,7 @@ #include "control.h" #include "imageItem.h" +#include "petrack.h" #include "ui_control.h" #include "util.h" #include "view.h" diff --git a/tests/unit_test/tst_coordinateSystemBox.cpp b/tests/unit_test/tst_coordinateSystemBox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1ee0d7d1d23d8c38ead94b8ab1481f88bf87598 --- /dev/null +++ b/tests/unit_test/tst_coordinateSystemBox.cpp @@ -0,0 +1,173 @@ +/* + * PeTrack - Software for tracking pedestrians movement in videos + * Copyright (C) 2023 Forschungszentrum JĂĽlich GmbH, IAS-7 + * + * 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 "autoCalib.h" +#include "calibFilter.h" +#include "coordinateSystemBox.h" +#include "extrinsicBox.h" +#include "imageItem.h" +#include "intrinsicBox.h" +#include "petrack.h" +#include "qsignalspy.h" +#include "ui_coordinateSystemBox.h" + +#include <catch2/catch.hpp> + +bool operator==(const CoordPose2D &lhs, const CoordPose2D &rhs) +{ + return lhs.angle == rhs.angle && lhs.position == rhs.position && lhs.scale == rhs.scale && lhs.unit == rhs.unit; +} + +TEST_CASE("CoordinateSystemBox: display of values in UI") +{ + Petrack petrack{"Unkown"}; + Autosave autosave(petrack); + PersonStorage storage(petrack, autosave); + ExtrCalibration extrCalib(storage); + ExtrinsicBox extrBox(nullptr, extrCalib); + AutoCalib autoCalib{}; + CalibFilter calibFilter; + IntrinsicBox intrBox{&petrack, autoCalib, calibFilter, []() {}}; + ImageItem imageItem{&petrack, nullptr}; + auto *ui = new Ui::CoordinateSystemBox(); + CoordinateSystemBox coordSysBox{ + &petrack, ui, []() {}, []() {}, []() { return 0; }, intrBox, extrBox, imageItem, extrCalib}; + + SECTION("Propagation Model to UI / 2D calibration") + { + CoordPose2D pose2d; + pose2d.angle = 254; + pose2d.position = {548, 533}; + pose2d.scale = 1337; + pose2d.unit = 42; + + coordSysBox.setCoordPose2D(pose2d); + + CHECK(ui->coordRotate->value() == pose2d.angle); + CHECK(ui->coordTransX->value() == pose2d.position.x()); + CHECK(ui->coordTransY->value() == pose2d.position.y()); + CHECK(ui->coordScale->value() == pose2d.scale); + CHECK(ui->coordUnit->value() == pose2d.unit); + } + + SECTION("Propagation Model to UI / 3D calibration") + { + CoordPose3D pose3d; + pose3d.position = Vec3F{123, 456, 432}; + // swap can only be changed from ui; will not be tested here + pose3d.swap = {false, true, false}; + + coordSysBox.setCoordTrans3D(pose3d.position); + CHECK(ui->coord3DTransX->value() == pose3d.position.x()); + CHECK(ui->coord3DTransY->value() == pose3d.position.y()); + CHECK(ui->coord3DTransZ->value() == pose3d.position.z()); + + coordSysBox.setCoord3DAxeLen(42); + CHECK(ui->coord3DAxeLen->value() == 42); + } + + SECTION("Propagation UI to Model / 2D calibration") + { + CoordPose2D pose2d; + pose2d.angle = 254; + pose2d.position = {548, 533}; + pose2d.scale = 1337; + pose2d.unit = 42; + + ui->coordRotate->setValue(pose2d.angle); + ui->coordTransX->setValue(pose2d.position.x()); + ui->coordTransY->setValue(pose2d.position.y()); + ui->coordScale->setValue(pose2d.scale); + ui->coordUnit->setValue(pose2d.unit); + + CHECK(coordSysBox.getCoordPose2D() == pose2d); + + ui->coordAltitude->setValue(852); + CHECK(coordSysBox.getCameraAltitude() == 852); + + const bool useIntrinsic = !ui->coordUseIntrinsic->isChecked(); + ui->coordUseIntrinsic->setChecked(useIntrinsic); + CHECK(coordSysBox.isCoordUseIntrinsicChecked() == useIntrinsic); + } + + SECTION("Propagation UI to Model / 3D calibration") + { + Vec3F trans{123, 456, 432}; + + ui->coord3DTransX->setValue(trans.x()); + ui->coord3DTransY->setValue(trans.y()); + ui->coord3DTransZ->setValue(trans.z()); + CHECK(coordSysBox.getCoordTrans3D() == trans); + + SwapAxis swap{false, true, false}; + ui->coord3DSwapX->setChecked(swap.x); + ui->coord3DSwapY->setChecked(swap.y); + ui->coord3DSwapZ->setChecked(swap.z); + CHECK(coordSysBox.getSwap3D() == swap); + + ui->coord3DAxeLen->setValue(852); + CHECK(coordSysBox.getCoord3DAxeLen() == 852); + + const bool showVanish = !ui->extVanishPointsShow->isChecked(); + ui->extVanishPointsShow->setChecked(showVanish); + CHECK(coordSysBox.getCalibExtrVanishPointsShow() == showVanish); + + const bool showCalibPoints = !ui->extCalibPointsShow->isChecked(); + ui->extCalibPointsShow->setChecked(showCalibPoints); + CHECK(coordSysBox.getCalibExtrCalibPointsShow() == showCalibPoints); + } +} + +TEST_CASE("CoordinateSystemBox: UI logic") +{ + Petrack petrack{"Unkown"}; + Autosave autosave(petrack); + PersonStorage storage(petrack, autosave); + ExtrCalibration extrCalib(storage); + ExtrinsicBox extrBox(nullptr, extrCalib); + AutoCalib autoCalib{}; + CalibFilter calibFilter; + IntrinsicBox intrBox{&petrack, autoCalib, calibFilter, []() {}}; + ImageItem imageItem{&petrack, nullptr}; + auto *ui = new Ui::CoordinateSystemBox(); + int updateStatusPosCounter = 0; + int updateHeadSizeCounter = 0; + CoordinateSystemBox coordSysBox{ + &petrack, + ui, + [&]() { updateStatusPosCounter++; }, + [&]() { updateHeadSizeCounter++; }, + []() { return 0; }, + intrBox, + extrBox, + imageItem, + extrCalib}; + + SECTION("Selection of 2D/3D") + { + constexpr int index3D = 0; + constexpr int index2D = 1; + QSignalSpy extrChangedSpy(&extrBox, &ExtrinsicBox::enabledChanged); + // NOTE: default is 3D; enabled + ui->coordTab->setCurrentIndex(index2D); + CHECK(extrChangedSpy.count() == 1); + + ui->coordTab->setCurrentIndex(index3D); + CHECK(extrChangedSpy.count() == 2); + } +} diff --git a/tests/unit_test/tst_extrinsicBox.cpp b/tests/unit_test/tst_extrinsicBox.cpp index fd5d1cb9fa5f2b8c53e89e7f5995a9f8ae637a42..d8ba1afeccb258a079cc11559e2ea3bf6d5e67cb 100644 --- a/tests/unit_test/tst_extrinsicBox.cpp +++ b/tests/unit_test/tst_extrinsicBox.cpp @@ -32,7 +32,7 @@ TEST_CASE("ExtrinsicBox: display of values in UI") PersonStorage storage(petrack, autosave); ExtrCalibration calib(storage); Ui::extr *ui = new Ui::extr(); - ExtrinsicBox extrBox(nullptr, ui, calib, []() {}); + ExtrinsicBox extrBox(nullptr, ui, calib); ExtrinsicParameters params; params.rot1 = 0.5; @@ -79,7 +79,7 @@ TEST_CASE("ExtrinsicBox: reading/writing xml") Autosave autosave(petrack); PersonStorage storage(petrack, autosave); ExtrCalibration calib(storage); - ExtrinsicBox extrBox(nullptr, calib, []() {}); + ExtrinsicBox extrBox(nullptr, calib); WHEN("We change the extrinsic parameters") { @@ -105,7 +105,7 @@ TEST_CASE("ExtrinsicBox: reading/writing xml") Autosave autosave(petrack); PersonStorage storage(petrack, autosave); ExtrCalibration calib(storage); - ExtrinsicBox extrBox(nullptr, calib, []() {}); + ExtrinsicBox extrBox(nullptr, calib); extrBox.getXml(elem); CHECK(extrBox.getExtrinsicParameters() == params); diff --git a/tests/unit_test/tst_moCapController.cpp b/tests/unit_test/tst_moCapController.cpp index 14c1904160f67c2b2afe398dbb7652b958783e93..8da59a0aa8a69f6c28ee3dc0d415df64551917ed 100644 --- a/tests/unit_test/tst_moCapController.cpp +++ b/tests/unit_test/tst_moCapController.cpp @@ -30,7 +30,7 @@ class ExtrCalibMock : public trompeloeil::mock_interface<ExtrCalibration> { public: ExtrCalibMock(PersonStorage &storage) : trompeloeil::mock_interface<ExtrCalibration>(storage) {} - MAKE_MOCK1(getImagePoint, cv::Point2f(cv::Point3f), override); + MAKE_CONST_MOCK1(getImagePoint, cv::Point2f(cv::Point3f), override); }; SCENARIO("I want to get the render data with one person loaded", "[ui]") diff --git a/ui/control.ui b/ui/control.ui index b51c06a482e04725feab2176d0ceafa0a2f4f66c..af8d50174f3d632b0c9421645649464d3f45e48e 100644 --- a/ui/control.ui +++ b/ui/control.ui @@ -150,1134 +150,6 @@ </sizepolicy> </property> <layout class="QVBoxLayout" name="verticalLayout_13"> - <item> - <widget class="QGroupBox" name="align_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>300</width> - <height>271</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>16777215</height> - </size> - </property> - <property name="title"> - <string>coordinate system</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_14"> - <property name="leftMargin"> - <number>5</number> - </property> - <property name="topMargin"> - <number>5</number> - </property> - <property name="rightMargin"> - <number>5</number> - </property> - <property name="bottomMargin"> - <number>5</number> - </property> - <item> - <layout class="QGridLayout" name="gridLayout_7" columnstretch="0,0,1"> - <item row="0" column="0"> - <widget class="QCheckBox" name="coordShow"> - <property name="minimumSize"> - <size> - <width>57</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Show the coordinate system.</string> - </property> - <property name="text"> - <string>show</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QCheckBox" name="coordFix"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Fix the coordinate system</string> - </property> - <property name="text"> - <string>fix</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer_9"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <widget class="QTabWidget" name="coordTab"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="tabPosition"> - <enum>QTabWidget::North</enum> - </property> - <property name="tabShape"> - <enum>QTabWidget::Rounded</enum> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <property name="elideMode"> - <enum>Qt::ElideNone</enum> - </property> - <property name="usesScrollButtons"> - <bool>true</bool> - </property> - <property name="tabsClosable"> - <bool>false</bool> - </property> - <widget class="QWidget" name="coordTab3D"> - <attribute name="title"> - <string> 3D </string> - </attribute> - <attribute name="toolTip"> - <string>Select for 3D coordinatesystem</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <item> - <layout class="QGridLayout" name="gridLayout_5"> - <property name="spacing"> - <number>4</number> - </property> - <item row="0" column="2"> - <widget class="PSpinBox" name="coord3DTransX_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="minimum"> - <number>-10000</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="PSpinBox" name="coord3DTransZ_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> - </property> - <property name="minimum"> - <number>-10000</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="PSpinBox" name="coord3DTransY_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in y-direction.</string> - </property> - <property name="minimum"> - <number>-10000</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QScrollBar" name="coord3DTransZ"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> - </property> - <property name="minimum"> - <number>-10000</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - <property name="pageStep"> - <number>10</number> - </property> - <property name="sliderPosition"> - <number>0</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QScrollBar" name="coord3DTransX"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>50</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="minimum"> - <number>-10000</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - <property name="pageStep"> - <number>10</number> - </property> - <property name="value"> - <number>0</number> - </property> - <property name="sliderPosition"> - <number>0</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QScrollBar" name="coord3DTransY"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in y-direction.</string> - </property> - <property name="minimum"> - <number>-10000</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - <property name="value"> - <number>0</number> - </property> - <property name="sliderPosition"> - <number>0</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_57"> - <property name="toolTip"> - <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> - </property> - <property name="text"> - <string>z:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_56"> - <property name="toolTip"> - <string>Scale the coordinate system.</string> - </property> - <property name="text"> - <string>axis length:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_55"> - <property name="toolTip"> - <string>Translate the coordinate system in y-direction.</string> - </property> - <property name="text"> - <string>y:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_54"> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="text"> - <string>translate [cm] x:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="PSpinBox" name="coord3DAxeLen_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Scale the coordinate system.</string> - </property> - <property name="suffix"> - <string> cm</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - <property name="value"> - <number>200</number> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QScrollBar" name="coord3DAxeLen"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Scale the coordinate system.</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - <property name="value"> - <number>200</number> - </property> - <property name="sliderPosition"> - <number>200</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLabel" name="label_60"> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="text"> - <string>swap axis:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="coord3DSwapX"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="text"> - <string>X-axis</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="coord3DSwapY"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="text"> - <string>Y-axis</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="coord3DSwapZ"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="text"> - <string>Z-axis</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <item> - <widget class="QLabel" name="label_61"> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="text"> - <string> show:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="extCalibPointsShow"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="text"> - <string>calibration points</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="extVanishPointsShow"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="text"> - <string>vanish points</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_6"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QWidget" name="coordTab2D"> - <attribute name="title"> - <string> 2D </string> - </attribute> - <attribute name="toolTip"> - <string>Select for 2D coordinatesystem</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <layout class="QGridLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>4</number> - </property> - <item row="1" column="2"> - <widget class="PSpinBox" name="coordTransX_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>18</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>18</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_34"> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="text"> - <string>translate x:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QScrollBar" name="coordTransX"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in x-direction.</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - <property name="pageStep"> - <number>10</number> - </property> - <property name="value"> - <number>0</number> - </property> - <property name="sliderPosition"> - <number>0</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_32"> - <property name="toolTip"> - <string>Translate the coordinate system in y-direction.</string> - </property> - <property name="text"> - <string>y:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QScrollBar" name="coordTransY"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in y-direction.</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - <property name="value"> - <number>0</number> - </property> - <property name="sliderPosition"> - <number>0</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_33"> - <property name="toolTip"> - <string>Scale the coordinate system.</string> - </property> - <property name="text"> - <string>scale:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QScrollBar" name="coordScale"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>Scale the coordinate system.</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>100000</number> - </property> - <property name="value"> - <number>100</number> - </property> - <property name="sliderPosition"> - <number>100</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="PSpinBox" name="coordTransY_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>18</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>18</height> - </size> - </property> - <property name="toolTip"> - <string>Translate the coordinate system in y-direction.</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>10000</number> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="PSpinBox" name="coordScale_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>18</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>18</height> - </size> - </property> - <property name="toolTip"> - <string>Scale the coordinate system.</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>100000</number> - </property> - <property name="value"> - <number>100</number> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_35"> - <property name="toolTip"> - <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> - </property> - <property name="text"> - <string>rotate:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QScrollBar" name="coordRotate"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>100</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="toolTip"> - <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>3600</number> - </property> - <property name="sliderPosition"> - <number>0</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="PSpinBox" name="coordRotate_spin"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>18</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>18</height> - </size> - </property> - <property name="toolTip"> - <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>3600</number> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QGridLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>6</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="label_14"> - <property name="text"> - <string>camera altitude [cm]:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="PDoubleSpinBox" name="coordAltitude"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>18</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>18</height> - </size> - </property> - <property name="alignment"> - <set>Qt::AlignRight</set> - </property> - <property name="suffix"> - <string/> - </property> - <property name="decimals"> - <number>1</number> - </property> - <property name="minimum"> - <double>0.100000000000000</double> - </property> - <property name="maximum"> - <double>9999.000000000000000</double> - </property> - <property name="value"> - <double>535.000000000000000</double> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="coordAltitudeMeasured"> - <property name="minimumSize"> - <size> - <width>90</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>(measured: 535.0)</string> - </property> - </widget> - </item> - <item row="0" column="3"> - <spacer name="horizontalSpacer_8"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <layout class="QGridLayout"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>6</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="label_37"> - <property name="minimumSize"> - <size> - <width>57</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>unit [cm]:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="PDoubleSpinBox" name="coordUnit"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>18</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>18</height> - </size> - </property> - <property name="alignment"> - <set>Qt::AlignRight</set> - </property> - <property name="suffix"> - <string/> - </property> - <property name="decimals"> - <number>0</number> - </property> - <property name="minimum"> - <double>1.000000000000000</double> - </property> - <property name="maximum"> - <double>9999.000000000000000</double> - </property> - <property name="singleStep"> - <double>1.000000000000000</double> - </property> - <property name="value"> - <double>100.000000000000000</double> - </property> - </widget> - </item> - <item row="0" column="2"> - <spacer> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <widget class="QCheckBox" name="coordUseIntrinsic"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>17</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>17</height> - </size> - </property> - <property name="text"> - <string>use intrinsic center for calculating real position</string> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - </item> <item> <widget class="QGroupBox" name="align"> <property name="sizePolicy"> @@ -6150,18 +5022,6 @@ </customwidget> </customwidgets> <tabstops> - <tabstop>coordShow</tabstop> - <tabstop>coordFix</tabstop> - <tabstop>coordTab</tabstop> - <tabstop>coord3DTransX_spin</tabstop> - <tabstop>coord3DTransY_spin</tabstop> - <tabstop>coord3DTransZ_spin</tabstop> - <tabstop>coord3DAxeLen_spin</tabstop> - <tabstop>coord3DSwapX</tabstop> - <tabstop>coord3DSwapY</tabstop> - <tabstop>coord3DSwapZ</tabstop> - <tabstop>extCalibPointsShow</tabstop> - <tabstop>extVanishPointsShow</tabstop> <tabstop>gridShow</tabstop> <tabstop>gridFix</tabstop> <tabstop>gridTab</tabstop> @@ -6283,16 +5143,9 @@ <tabstop>scrollArea_3</tabstop> <tabstop>tabs</tabstop> <tabstop>scrollArea</tabstop> - <tabstop>coordScale_spin</tabstop> - <tabstop>coordUnit</tabstop> - <tabstop>coordTransX_spin</tabstop> <tabstop>gridTransY_spin</tabstop> <tabstop>scrollArea_2</tabstop> - <tabstop>coordTransY_spin</tabstop> <tabstop>gridRot_spin</tabstop> - <tabstop>coordAltitude</tabstop> - <tabstop>coordUseIntrinsic</tabstop> - <tabstop>coordRotate_spin</tabstop> <tabstop>gridScale_spin</tabstop> <tabstop>scrollArea_4</tabstop> <tabstop>gridTransX_spin</tabstop> @@ -6379,22 +5232,6 @@ </hint> </hints> </connection> - <connection> - <sender>coordTransY</sender> - <signal>valueChanged(int)</signal> - <receiver>coordTransY_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>92</x> - <y>713</y> - </hint> - <hint type="destinationlabel"> - <x>120</x> - <y>713</y> - </hint> - </hints> - </connection> <connection> <sender>gridRotate</sender> <signal>valueChanged(int)</signal> @@ -6411,22 +5248,6 @@ </hint> </hints> </connection> - <connection> - <sender>coordTransX</sender> - <signal>valueChanged(int)</signal> - <receiver>coordTransX_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>92</x> - <y>712</y> - </hint> - <hint type="destinationlabel"> - <x>120</x> - <y>712</y> - </hint> - </hints> - </connection> <connection> <sender>gridScale_spin</sender> <signal>valueChanged(int)</signal> @@ -6459,70 +5280,6 @@ </hint> </hints> </connection> - <connection> - <sender>coordScale</sender> - <signal>valueChanged(int)</signal> - <receiver>coordScale_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>92</x> - <y>732</y> - </hint> - <hint type="destinationlabel"> - <x>120</x> - <y>733</y> - </hint> - </hints> - </connection> - <connection> - <sender>coordRotate</sender> - <signal>valueChanged(int)</signal> - <receiver>coordRotate_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>139</x> - <y>727</y> - </hint> - <hint type="destinationlabel"> - <x>120</x> - <y>729</y> - </hint> - </hints> - </connection> - <connection> - <sender>coordTransY_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coordTransY</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>120</x> - <y>713</y> - </hint> - <hint type="destinationlabel"> - <x>92</x> - <y>713</y> - </hint> - </hints> - </connection> - <connection> - <sender>coordTransX_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coordTransX</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>120</x> - <y>712</y> - </hint> - <hint type="destinationlabel"> - <x>92</x> - <y>712</y> - </hint> - </hints> - </connection> <connection> <sender>grid3DTransY</sender> <signal>valueChanged(int)</signal> @@ -6539,70 +5296,6 @@ </hint> </hints> </connection> - <connection> - <sender>coord3DTransZ_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DTransZ</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>351</x> - <y>771</y> - </hint> - <hint type="destinationlabel"> - <x>274</x> - <y>771</y> - </hint> - </hints> - </connection> - <connection> - <sender>coordRotate_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coordRotate</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>120</x> - <y>729</y> - </hint> - <hint type="destinationlabel"> - <x>139</x> - <y>727</y> - </hint> - </hints> - </connection> - <connection> - <sender>coord3DAxeLen_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DAxeLen</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>351</x> - <y>792</y> - </hint> - <hint type="destinationlabel"> - <x>274</x> - <y>792</y> - </hint> - </hints> - </connection> - <connection> - <sender>coordScale_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coordScale</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>120</x> - <y>733</y> - </hint> - <hint type="destinationlabel"> - <x>92</x> - <y>732</y> - </hint> - </hints> - </connection> <connection> <sender>grid3DTransX</sender> <signal>valueChanged(int)</signal> @@ -6699,54 +5392,6 @@ </hint> </hints> </connection> - <connection> - <sender>coord3DTransY</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DTransY_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>274</x> - <y>750</y> - </hint> - <hint type="destinationlabel"> - <x>351</x> - <y>750</y> - </hint> - </hints> - </connection> - <connection> - <sender>coord3DTransZ</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DTransZ_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>274</x> - <y>771</y> - </hint> - <hint type="destinationlabel"> - <x>351</x> - <y>771</y> - </hint> - </hints> - </connection> - <connection> - <sender>coord3DAxeLen</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DAxeLen_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>274</x> - <y>792</y> - </hint> - <hint type="destinationlabel"> - <x>351</x> - <y>792</y> - </hint> - </hints> - </connection> <connection> <sender>grid3DTransX_spin</sender> <signal>valueChanged(int)</signal> @@ -6763,53 +5408,5 @@ </hint> </hints> </connection> - <connection> - <sender>coord3DTransX_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DTransX</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>351</x> - <y>713</y> - </hint> - <hint type="destinationlabel"> - <x>274</x> - <y>713</y> - </hint> - </hints> - </connection> - <connection> - <sender>coord3DTransY_spin</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DTransY</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>351</x> - <y>750</y> - </hint> - <hint type="destinationlabel"> - <x>274</x> - <y>750</y> - </hint> - </hints> - </connection> - <connection> - <sender>coord3DTransX</sender> - <signal>valueChanged(int)</signal> - <receiver>coord3DTransX_spin</receiver> - <slot>setValue(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>274</x> - <y>713</y> - </hint> - <hint type="destinationlabel"> - <x>351</x> - <y>713</y> - </hint> - </hints> - </connection> </connections> </ui> diff --git a/ui/coordinateSystemBox.ui b/ui/coordinateSystemBox.ui new file mode 100644 index 0000000000000000000000000000000000000000..a4721cfcbfea0fc9a79747e8331a257c21879807 --- /dev/null +++ b/ui/coordinateSystemBox.ui @@ -0,0 +1,1433 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CoordinateSystemBox</class> + <widget class="QGroupBox" name="CoordinateSystemBox"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>476</width> + <height>271</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>271</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::TabFocus</enum> + </property> + <property name="title"> + <string>coordinate system</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_14"> + <property name="leftMargin"> + <number>5</number> + </property> + <property name="topMargin"> + <number>5</number> + </property> + <property name="rightMargin"> + <number>5</number> + </property> + <property name="bottomMargin"> + <number>5</number> + </property> + <item> + <layout class="QGridLayout" name="gridLayout_7" columnstretch="0,0,1"> + <item row="0" column="0"> + <widget class="QCheckBox" name="coordShow"> + <property name="minimumSize"> + <size> + <width>57</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Show the coordinate system.</string> + </property> + <property name="text"> + <string>show</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QCheckBox" name="coordFix"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Fix the coordinate system</string> + </property> + <property name="text"> + <string>fix</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer_9"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QTabWidget" name="coordTab"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="tabPosition"> + <enum>QTabWidget::North</enum> + </property> + <property name="tabShape"> + <enum>QTabWidget::Rounded</enum> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <property name="elideMode"> + <enum>Qt::ElideNone</enum> + </property> + <property name="usesScrollButtons"> + <bool>true</bool> + </property> + <property name="tabsClosable"> + <bool>false</bool> + </property> + <widget class="QWidget" name="coordTab3D"> + <attribute name="title"> + <string> 3D </string> + </attribute> + <attribute name="toolTip"> + <string>Select for 3D coordinatesystem</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QGridLayout" name="gridLayout_5"> + <property name="spacing"> + <number>4</number> + </property> + <item row="0" column="2"> + <widget class="PSpinBox" name="coord3DTransX_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="minimum"> + <number>-10000</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="PSpinBox" name="coord3DTransZ_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> + </property> + <property name="minimum"> + <number>-10000</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="PSpinBox" name="coord3DTransY_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in y-direction.</string> + </property> + <property name="minimum"> + <number>-10000</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QScrollBar" name="coord3DTransZ"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> + </property> + <property name="minimum"> + <number>-10000</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="sliderPosition"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QScrollBar" name="coord3DTransX"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="minimum"> + <number>-10000</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="sliderPosition"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QScrollBar" name="coord3DTransY"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in y-direction.</string> + </property> + <property name="minimum"> + <number>-10000</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="sliderPosition"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_57"> + <property name="toolTip"> + <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> + </property> + <property name="text"> + <string>z:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_56"> + <property name="toolTip"> + <string>Scale the coordinate system.</string> + </property> + <property name="text"> + <string>axis length:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_55"> + <property name="toolTip"> + <string>Translate the coordinate system in y-direction.</string> + </property> + <property name="text"> + <string>y:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_54"> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="text"> + <string>translate [cm] x:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="PSpinBox" name="coord3DAxeLen_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Scale the coordinate system.</string> + </property> + <property name="suffix"> + <string> cm</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="value"> + <number>200</number> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QScrollBar" name="coord3DAxeLen"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Scale the coordinate system.</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="value"> + <number>200</number> + </property> + <property name="sliderPosition"> + <number>200</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLabel" name="label_60"> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="text"> + <string>swap axis:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="coord3DSwapX"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="text"> + <string>X-axis</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="coord3DSwapY"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="text"> + <string>Y-axis</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="coord3DSwapZ"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="text"> + <string>Z-axis</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QLabel" name="label_61"> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="text"> + <string> show:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="extCalibPointsShow"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="text"> + <string>calibration points</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="extVanishPointsShow"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="text"> + <string>vanish points</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="coordTab2D"> + <attribute name="title"> + <string> 2D </string> + </attribute> + <attribute name="toolTip"> + <string>Select for 2D coordinatesystem</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QGridLayout" name="_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <property name="spacing"> + <number>4</number> + </property> + <item row="1" column="2"> + <widget class="PSpinBox" name="coordTransX_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_34"> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="text"> + <string>translate x:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QScrollBar" name="coordTransX"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in x-direction.</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="sliderPosition"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_32"> + <property name="toolTip"> + <string>Translate the coordinate system in y-direction.</string> + </property> + <property name="text"> + <string>y:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QScrollBar" name="coordTransY"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in y-direction.</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="sliderPosition"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_33"> + <property name="toolTip"> + <string>Scale the coordinate system.</string> + </property> + <property name="text"> + <string>scale:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QScrollBar" name="coordScale"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>Scale the coordinate system.</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100000</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="sliderPosition"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="PSpinBox" name="coordTransY_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="toolTip"> + <string>Translate the coordinate system in y-direction.</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>10000</number> + </property> + </widget> + </item> + <item row="4" column="2"> + <widget class="PSpinBox" name="coordScale_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="toolTip"> + <string>Scale the coordinate system.</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100000</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_35"> + <property name="toolTip"> + <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> + </property> + <property name="text"> + <string>rotate:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QScrollBar" name="coordRotate"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="toolTip"> + <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>3600</number> + </property> + <property name="sliderPosition"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="PSpinBox" name="coordRotate_spin"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="toolTip"> + <string>2D: Rotate the coordinate system clockwise. 3D: Translate the coordinate system in z-direction.</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>3600</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>camera altitude [cm]:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="PDoubleSpinBox" name="coordAltitude"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignRight</set> + </property> + <property name="suffix"> + <string/> + </property> + <property name="decimals"> + <number>1</number> + </property> + <property name="minimum"> + <double>0.100000000000000</double> + </property> + <property name="maximum"> + <double>9999.000000000000000</double> + </property> + <property name="value"> + <double>535.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="coordAltitudeMeasured"> + <property name="minimumSize"> + <size> + <width>90</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>(measured: 535.0)</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer_8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="_4"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label_37"> + <property name="minimumSize"> + <size> + <width>57</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>unit [cm]:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="PDoubleSpinBox" name="coordUnit"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignRight</set> + </property> + <property name="suffix"> + <string/> + </property> + <property name="decimals"> + <number>0</number> + </property> + <property name="minimum"> + <double>1.000000000000000</double> + </property> + <property name="maximum"> + <double>9999.000000000000000</double> + </property> + <property name="singleStep"> + <double>1.000000000000000</double> + </property> + <property name="value"> + <double>100.000000000000000</double> + </property> + </widget> + </item> + <item row="0" column="2"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="coordUseIntrinsic"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>17</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>17</height> + </size> + </property> + <property name="text"> + <string>use intrinsic center for calculating real position</string> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>PSpinBox</class> + <extends>QSpinBox</extends> + <header>pspinbox.h</header> + </customwidget> + <customwidget> + <class>PDoubleSpinBox</class> + <extends>QDoubleSpinBox</extends> + <header>pdoublespinbox.h</header> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>coordShow</tabstop> + <tabstop>coordFix</tabstop> + <tabstop>coordTab</tabstop> + <tabstop>coord3DTransX_spin</tabstop> + <tabstop>coord3DTransY_spin</tabstop> + <tabstop>coord3DTransZ_spin</tabstop> + <tabstop>coord3DAxeLen_spin</tabstop> + <tabstop>coord3DSwapX</tabstop> + <tabstop>coord3DSwapY</tabstop> + <tabstop>coord3DSwapZ</tabstop> + <tabstop>extCalibPointsShow</tabstop> + <tabstop>extVanishPointsShow</tabstop> + <tabstop>coordTransX_spin</tabstop> + <tabstop>coordTransY_spin</tabstop> + <tabstop>coordScale_spin</tabstop> + <tabstop>coordRotate_spin</tabstop> + <tabstop>coordAltitude</tabstop> + <tabstop>coordUnit</tabstop> + <tabstop>coordUseIntrinsic</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>coord3DTransX_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DTransX</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>394</x> + <y>91</y> + </hint> + <hint type="destinationlabel"> + <x>345</x> + <y>91</y> + </hint> + </hints> + </connection> + <connection> + <sender>coord3DTransX</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DTransX_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>259</x> + <y>93</y> + </hint> + <hint type="destinationlabel"> + <x>423</x> + <y>95</y> + </hint> + </hints> + </connection> + <connection> + <sender>coord3DTransY</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DTransY_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>320</x> + <y>117</y> + </hint> + <hint type="destinationlabel"> + <x>411</x> + <y>120</y> + </hint> + </hints> + </connection> + <connection> + <sender>coord3DTransY_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DTransY</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>400</x> + <y>116</y> + </hint> + <hint type="destinationlabel"> + <x>343</x> + <y>116</y> + </hint> + </hints> + </connection> + <connection> + <sender>coord3DTransZ</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DTransZ_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>342</x> + <y>134</y> + </hint> + <hint type="destinationlabel"> + <x>405</x> + <y>139</y> + </hint> + </hints> + </connection> + <connection> + <sender>coord3DTransZ_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DTransZ</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>396</x> + <y>139</y> + </hint> + <hint type="destinationlabel"> + <x>373</x> + <y>139</y> + </hint> + </hints> + </connection> + <connection> + <sender>coord3DAxeLen</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DAxeLen_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>343</x> + <y>156</y> + </hint> + <hint type="destinationlabel"> + <x>402</x> + <y>155</y> + </hint> + </hints> + </connection> + <connection> + <sender>coord3DAxeLen_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coord3DAxeLen</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>405</x> + <y>159</y> + </hint> + <hint type="destinationlabel"> + <x>353</x> + <y>160</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordTransX</sender> + <signal>valueChanged(int)</signal> + <receiver>coordTransX_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>370</x> + <y>88</y> + </hint> + <hint type="destinationlabel"> + <x>424</x> + <y>93</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordTransX_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coordTransX</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>413</x> + <y>97</y> + </hint> + <hint type="destinationlabel"> + <x>380</x> + <y>97</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordTransY</sender> + <signal>valueChanged(int)</signal> + <receiver>coordTransY_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>351</x> + <y>116</y> + </hint> + <hint type="destinationlabel"> + <x>410</x> + <y>117</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordTransY_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coordTransY</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>418</x> + <y>114</y> + </hint> + <hint type="destinationlabel"> + <x>362</x> + <y>113</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordRotate</sender> + <signal>valueChanged(int)</signal> + <receiver>coordRotate_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>338</x> + <y>140</y> + </hint> + <hint type="destinationlabel"> + <x>411</x> + <y>145</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordRotate_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coordRotate</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>403</x> + <y>134</y> + </hint> + <hint type="destinationlabel"> + <x>371</x> + <y>134</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordScale</sender> + <signal>valueChanged(int)</signal> + <receiver>coordScale_spin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>359</x> + <y>160</y> + </hint> + <hint type="destinationlabel"> + <x>399</x> + <y>160</y> + </hint> + </hints> + </connection> + <connection> + <sender>coordScale_spin</sender> + <signal>valueChanged(int)</signal> + <receiver>coordScale</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>421</x> + <y>166</y> + </hint> + <hint type="destinationlabel"> + <x>377</x> + <y>166</y> + </hint> + </hints> + </connection> + </connections> +</ui>