5 #include "opencv2/core/core.hpp"
6 #include "opencv2/video/video.hpp"
7 #include "opencv2/imgproc/imgproc.hpp"
8 #include "opencv2/highgui/highgui.hpp"
9 #include "opencv2/videostab/videostab.hpp"
13 using namespace cv::videostab;
15 Ptr<Stabilizer> stabilizer;
28 while (!(stabilizedFrame = stabilizer->nextFrame()).empty())
30 if (!outputPath.empty())
32 if (!writer.isOpened())
33 writer.open(outputPath, CV_FOURCC('X','V','I','D'), outputFps, stabilizedFrame.size());
34 writer << stabilizedFrame;
38 imshow("stabilizedFrame", stabilizedFrame);
39 char key = static_cast<char>(waitKey(3));
45 cout << "\nfinished\n";
51 cout << "OpenCV video stabilizer.\n"
52 "Usage: videostab <file_path> [arguments]\n\n"
54 " -m, --model=(transl|transl_and_scale|affine)\n"
55 " Set motion model. The default is affine.\n"
56 " --outlier-ratio=<float_number>\n"
57 " Outliers ratio in motion estimation. The default is 0.5.\n"
58 " --min-inlier-ratio=<float_number>\n"
59 " Minimum inlier ratio to decide if estimated motion is OK. The default is 0.1,\n"
60 " but you may want to increase it.\n"
61 " -r, --radius=<int_number>\n"
62 " Set smoothing radius. The default is 15.\n"
63 " --stdev=<float_number>\n"
64 " Set smoothing weights standard deviation. The default is sqrt(radius).\n"
65 " --deblur=(yes|no)\n"
67 " --deblur-sens=<float_number>\n"
68 " Set deblurring sensitivity (from 0 to +inf). The default is 0.1.\n"
69 " -t, --trim-ratio=<float_number>\n"
70 " Set trimming ratio (from 0 to 0.5). The default is 0.\n"
71 " --est-trim=(yes|no)\n"
72 " Estimate trim ratio automatically. The default is yes (that leads to two passes,\n"
73 " you can turn it off if you want to use one pass only).\n"
74 " --incl-constr=(yes|no)\n"
75 " Ensure the inclusion constraint is always satisfied. The default is no.\n"
76 " --border-mode=(replicate|reflect|const)\n"
77 " Set border extrapolation mode. The default is replicate.\n"
78 " --mosaic=(yes|no)\n"
79 " Do consistent mosaicing. The default is no.\n"
80 " --mosaic-stdev=<float_number>\n"
81 " Consistent mosaicing stdev threshold. The default is 10.\n"
82 " --motion-inpaint=(yes|no)\n"
83 " Do motion inpainting (requires GPU support). The default is no.\n"
84 " --color-inpaint=(no|average|ns|telea)\n"
85 " Do color inpainting. The defailt is no.\n"
86 " --color-inpaint-radius=<float_number>\n"
87 " Set color inpainting radius (for ns and telea options only).\n"
88 " -o, --output=<file_path>\n"
89 " Set output file path explicitely. The default is stabilized.avi.\n"
90 " --fps=<int_number>\n"
91 " Set output video FPS explicitely. By default the source FPS is used.\n"
93 " Don't show output video frames.\n"
100 int main(int argc, const char **argv)
107 "{ | min-inlier-ratio | | }"
108 "{ | outlier-ratio | | }"
112 "{ | deblur-sens | | }"
114 "{ t | trim-ratio | | }"
115 "{ | incl-constr | | }"
116 "{ | border-mode | | }"
118 "{ | mosaic-stdev | | }"
119 "{ | motion-inpaint | | }"
120 "{ | color-inpaint | no | }"
121 "{ | color-inpaint-radius | | }"
122 "{ o | output | stabilized.avi | }"
124 "{ q | quiet | false | }"
125 "{ h | help | false | }";
126 CommandLineParser cmd(argc, argv, keys);
128 // parse command arguments
130 if (cmd.get<bool>("help"))
136 stabilizer = new Stabilizer();
138 string inputPath = cmd.get<string>("1");
139 if (inputPath.empty())
140 throw runtime_error("specify video file path");
142 VideoFileSource *frameSource = new VideoFileSource(inputPath);
143 outputFps = frameSource->fps();
144 stabilizer->setFrameSource(frameSource);
145 cout << "frame count: " << frameSource->frameCount() << endl;
147 PyrLkRobustMotionEstimator *motionEstimator = new PyrLkRobustMotionEstimator();
148 if (cmd.get<string>("model") == "transl")
149 motionEstimator->setMotionModel(TRANSLATION);
150 else if (cmd.get<string>("model") == "transl_and_scale")
151 motionEstimator->setMotionModel(TRANSLATION_AND_SCALE);
152 else if (cmd.get<string>("model") == "affine")
153 motionEstimator->setMotionModel(AFFINE);
154 else if (!cmd.get<string>("model").empty())
155 throw runtime_error("unknow motion mode: " + cmd.get<string>("model"));
157 if (!cmd.get<string>("outlier-ratio").empty())
159 RansacParams ransacParams = motionEstimator->ransacParams();
160 ransacParams.eps = cmd.get<float>("outlier-ratio");
161 motionEstimator->setRansacParams(ransacParams);
164 if (!cmd.get<string>("min-inlier-ratio").empty())
165 motionEstimator->setMinInlierRatio(cmd.get<float>("min-inlier-ratio"));
167 stabilizer->setMotionEstimator(motionEstimator);
169 int smoothRadius = -1;
170 float smoothStdev = -1;
171 if (!cmd.get<string>("radius").empty())
172 smoothRadius = cmd.get<int>("radius");
173 if (!cmd.get<string>("stdev").empty())
174 smoothStdev = cmd.get<float>("stdev");
175 if (smoothRadius > 0 && smoothStdev > 0)
176 stabilizer->setMotionFilter(new GaussianMotionFilter(smoothRadius, smoothStdev));
177 else if (smoothRadius > 0 && smoothStdev < 0)
178 stabilizer->setMotionFilter(new GaussianMotionFilter(smoothRadius, sqrt(static_cast<float>(smoothRadius))));
180 if (cmd.get<string>("deblur") == "yes")
182 WeightingDeblurer *deblurer = new WeightingDeblurer();
183 if (!cmd.get<string>("deblur-sens").empty())
184 deblurer->setSensitivity(cmd.get<float>("deblur-sens"));
185 stabilizer->setDeblurer(deblurer);
188 if (!cmd.get<string>("est-trim").empty())
189 stabilizer->setEstimateTrimRatio(cmd.get<string>("est-trim") == "yes");
191 if (!cmd.get<string>("trim-ratio").empty())
192 stabilizer->setTrimRatio(cmd.get<float>("trim-ratio"));
194 if (!cmd.get<string>("incl-constr").empty())
195 stabilizer->setInclusionConstraint(cmd.get<string>("incl-constr") == "yes");
197 if (cmd.get<string>("border-mode") == "reflect")
198 stabilizer->setBorderMode(BORDER_REFLECT);
199 else if (cmd.get<string>("border-mode") == "replicate")
200 stabilizer->setBorderMode(BORDER_REPLICATE);
201 else if (cmd.get<string>("border-mode") == "const")
202 stabilizer->setBorderMode(BORDER_CONSTANT);
203 else if (!cmd.get<string>("border-mode").empty())
204 throw runtime_error("unknown border extrapolation mode: " + cmd.get<string>("border-mode"));
206 InpaintingPipeline *inpainters = new InpaintingPipeline();
207 if (cmd.get<string>("mosaic") == "yes")
209 ConsistentMosaicInpainter *inpainter = new ConsistentMosaicInpainter();
210 if (!cmd.get<string>("mosaic-stdev").empty())
211 inpainter->setStdevThresh(cmd.get<float>("mosaic-stdev"));
212 inpainters->pushBack(inpainter);
214 if (cmd.get<string>("motion-inpaint") == "yes")
215 inpainters->pushBack(new MotionInpainter());
216 if (!cmd.get<string>("color-inpaint").empty())
218 if (cmd.get<string>("color-inpaint") == "average")
219 inpainters->pushBack(new ColorAverageInpainter());
220 else if (!cmd.get<string>("color-inpaint-radius").empty())
222 float radius = cmd.get<float>("color-inpaint-radius");
223 if (cmd.get<string>("color-inpaint") == "ns")
224 inpainters->pushBack(new ColorInpainter(INPAINT_NS, radius));
225 else if (cmd.get<string>("color-inpaint") == "telea")
226 inpainters->pushBack(new ColorInpainter(INPAINT_TELEA, radius));
227 else if (cmd.get<string>("color-inpaint") != "no")
228 throw runtime_error("unknown color inpainting method: " + cmd.get<string>("color-inpaint"));
232 if (cmd.get<string>("color-inpaint") == "ns")
233 inpainters->pushBack(new ColorInpainter(INPAINT_NS));
234 else if (cmd.get<string>("color-inpaint") == "telea")
235 inpainters->pushBack(new ColorInpainter(INPAINT_TELEA));
236 else if (cmd.get<string>("color-inpaint") != "no")
237 throw runtime_error("unknown color inpainting method: " + cmd.get<string>("color-inpaint"));
240 if (!inpainters->empty())
241 stabilizer->setInpainter(inpainters);
243 stabilizer->setLog(new LogToStdout());
245 outputPath = cmd.get<string>("output");
247 if (!cmd.get<string>("fps").empty())
248 outputFps = cmd.get<double>("fps");
250 quietMode = cmd.get<bool>("quiet");
252 // run video processing
255 catch (const exception &e)
257 cout << e.what() << endl;
258 stabilizer.release();
261 stabilizer.release();