2 * openvc_trail_effect - experiments about video trail effects
4 * Copyright (C) 2015 Antonio Ospite <ao2@ao2.it>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <opencv2/opencv.hpp>
24 #include "Segmentation.hpp"
27 static void usage(const char *name)
29 std::cout << "usage: " << name << " [OPTIONS]" << std::endl;
30 std::cout << "OPTIONS:" << std::endl;
31 std::cout << "\t-i <file>\tthe input file (if missing, a webcam will be tried)" << std::endl;
32 std::cout << "\t-o <file>\tthe optional output file" << std::endl;
33 std::cout << "\t-l <number>\tthe trail length in frames" << std::endl;
34 std::cout << "\t\t\tthe default is 25" << std::endl;
35 std::cout << "\t\t\tNOTES:" << std::endl;
36 std::cout << "\t\t\t * a negative value means an 'infinite' trail" << std::endl;
37 std::cout << "\t-s <method>\tthe image segmentation method" << std::endl;
38 std::cout << "\t\t\tvalid values are:" << std::endl;
39 std::cout << "\t\t\t none, threshold, background" << std::endl;
40 std::cout << "\t\t\tthe default is 'background'" << std::endl;
41 std::cout << "\t\t\tNOTES:" << std::endl;
42 std::cout << "\t\t\t * 'none' is only useful with '-d average'" << std::endl;
43 std::cout << "\t-b <number>\tthe number of initial frames for background learning," << std::endl;
44 std::cout << "\t\t\tthe default is 50" << std::endl;
45 std::cout << "\t\t\tNOTES:" << std::endl;
46 std::cout << "\t\t\t * only useful with '-s background'" << std::endl;
47 std::cout << "\t-t <number>\tthe level for the threshold segmentation method," << std::endl;
48 std::cout << "\t\t\tthe default is 5" << std::endl;
49 std::cout << "\t\t\tNOTES:" << std::endl;
50 std::cout << "\t\t\t * only useful with '-s threshold'" << std::endl;
51 std::cout << "\t-d <method>\tthe trail drawing method" << std::endl;
52 std::cout << "\t\t\tvalid values are:" << std::endl;
53 std::cout << "\t\t\t copy, accumulate, fadecopy, fadeaccumulate, average" << std::endl;
54 std::cout << "\t\t\tthe default is 'copy'" << std::endl;
55 std::cout << "\t\t\tNOTES:" << std::endl;
56 std::cout << "\t\t\t * 'copy' is useless with '-s none'" << std::endl;
57 std::cout << "\t\t\t * the difference between 'fadecopy' and" << std::endl;
58 std::cout << "\t\t\t 'fadeaccumulate is cleared when using '-B'" << std::endl;
59 std::cout << "\t-r\t\treverse the trail drawing sequence" << std::endl;
60 std::cout << "\t-B\t\tshow the background behind the trail" << std::endl;
61 std::cout << "\t\t\tNOTES:" << std::endl;
62 std::cout << "\t\t\t * only used with '-s background'" << std::endl;
63 std::cout << "\t-F\t\tredraw the current frame on top of the trail" << std::endl;
64 std::cout << "\t\t\tNOTES:" << std::endl;
65 std::cout << "\t\t\t * noticeable with '-s average'" << std::endl;
66 std::cout << "\t\t\t * noticeable with reverse faded trails" << std::endl;
69 int main(int argc, char *argv[])
74 std::string *input_file = NULL;
75 std::string *output_file = NULL;
76 int trail_lenght = 25;
77 std::string *segmentation_method = new std::string("background");
78 int background_learn_frames = 50;
79 int threshold_level = 5;
80 std::string *drawing_method = new std::string("copy");
81 bool reverse_trail = false;
82 bool show_background = false;
83 bool redraw_current_frame = false;
85 while ((opt = getopt(argc, argv, "i:o:l:s:b:t:d:rBFh")) != -1) {
88 input_file = new std::string(optarg);
91 output_file = new std::string(optarg);
94 trail_lenght = atoi(optarg);
97 delete segmentation_method;
98 segmentation_method = new std::string(optarg);
101 background_learn_frames = atoi(optarg);
104 threshold_level = atoi(optarg);
107 delete drawing_method;
108 drawing_method = new std::string(optarg);
111 reverse_trail = true;
114 show_background = true;
117 redraw_current_frame = true;
128 cv::VideoCapture inputVideo;
129 cv::VideoWriter outputVideo;
134 inputVideo.open(*input_file);
139 if (!inputVideo.isOpened()) {
140 std::cerr << "Could not open the input video." << std::endl;
145 frame_size = cv::Size((int) inputVideo.get(cv::CAP_PROP_FRAME_WIDTH),
146 (int) inputVideo.get(cv::CAP_PROP_FRAME_HEIGHT));
149 int fps = inputVideo.get(cv::CAP_PROP_FPS);
153 outputVideo.open(*output_file, cv::VideoWriter::fourcc('M','J','P','G'), fps, frame_size, true);
154 if (!outputVideo.isOpened()) {
155 std::cerr << "Could not open the output video for write." << std::endl;
163 trail = new ReverseTrail(trail_lenght, frame_size);
165 trail = new ForwardTrail(trail_lenght, frame_size);
167 trail->setRedrawCurrentFrame(redraw_current_frame);
169 if (trail->setDrawingMethod(*drawing_method) < 0) {
170 std::cerr << "Invalid drawing method." << std::endl;
172 goto out_delete_trail;
175 Segmentation *segmentation;
176 if (*segmentation_method == "background") {
177 segmentation = new MOG2Segmentation(inputVideo, background_learn_frames);
178 if (show_background) {
179 cv::Mat background(frame_size, inputVideo.get(cv::CAP_PROP_FORMAT));
181 ((MOG2Segmentation *)segmentation)->getBackgroundImage(background);
182 trail->setBackground(background);
184 } else if (*segmentation_method == "threshold") {
185 segmentation = new ThresholdSegmentation(threshold_level);
186 } else if (*segmentation_method == "none") {
187 segmentation = new DummySegmentation();
189 std::cerr << "Invalid segmentation method." << std::endl;
191 goto out_delete_trail;
194 cv::namedWindow("Frame", cv::WINDOW_NORMAL);
197 inputVideo >> input_frame;
199 Frame *foreground = new Frame(input_frame,
200 segmentation->getForegroundMask(input_frame));
201 trail->update(foreground);
203 cv::Mat canvas = cv::Mat::zeros(input_frame.size(), input_frame.type());
206 cv::imshow("Frame", canvas);
207 if (cv::waitKeyEx(30) >= 0)
210 if (outputVideo.isOpened())
211 outputVideo << canvas;
214 cv::destroyWindow("Frame");
221 delete drawing_method;
222 delete segmentation_method;