opencv_trail_effect.cpp: set window size and title
[experiments/opencv_trail_effect.git] / Trail.hpp
1 #ifndef TRAIL_HPP
2 #define TRAIL_HPP
3
4 #include <opencv2/opencv.hpp>
5 #include "Frame.hpp"
6
7 typedef std::list<Frame *> trail_t;
8
9 class Trail {
10 private:
11         virtual void iterate(cv::Mat& frame, void (*action)(cv::Mat&, Frame *, int, int)) = 0;
12
13         cv::Mat *background;
14         bool redraw_current_frame;
15         bool persistent;
16
17         void (*drawStrategy)(cv::Mat&, Frame *, int, int);
18
19         static void frameCopy(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
20         {
21                 (void) frame_index;
22                 (void) trail_size;
23                 frame->copyTo(destination);
24         }
25
26         static void frameAccumulate(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
27         {
28                 (void) frame_index;
29                 (void) trail_size;
30                 cv::accumulate(frame->getData(), destination, frame->getMask());
31         }
32
33         static void frameFadeCopy(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
34         {
35                 double weight = ((double) frame_index) / trail_size;
36                 cv::Mat weighted_frame;
37
38                 frame->getData().convertTo(weighted_frame, destination.type(), weight);
39                 weighted_frame.copyTo(destination, frame->getMask());
40         }
41
42         static void frameFadeAccumulate(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
43         {
44                 double weight = ((double) frame_index) / trail_size;
45                 cv::accumulateWeighted(frame->getData(), destination, weight, frame->getMask());
46         }
47
48         static void frameAverage(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
49         {
50                 (void) frame_index;
51                 double weight = 1. / trail_size;
52                 cv::accumulateWeighted(frame->getData(), destination, weight, frame->getMask());
53         }
54
55 protected:
56         trail_t trail;
57
58 public:
59         Trail(int trail_length, cv::Size frame_size)
60         {
61                 background = NULL;
62                 redraw_current_frame = false;
63                 drawStrategy = frameCopy;
64                 persistent = false;
65
66                 if (trail_length < 0) {
67                         persistent = true;
68                         background = new cv::Mat(frame_size, CV_8UC3);
69                 }
70
71                 if (trail_length < 1)
72                         trail_length = 1;
73
74                 for (int i = 0; i < trail_length; i++)
75                         trail.push_back(new Frame(frame_size));
76         }
77
78         virtual ~Trail()
79         {
80                 trail_t::iterator trail_it;
81                 for (trail_it = trail.begin(); trail_it != trail.end(); trail_it++) {
82                         delete(*trail_it);
83                 }
84                 trail.clear();
85                 delete background;
86         }
87
88         void setBackground(cv::Mat trail_background)
89         {
90                 delete background;
91                 background = new cv::Mat(trail_background);
92         }
93
94         int setDrawingMethod(std::string drawing_method)
95         {
96                 if (drawing_method == "copy") {
97                         drawStrategy = frameCopy;
98                 } else if (drawing_method == "accumulate") {
99                         drawStrategy = frameAccumulate;
100                 } else if (drawing_method == "fadecopy") {
101                         drawStrategy = frameFadeCopy;
102                 } else if (drawing_method == "fadeaccumulate") {
103                         drawStrategy = frameFadeAccumulate;
104                 } else if (drawing_method == "average") {
105                         drawStrategy = frameAverage;
106                 } else {
107                         return -1;
108                 }
109                 return 0;
110         }
111
112         void setRedrawCurrentFrame(bool do_redraw_current_frame)
113         {
114                 redraw_current_frame = do_redraw_current_frame;
115         }
116
117         void update(Frame *frame)
118         {
119                 Frame *front = trail.front();
120                 trail.pop_front();
121                 delete front;
122
123                 trail.push_back(frame);
124         }
125
126         void draw(cv::Mat& destination)
127         {
128                 cv::Mat float_destination;
129
130                 if (background)
131                         background->convertTo(float_destination, CV_32FC3);
132                 else
133                         destination.convertTo(float_destination, CV_32FC3);
134
135                 iterate(float_destination, drawStrategy);
136                 float_destination.convertTo(destination, destination.type());
137
138                 if (redraw_current_frame) {
139                         Frame *current_frame = trail.back();
140                         current_frame->getData().copyTo(destination, current_frame->getMask());
141                 }
142
143                 /* remember the current trail in the background image */
144                 if (persistent)
145                         float_destination.convertTo(*background, background->type());
146         }
147 };
148
149 class ForwardTrail: public Trail {
150         void iterate(cv::Mat& destination, void (*action)(cv::Mat&, Frame *, int, int))
151         {
152                 int index = 0;
153                 trail_t::iterator trail_it;
154                 for (trail_it = trail.begin(); trail_it != trail.end(); trail_it++) {
155                         action(destination, *trail_it, ++index, trail.size());
156                 }
157         }
158
159 public:
160         ForwardTrail(int trail_lenght, cv::Size frame_size) : Trail(trail_lenght, frame_size)
161         {
162         }
163 };
164
165 class ReverseTrail: public Trail {
166         void iterate(cv::Mat& destination, void (*action)(cv::Mat&, Frame *, int, int))
167         {
168                 int index = 0;
169                 trail_t::reverse_iterator trail_it;
170                 for (trail_it = trail.rbegin(); trail_it != trail.rend(); trail_it++) {
171                         action(destination, *trail_it, ++index, trail.size());
172                 }
173         }
174
175 public:
176         ReverseTrail(int trail_lenght, cv::Size frame_size) : Trail(trail_lenght, frame_size)
177         {
178         }
179 };
180
181 #endif // TRAIL_HPP