1+ #include < iostream>
2+ #include < ins_stitcher.h>
3+
4+ #include < iostream>
5+ #include < algorithm>
6+ #include < condition_variable>
7+ #include < mutex>
8+ #include < chrono>
9+ #include < vector>
10+ #include < sstream>
11+
12+ #ifdef WIN32
13+ #include < direct.h>
14+ #include < Windows.h>
15+ #endif // WIN32
16+
17+ using namespace std ::chrono;
18+ using namespace ins ;
19+
20+ const std::string helpstr =
21+ " {-help | default | print this message }\n "
22+ " {-inputs | None | input files }\n "
23+ " {-output | None | out path }\n "
24+ " {-stitch_type | template | template }\n "
25+ " { | optflow }\n "
26+ " { | dynamicstitch }\n "
27+ " { | aistitch }\n "
28+ " {-ai_stitching_model | | ai stitching model path }\n "
29+ " {-bitrate | same as input video | the bitrate of ouput file }\n "
30+ " {-enable_flowstate | OFF | enable flowstate }\n "
31+ " {-enable_directionlock | OFF | enable directionlock }\n "
32+ " {-output_size | 1920x960 | the resolution of output }\n "
33+ " {-enable_h265_encoder | h264 | encode format }\n "
34+ " {-disable_cuda | true | disable cuda }\n "
35+ " {-enable_soft_encode | false | use soft encoder }\n "
36+ " {-enable_soft_decode | false | use soft decoder }\n "
37+ " {-enable_stitchfusion | OFF | stitch_fusion }\n "
38+ " {-enable_denoise | OFF | enable denoise }\n "
39+ " {-image_denoise_model | OFF | image denoise model path }\n "
40+ " {-enable_colorplus | OFF | enable colorplus }\n "
41+ " {-colorplus_model | | colorplus model path }\n "
42+ " {-enable_deflicker | OFF | enable deflicker }\n "
43+ " {-deflicker_model | | deflicker model path }\n "
44+ " {-image_sequence_dir | None | the output dir of image sequence }\n "
45+ " {-image_type | jpg | jpg }\n "
46+ " { | png }\n "
47+ " {-camera_accessory_type | default 0 | refer to 'common.h' }\n "
48+ " {-export_frame_index | | Derived frame number sequence, example: 20-50-30 }\n " ;
49+
50+ static std::string stringToUtf8 (const std::string& original_str) {
51+ #ifdef WIN32
52+ const char * std_origin_str = original_str.c_str ();
53+ const int std_origin_str_len = static_cast <int >(original_str.length ());
54+
55+ int nwLen = MultiByteToWideChar (CP_ACP, 0 , std_origin_str, -1 , NULL , 0 );
56+
57+ wchar_t * pwBuf = new wchar_t [nwLen + 1 ];
58+ ZeroMemory (pwBuf, nwLen * 2 + 2 );
59+
60+ MultiByteToWideChar (CP_ACP, 0 , std_origin_str, std_origin_str_len, pwBuf, nwLen);
61+
62+ int nLen = WideCharToMultiByte (CP_UTF8, 0 , pwBuf, -1 , NULL , NULL , NULL , NULL );
63+
64+ char * pBuf = new char [nLen + 1 ];
65+ ZeroMemory (pBuf, nLen + 1 );
66+
67+ WideCharToMultiByte (CP_UTF8, 0 , pwBuf, nwLen, pBuf, nLen, NULL , NULL );
68+
69+ std::string ret_str (pBuf);
70+
71+ delete[] pwBuf;
72+ delete[] pBuf;
73+
74+ pwBuf = NULL ;
75+ pBuf = NULL ;
76+
77+ return ret_str;
78+ #else
79+ return original_str;
80+ #endif
81+ }
82+
83+ std::vector<std::string> split (const std::string& s, char delimiter) {
84+ std::vector<std::string> tokens;
85+ std::string token;
86+ std::istringstream tokenStream (s);
87+
88+ while (std::getline (tokenStream, token, delimiter)) {
89+ tokens.push_back (token);
90+ }
91+
92+ return tokens;
93+ }
94+
95+ int main (int argc, char * argv[]) {
96+ ins::SetLogLevel (ins::InsLogLevel::ERR);
97+ ins::InitEnv ();
98+
99+ std::vector<std::string> input_paths;
100+ std::string output_path;
101+ std::string image_sequence_dir;
102+ std::string ai_stitching_model;
103+ std::string color_plus_model_path;
104+ std::string denoise_model_path;
105+ std::string exported_frame_number_sequence;
106+ std::string deflicker_model_path;
107+
108+ STITCH_TYPE stitch_type = STITCH_TYPE::OPTFLOW;
109+ IMAGE_TYPE image_type = IMAGE_TYPE::JPEG;
110+ CameraAccessoryType accessory_type = CameraAccessoryType::kNormal ;
111+
112+ int output_width = 1920 ;
113+ int output_height = 960 ;
114+ int output_bitrate = 0 ;
115+
116+ bool enable_flowstate = false ;
117+ bool enable_cuda = true ;
118+ bool enable_soft_encode = false ;
119+ bool enable_soft_decode = false ;
120+ bool enalbe_stitchfusion = true ;
121+ bool enable_colorplus = false ;
122+ bool enable_directionlock = false ;
123+ bool enable_sequence_denoise = false ;
124+ bool enable_H265_encoder = false ;
125+ bool enable_deflicker = false ;
126+
127+ for (int i = 1 ; i < argc; i++) {
128+ if (std::string (" -inputs" ) == std::string (argv[i])) {
129+ std::string input_path = argv[++i];
130+ while (input_path[0 ] != ' -' ) {
131+ input_paths.push_back (stringToUtf8 (input_path));
132+ input_path = argv[++i];
133+ }
134+ }
135+ if (std::string (" -output" ) == std::string (argv[i])) {
136+ output_path = stringToUtf8 (argv[++i]);
137+ }
138+ if (std::string (" -colorplus_model" ) == std::string (argv[i])) {
139+ color_plus_model_path = stringToUtf8 (argv[++i]);
140+ }
141+ else if (std::string (" -stitch_type" ) == std::string (argv[i])) {
142+ std::string stitchType = argv[++i];
143+ if (stitchType == std::string (" optflow" )) {
144+ stitch_type = STITCH_TYPE::OPTFLOW;
145+ }
146+ else if (stitchType == std::string (" dynamicstitch" )) {
147+ stitch_type = STITCH_TYPE::DYNAMICSTITCH;
148+ }
149+ else if (stitchType == std::string (" aistitch" )) {
150+ stitch_type = STITCH_TYPE::AIFLOW;
151+ }
152+ }
153+ else if (std::string (" -enable_flowstate" ) == std::string (argv[i])) {
154+ enable_flowstate = true ;
155+ }
156+ else if (std::string (" -disable_cuda" ) == std::string (argv[i])) {
157+ enable_cuda = false ;
158+ }
159+ else if (std::string (" -enable_stitchfusion" ) == std::string (argv[i])) {
160+ enalbe_stitchfusion = true ;
161+ }
162+ else if (std::string (" -enable_denoise" ) == std::string (argv[i])) {
163+ enable_sequence_denoise = true ;
164+ }
165+ else if (std::string (" -enable_colorplus" ) == std::string (argv[i])) {
166+ enable_colorplus = true ;
167+ }
168+ else if (std::string (" -enable_directionlock" ) == std::string (argv[i])) {
169+ enable_directionlock = true ;
170+ }
171+ else if (std::string (" -enable_h265_encoder" ) == std::string (argv[i])) {
172+ enable_H265_encoder = true ;
173+ }
174+ else if (std::string (" -bitrate" ) == std::string (argv[i])) {
175+ output_bitrate = atoi (argv[++i]);
176+ }
177+ else if (std::string (" -output_size" ) == std::string (argv[i])) {
178+ auto res = split (std::string (argv[++i]), ' x' );
179+ if (res.size () == 2 ) {
180+ output_width = std::atoi (res[0 ].c_str ());
181+ output_height = std::atoi (res[1 ].c_str ());
182+ }
183+ }
184+ else if (std::string (" -image_sequence_dir" ) == std::string (argv[i])) {
185+ image_sequence_dir = std::string (argv[++i]);
186+ }
187+ else if (std::string (" -image_type" ) == std::string (argv[i])) {
188+ std::string type = argv[++i];
189+ if (type == std::string (" jpg" )) {
190+ image_type = IMAGE_TYPE::JPEG;
191+ }
192+ else if (type == std::string (" png" )) {
193+ image_type = IMAGE_TYPE::PNG;
194+ }
195+ }
196+ else if (std::string (" -camera_accessory_type" ) == std::string (argv[i])) {
197+ accessory_type = static_cast <CameraAccessoryType>(std::atoi (argv[++i]));
198+ }
199+ else if (std::string (" -ai_stitching_model" ) == std::string (argv[i])) {
200+ ai_stitching_model = stringToUtf8 (argv[++i]);
201+ }
202+ else if (std::string (" -image_denoise_model" ) == std::string (argv[i])) {
203+ denoise_model_path = stringToUtf8 (argv[++i]);
204+ }
205+ else if (std::string (" -export_frame_index" ) == std::string (argv[i])) {
206+ exported_frame_number_sequence = argv[++i];
207+ }
208+ else if (std::string (" -deflicker_model" ) == std::string (argv[i])) {
209+ deflicker_model_path = stringToUtf8 (argv[++i]);
210+ }
211+ else if (std::string (" -enable_deflicker" ) == std::string (argv[i])) {
212+ enable_deflicker = true ;
213+ }
214+ else if (std::string (" -enable_soft_encode" ) == std::string (argv[i])) {
215+ enable_soft_encode = true ;
216+ }
217+ else if (std::string (" -enable_soft_decode" ) == std::string (argv[i])) {
218+ enable_soft_decode = true ;
219+ }
220+ else if (std::string (" -help" ) == std::string (argv[i])) {
221+ std::cout << helpstr << std::endl;
222+ }
223+ }
224+
225+ if (input_paths.empty ()) {
226+ std::cout << " can not find input_file" << std::endl;
227+ std::cout << helpstr << std::endl;
228+ return -1 ;
229+ }
230+
231+ if (output_path.empty () && image_sequence_dir.empty ()) {
232+ std::cout << " can not find output_file" << std::endl;
233+ std::cout << helpstr << std::endl;
234+ return -1 ;
235+ }
236+
237+ std::vector<uint64_t > export_frame_nums;
238+ if (!image_sequence_dir.empty ()) {
239+ auto frame_index_vec = split (exported_frame_number_sequence, ' -' );
240+ for (auto & frame_index : frame_index_vec) {
241+ int index = atoi (frame_index.c_str ());
242+ export_frame_nums.push_back (index);
243+ }
244+ }
245+
246+ if (color_plus_model_path.empty ()) {
247+ enable_colorplus = false ;
248+ }
249+
250+ int count = 1 ;
251+ while (count--) {
252+ std::mutex mutex;
253+ std::condition_variable cond;
254+ bool is_finished = false ;
255+ bool has_error = false ;
256+ int stitch_progress = 0 ;
257+ std::string suffix = input_paths[0 ].substr (input_paths[0 ].find_last_of (" ." ) + 1 );
258+ std::transform (suffix.begin (), suffix.end (), suffix.begin (), ::tolower);
259+ if (suffix == " insp" || suffix == " jpg" ) {
260+ auto image_stitcher = std::make_shared<ImageStitcher>();
261+ image_stitcher->SetInputPath (input_paths);
262+ image_stitcher->SetStitchType (stitch_type);
263+ image_stitcher->SetOutputPath (output_path);
264+ image_stitcher->SetOutputSize (output_width, output_height);
265+ image_stitcher->EnableFlowState (enable_flowstate);
266+ image_stitcher->EnableDenoise (enable_sequence_denoise, denoise_model_path);
267+ image_stitcher->EnableCuda (enable_cuda);
268+ image_stitcher->EnableStitchFusion (enalbe_stitchfusion);
269+ image_stitcher->SetCameraAccessoryType (accessory_type);
270+ image_stitcher->SetAiStitchModelFile (ai_stitching_model);
271+ image_stitcher->EnableColorPlus (enable_colorplus, color_plus_model_path);
272+ image_stitcher->Stitch ();
273+ }
274+ else if (suffix == " mp4" || suffix == " insv" || suffix == " lrv" ) {
275+ auto start_time = steady_clock::now ();
276+ auto video_stitcher = std::make_shared<VideoStitcher>();
277+ video_stitcher->SetInputPath (input_paths);
278+ if (image_sequence_dir.empty ()) {
279+ video_stitcher->SetOutputPath (output_path);
280+ }
281+ else {
282+ if (!export_frame_nums.empty ()) {
283+ video_stitcher->SetExportFrameSequence (export_frame_nums);
284+ }
285+
286+ video_stitcher->SetImageSequenceInfo (image_sequence_dir, image_type);
287+ }
288+ video_stitcher->SetStitchType (stitch_type);
289+ video_stitcher->EnableCuda (enable_cuda);
290+ video_stitcher->EnableStitchFusion (enalbe_stitchfusion);
291+ video_stitcher->EnableColorPlus (enable_colorplus, color_plus_model_path);
292+ video_stitcher->SetOutputSize (output_width, output_height);
293+ video_stitcher->SetOutputBitRate (output_bitrate);
294+ video_stitcher->EnableFlowState (enable_flowstate);
295+ video_stitcher->SetAiStitchModelFile (ai_stitching_model);
296+ video_stitcher->EnableDenoise (enable_sequence_denoise);
297+ video_stitcher->EnableDirectionLock (enable_directionlock);
298+ video_stitcher->SetCameraAccessoryType (accessory_type);
299+ video_stitcher->SetSoftwareCodecUsage (enable_soft_encode, enable_soft_decode);
300+ if (enable_H265_encoder) {
301+ video_stitcher->EnableH265Encoder ();
302+ }
303+ video_stitcher->EnableDeflicker (enable_deflicker, deflicker_model_path);
304+ video_stitcher->SetStitchProgressCallback ([&](int process, int error) {
305+ if (stitch_progress != process) {
306+ const std::string process_desc = " process = " + std::to_string (process) + std::string (" %" );
307+ std::cout << " \r " << process_desc << std::flush;
308+ stitch_progress = process;
309+ }
310+
311+ if (stitch_progress == 100 ) {
312+ std::cout << std::endl;
313+ std::unique_lock<std::mutex> lck (mutex);
314+ cond.notify_one ();
315+ is_finished = true ;
316+ }
317+ });
318+
319+ video_stitcher->SetStitchStateCallback ([&](int error, const char * err_info) {
320+ std::cout << " error: " << err_info << std::endl;
321+ has_error = true ;
322+ cond.notify_one ();
323+ });
324+
325+ std::cout << " start stitch " << std::endl;
326+ video_stitcher->StartStitch ();
327+
328+ std::unique_lock<std::mutex> lck (mutex);
329+ cond.wait (lck, [&] {
330+ std::cout << " progress: " << video_stitcher->GetStitchProgress () << " ; finished: " << is_finished << std::endl;
331+ return is_finished || has_error;
332+ });
333+
334+ std::cout << " end stitch " << std::endl;
335+
336+ auto end_time = steady_clock::now ();
337+ std::cout << " cost = " << duration_cast<duration<double >>(end_time - start_time).count () << std::endl;
338+ }
339+ }
340+ return 0 ;
341+ }
0 commit comments