summaryrefslogtreecommitdiffhomepage
path: root/tracker-easy/tracker-easy.h
blob: bbafcefa9031008c954572300df924c3c6099e7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* Copyright (c) 2019 Stephane Lenclud
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 */

#pragma once

#include "api/plugin-api.hpp"
#include "cv/numeric.hpp"
#include "video/video-widget.hpp"
#include "video/camera.hpp"
#include "compat/timer.hpp"


#include "preview.h"
#include "settings.h"
#include "point-extractor.h"
#include "kalman-filter-pose.h"

#include <atomic>
#include <memory>
#include <vector>

#include <opencv2/core.hpp>
#include <opencv2/video/tracking.hpp>

#include <QThread>
#include <QMutex>
#include <QLayout>

namespace EasyTracker
{

    static const QString KModuleName = "tracker-easy";

    class Dialog;

    using namespace numeric_types;

    struct Tracker : public QObject, ITracker
    {
        Q_OBJECT
    public:        
        friend class Dialog;

        explicit Tracker();
        ~Tracker() override;

        // From ITracker
        module_status start_tracker(QFrame* parent_window) override;
        void data(double* data) override;
        bool center() override;

    private slots:
        void Tick();


    private:
        void CreateModelFromSettings();
        void CreateCameraIntrinsicsMatrices();
        void ProcessFrame();
        
        //

        bool maybe_reopen_camera();
        void set_fov(int value);
        void SetFps(int aFps);
        void DoSetFps(int aFps);
        void UpdateDeadzones(int aHalfEdgeSize);

        QMutex camera_mtx;
        QThread iThread;
        QTimer iTicker;

        Settings iSettings;

        std::unique_ptr<QLayout> layout;
        std::vector<cv::Point> iPoints;

        int preview_width = 320, preview_height = 240;

        PointExtractor iPointExtractor;

        std::unique_ptr<video::impl::camera> camera;
        video::impl::camera::info iCameraInfo;
        std::unique_ptr<video_widget> widget;

        video::frame iFrame;
        cv::Mat iMatFrame;
        Preview iPreview;

        std::atomic<bool> ever_success = false;
        mutable QMutex center_lock, data_lock;

        // Deadzone
        int iDeadzoneEdge=0;
        int iDeadzoneHalfEdge=0;

        // Statistics
        Timer iTimer;
        Timer iFpsTimer;        
        int iFrameCount = 0;
        int iSkippedFrameCount = 0;
        int iFps = 0;
        int iSkippedFps = 0;

        //
        KalmanFilterPose iKf;

        // Vertices defining the model we are tracking
        std::vector<cv::Point3f> iModel;
        // Bitmap points corresponding to model vertices
        std::vector<cv::Point2f> iTrackedPoints;

        std::vector<cv::Rect> iTrackedRects;

        // Intrinsics camera matrix
        cv::Mat iCameraMatrix;
        // Intrinsics distortion coefficients as a matrix
        cv::Mat iDistCoeffsMatrix;
        // Translation solutions
        std::vector<cv::Mat> iTranslations;
        // Rotation solutions
        std::vector<cv::Mat> iRotations;
        // Angle solutions, pitch, yaw, roll, in this order
        std::vector<cv::Vec3d> iAngles;
        // The index of our best solution in the above arrays
        int iBestSolutionIndex = -1;
        // Best translation
        cv::Vec3d iBestTranslation;
        // Best angles
        cv::Vec3d iBestAngles;
    };

}