4 #include <opencv2/opencv.hpp>
7 typedef std::list<Frame *> trail_t;
11 virtual void iterate(cv::Mat& frame, void (*action)(cv::Mat&, Frame *, int, int)) = 0;
14 bool redraw_current_frame;
17 void (*drawStrategy)(cv::Mat&, Frame *, int, int);
19 static void frameCopy(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
23 frame->copyTo(destination);
26 static void frameAccumulate(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
30 cv::accumulate(frame->getData(), destination, frame->getMask());
33 static void frameFadeCopy(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
35 double weight = ((double) frame_index) / trail_size;
36 cv::Mat weighted_frame;
38 frame->getData().convertTo(weighted_frame, destination.type(), weight);
39 weighted_frame.copyTo(destination, frame->getMask());
42 static void frameFadeAccumulate(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
44 double weight = ((double) frame_index) / trail_size;
45 cv::accumulateWeighted(frame->getData(), destination, weight, frame->getMask());
48 static void frameAverage(cv::Mat& destination, Frame *frame, int frame_index, int trail_size)
51 double weight = 1. / trail_size;
52 cv::accumulateWeighted(frame->getData(), destination, weight, frame->getMask());
59 Trail(int trail_length, cv::Size frame_size)
62 redraw_current_frame = false;
63 drawStrategy = frameCopy;
66 if (trail_length < 0) {
68 background = new cv::Mat(frame_size, CV_8UC3);
74 for (int i = 0; i < trail_length; i++)
75 trail.push_back(new Frame(frame_size));
80 trail_t::iterator trail_it;
81 for (trail_it = trail.begin(); trail_it != trail.end(); trail_it++) {
88 void setBackground(cv::Mat trail_background)
91 background = new cv::Mat(trail_background);
94 int setDrawingMethod(std::string drawing_method)
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;
112 void setRedrawCurrentFrame(bool do_redraw_current_frame)
114 redraw_current_frame = do_redraw_current_frame;
117 void update(Frame *frame)
119 Frame *front = trail.front();
123 trail.push_back(frame);
126 void draw(cv::Mat& destination)
128 cv::Mat float_destination;
131 background->convertTo(float_destination, CV_32FC3);
133 destination.convertTo(float_destination, CV_32FC3);
135 iterate(float_destination, drawStrategy);
136 float_destination.convertTo(destination, destination.type());
138 if (redraw_current_frame) {
139 Frame *current_frame = trail.back();
140 current_frame->getData().copyTo(destination, current_frame->getMask());
143 /* remember the current trail in the background image */
145 float_destination.convertTo(*background, background->type());
149 class ForwardTrail: public Trail {
150 void iterate(cv::Mat& destination, void (*action)(cv::Mat&, Frame *, int, int))
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());
160 ForwardTrail(int trail_lenght, cv::Size frame_size) : Trail(trail_lenght, frame_size)
165 class ReverseTrail: public Trail {
166 void iterate(cv::Mat& destination, void (*action)(cv::Mat&, Frame *, int, int))
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());
176 ReverseTrail(int trail_lenght, cv::Size frame_size) : Trail(trail_lenght, frame_size)