-
Notifications
You must be signed in to change notification settings - Fork 5
/
stitching_backup.cpp
907 lines (873 loc) · 29.3 KB
/
stitching_backup.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
// Stitching.cpp : 定义控制台应用程序的入口点。
#include <QtWidgets/QMainWindow>
#include <QFileDialog>
#include <qprogressdialog.h>
#include "ui_stitchingvsqt.h"
#include <iostream>
#include <fstream>
#include <string>
#include <tchar.h>
#include <Windows.h>
#include "opencv2/opencv_modules.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/stitching/detail/autocalib.hpp"
#include "opencv2/stitching/detail/blenders.hpp"
#include "opencv2/stitching/detail/camera.hpp"
#include "opencv2/stitching/detail/exposure_compensate.hpp"
#include "opencv2/stitching/detail/matchers.hpp"
#include "opencv2/stitching/detail/motion_estimators.hpp"
#include "opencv2/stitching/detail/seam_finders.hpp"
#include "opencv2/stitching/detail/util.hpp"
#include "opencv2/stitching/detail/warpers.hpp"
#include "opencv2/stitching/warpers.hpp"
#include "stitching.h"
#include "qmessagebox.h"
#include <QRunnable>
#include "stitchingvsqt.h"
using namespace std;
using namespace cv;
using namespace cv::detail;
typedef void*(*STITCH)(std::vector<std::vector<std::string>> &img_names,
const void *config,
std::string &msg);
typedef void (*PANOIMAGE)(void *img, const std::string &name);
//static void printUsage()
//{
// cout <<
// "Rotation model images stitcher.\n\n"
// "stitching_detailed img1 img2 [...imgN] [flags]\n\n"
// "Flags:\n"
// " --preview\n"
// " Run stitching in the preview mode. Works faster than usual mode,\n"
// " but output image will have lower resolution.\n"
// " --try_gpu (yes|no)\n"
// " Try to use GPU. The default value is 'no'. All default values\n"
// " are for CPU mode.\n"
// "\nMotion Estimation Flags:\n"
// " --work_megapix <float>\n"
// " Resolution for image registration step. The default is 0.6 Mpx.\n"
// " --features (surf|orb)\n"
// " Type of features used for images matching. The default is surf.\n"
// " --match_conf <float>\n"
// " Confidence for feature matching step. The default is 0.65 for surf and 0.3 for orb.\n"
// " --conf_thresh <float>\n"
// " Threshold for two images are from the same panorama confidence.\n"
// " The default is 1.0.\n"
// " --ba (reproj|ray)\n"
// " Bundle adjustment cost function. The default is ray.\n"
// " --ba_refine_mask (mask)\n"
// " Set refinement mask for bundle adjustment. It looks like 'x_xxx',\n"
// " where 'x' means refine respective parameter and '_' means don't\n"
// " refine one, and has the following format:\n"
// " <fx><skew><ppx><aspect><ppy>. The default mask is 'xxxxx'. If bundle\n"
// " adjustment doesn't support estimation of selected parameter then\n"
// " the respective flag is ignored.\n"
// " --wave_correct (no|horiz|vert)\n"
// " Perform wave effect correction. The default is 'horiz'.\n"
// " --save_graph <file_name>\n"
// " Save matches graph represented in DOT language to <file_name> file.\n"
// " Labels description: Nm is number of matches, Ni is number of inliers,\n"
// " C is confidence.\n"
// "\nCompositing Flags:\n"
// " --warp (plane|cylindrical|spherical|fisheye|stereographic|compressedPlaneA2B1|compressedPlaneA1.5B1|compressedPlanePortraitA2B1|compressedPlanePortraitA1.5B1|paniniA2B1|paniniA1.5B1|paniniPortraitA2B1|paniniPortraitA1.5B1|mercator|transverseMercator)\n"
// " Warp surface type. The default is 'spherical'.\n"
// " --seam_megapix <float>\n"
// " Resolution for seam estimation step. The default is 0.1 Mpx.\n"
// " --seam (no|voronoi|gc_color|gc_colorgrad)\n"
// " Seam estimation method. The default is 'gc_color'.\n"
// " --compose_megapix <float>\n"
// " Resolution for compositing step. Use -1 for original resolution.\n"
// " The default is -1.\n"
// " --expos_comp (no|gain|gain_blocks)\n"
// " Exposure compensation method. The default is 'gain_blocks'.\n"
// " --blend (no|feather|multiband)\n"
// " Blending method. The default is 'multiband'.\n"
// " --blend_strength <float>\n"
// " Blending strength from [0,100] range. The default is 5.\n"
// " --output <result_img>\n"
// " The default is 'result.jpg'.\n";
//}
// Default command line args
/*
运行流程:
1.命令行调用程序,输入源图像以及程序的参数
2.特征点检测,判断是使用surf还是orb,默认是surf。
3.对图像的特征点进行匹配,使用最近邻和次近邻方法,将两个最优的匹配的置信度保存下来。
4.对图像进行排序以及将置信度高的图像保存到同一个集合中,删除置信度比较低的图像间的匹配,得到能正确匹配的图像序列。这样将置信度高于门限的所有匹配合并到一个集合中。
5.对所有图像进行相机参数粗略估计,然后求出旋转矩阵
6.使用光束平均法进一步精准的估计出旋转矩阵。
7.波形校正,水平或者垂直
8.拼接
9.融合,多频段融合,光照补偿
*/
//vector<string> img_names;
bool preview = false; //以预览模式运行程序,比正常模式要快,但输出图像分辨率低,拼接的分辨率compose_megapix 设置为0.6
bool try_gpu = false;
double work_megapix = 0.6;//图像匹配的分辨率大小,图像的面积尺寸变为work_megapix*100000,默认为0.6
double seam_megapix = 0.1; //拼接缝像素的大小 默认是0.1
double compose_megapix = -1; //拼接分辨率
float conf_thresh = 1.f; //两幅图来自同一全景图的置信度,默认为1.0
string features_type = "surf";
//string features_type = "orb";
string ba_cost_func = "ray"; //光束平均法的误差函数选择
//string ba_cost_func = "reproj";
string ba_refine_mask = "xxxxx";
bool do_wave_correct = true;
WaveCorrectKind wave_correct = detail::WAVE_CORRECT_HORIZ;//波形校验 水平,垂直或者没有 默认是horiz
bool save_graph = false;
std::string save_graph_to;
string warp_type = "cylindrical";
int expos_comp_type = ExposureCompensator::GAIN_BLOCKS;
float match_conf = 0.65f;//特征点检测置信等级,最近邻匹配距离与次近邻匹配距离的比值,surf默认为0.65,orb默认为0.3
string seam_find_type = "gc_color"; // 拼接缝隙估计方法
int blend_type = Blender::MULTI_BAND;// 融合方法,默认是多频段融合
float blend_strength = 5;//融合强度,0-100
string result_name = "result.jpg";
vector<std::vector<std::string>> imageNames;
vector<int> idx;
class StitchingVSQt;
////static int parseCmdArgs(int argc, char** argv)
////{
// /*if (argc == 1)
// {
// printUsage();
// return -1;
// }
// for (int i = 1; i < argc; ++i)
// {
// if (string(argv[i]) == "--help" || string(argv[i]) == "/?")
// {
// printUsage();
// return -1;
// }
// else if (string(argv[i]) == "--preview")
// {
// preview = true;
// }
// else if (string(argv[i]) == "--try_gpu")
// {
// if (string(argv[i + 1]) == "no")
// try_gpu = false;
// else if (string(argv[i + 1]) == "yes")
// try_gpu = true;
// else
// {
// cout << "Bad --try_gpu flag value\n";
// return -1;
// }
// i++;
// }
// else if (string(argv[i]) == "--work_megapix")
// {
// work_megapix = atof(argv[i + 1]);
// i++;
// }
// else if (string(argv[i]) == "--seam_megapix")
// {
// seam_megapix = atof(argv[i + 1]);
// i++;
// }
// else if (string(argv[i]) == "--compose_megapix")
// {
// compose_megapix = atof(argv[i + 1]);
// i++;
// }
// else if (string(argv[i]) == "--result")
// {
// result_name = argv[i + 1];
// i++;
// }
// else if (string(argv[i]) == "--features")
// {
// features_type = argv[i + 1];
// if (features_type == "orb")
// match_conf = 0.3f;
// i++;
// }
// else if (string(argv[i]) == "--match_conf")
// {
// match_conf = static_cast<float>(atof(argv[i + 1]));
// i++;
// }
// else if (string(argv[i]) == "--conf_thresh")
// {
// conf_thresh = static_cast<float>(atof(argv[i + 1]));
// i++;
// }
// else if (string(argv[i]) == "--ba")
// {
// ba_cost_func = argv[i + 1];
// i++;
// }
// else if (string(argv[i]) == "--ba_refine_mask")
// {
// ba_refine_mask = argv[i + 1];
// if (ba_refine_mask.size() != 5)
// {
// cout << "Incorrect refinement mask length.\n";
// return -1;
// }
// i++;
// }
// else if (string(argv[i]) == "--wave_correct")
// {
// if (string(argv[i + 1]) == "no")
// do_wave_correct = false;
// else if (string(argv[i + 1]) == "horiz")
// {
// do_wave_correct = true;
// wave_correct = detail::WAVE_CORRECT_HORIZ;
// }
// else if (string(argv[i + 1]) == "vert")
// {
// do_wave_correct = true;
// wave_correct = detail::WAVE_CORRECT_VERT;
// }
// else
// {
// cout << "Bad --wave_correct flag value\n";
// return -1;
// }
// i++;
// }
// else if (string(argv[i]) == "--save_graph")
// {
// save_graph = true;
// save_graph_to = argv[i + 1];
// i++;
// }
// else if (string(argv[i]) == "--warp")
// {
// warp_type = string(argv[i + 1]);
// i++;
// }
// else if (string(argv[i]) == "--expos_comp")
// {
// if (string(argv[i + 1]) == "no")
// expos_comp_type = ExposureCompensator::NO;
// else if (string(argv[i + 1]) == "gain")
// expos_comp_type = ExposureCompensator::GAIN;
// else if (string(argv[i + 1]) == "gain_blocks")
// expos_comp_type = ExposureCompensator::GAIN_BLOCKS;
// else
// {
// cout << "Bad exposure compensation method\n";
// return -1;
// }
// i++;
// }
// else if (string(argv[i]) == "--seam")
// {
// if (string(argv[i + 1]) == "no" ||
// string(argv[i + 1]) == "voronoi" ||
// string(argv[i + 1]) == "gc_color" ||
// string(argv[i + 1]) == "gc_colorgrad" ||
// string(argv[i + 1]) == "dp_color" ||
// string(argv[i + 1]) == "dp_colorgrad")
// seam_find_type = argv[i + 1];
// else
// {
// cout << "Bad seam finding method\n";
// return -1;
// }
// i++;
// }
// else if (string(argv[i]) == "--blend")
// {
// if (string(argv[i + 1]) == "no")
// blend_type = Blender::NO;
// else if (string(argv[i + 1]) == "feather")
// blend_type = Blender::FEATHER;
// else if (string(argv[i + 1]) == "multiband")
// blend_type = Blender::MULTI_BAND;
// else
// {
// cout << "Bad blending method\n";
// return -1;
// }
// i++;
// }
// else if (string(argv[i]) == "--blend_strength")
// {
// blend_strength = static_cast<float>(atof(argv[i + 1]));
// i++;
// }
// else if (string(argv[i]) == "--output")
// {
// result_name = argv[i + 1];
// i++;
// }
// else*/
//// img_names.push_back(argv[i]);
////
//// if (preview)
//// {
//// compose_megapix = 0.6;
//// }
//// return 0;
////}
string& replace_all_distinct(string& str, const string& old_value, const string& new_value)
{
for (string::size_type pos(0); pos != string::npos; pos += new_value.length()) {
if ((pos = str.find(old_value, pos)) != string::npos)
str.replace(pos, old_value.length(), new_value);
else break;
}
return str;
}
int startCalculation()
{
StitchingVSQt s;
std::string msg;
const char* dllName = "stitching.dll";
const char* funName1 = "stitch";
const char* funName2 = "pano_image";
HINSTANCE hDll = LoadLibrary(TEXT("stitching.dll"));
if (hDll != NULL){
STITCH fp = STITCH(GetProcAddress(hDll, "stitch"));
PANOIMAGE fPa = PANOIMAGE(GetProcAddress(hDll, "writeImage"));
if (fp != NULL){
//s.showMessage(QString::fromLocal8Bit("找到dll中的函数"));
void* p=fp(imageNames, nullptr, msg);
//s.showMessage(QString::fromLocal8Bit("第一个函数调用完毕"));
QString fileName(QString::fromStdString(result_name));
QString dir = QFileDialog::getExistingDirectory(NULL, QString::fromLocal8Bit("选择生成图片保存目录"),
"/home",
QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks);
s.changePicture(dir + "/" + fileName);
fPa(p, (dir + "/" + fileName).toStdString());
//s.showMessage(QString::fromLocal8Bit("第二个函数调用完毕"));
/*img_names.clear();*/
imageNames.clear();
idx.clear();
delete p;
}
else{
s.showMessage(QString::fromLocal8Bit("未找到dll中的函数"));
}
FreeLibrary(hDll);
}
else {
s.showMessage(QString::fromLocal8Bit("未找到dll"));
return -1;
}
// QMessageBox::StandardButton rb = QMessageBox::question(NULL, QString::fromLocal8Bit("相机标定参数选择"), QString::fromLocal8Bit("是否导入已有的相机标定参数文件?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
// if (rb == QMessageBox::Yes)
// {
// QStringList fileNames = QFileDialog::getOpenFileNames(NULL,
// QString::fromLocal8Bit("选择此次拼接的相机标定参数"),
// "",
// "TXT Files(*.txt)",
// 0);
// if (fileNames.length() == 0)
// {
// return -1;
// }
// }
// else{
// s.showMessage(QString::fromLocal8Bit("若拼接所用的相机参数尚未标定或保存,请先在标定模块标定,再进行计算"));
// return -1;
// }
//
// QProgressDialog progress(QString::fromLocal8Bit("正在导入图片数据,请稍候..."),
// QString::fromLocal8Bit("取消"),
// 0, 12, // Range
// NULL);
// progress.show();
// qApp->processEvents();
// progress.setWindowModality(Qt::WindowModal);
// progress.setWindowTitle(QString::fromLocal8Bit("正在导入图片数据,请稍候..."));
//
// progress.setValue(1);
// progress.setModal(true);
// progress.setLabelText(QString::fromLocal8Bit("读取图片,请稍候..."));
//
// // Check if have enough images
// int num_images = static_cast<int>(img_names.size());
// if (num_images < 2)
// {
// //LOGLN("Need more images");
// s.showMessage("Need more images");
//
// return -1;
// }
//
// double work_scale = 1, seam_scale = 1, compose_scale = 1;
// bool is_work_scale_set = false, is_seam_scale_set = false, is_compose_scale_set = false;
//
// /**
// *特征点提取
// */
// progress.setValue(2);
// progress.setLabelText(QString::fromLocal8Bit("特征点提取...."));
//
// Ptr<FeaturesFinder> finder;
// if (features_type == "surf")
// {
//#if defined(HAVE_OPENCV_NONFREE) && defined(HAVE_OPENCV_GPU)
// if (try_gpu && gpu::getCudaEnabledDeviceCount() > 0)
// finder = new SurfFeaturesFinderGpu();
// else
//#endif
// finder = new SurfFeaturesFinder();
// }
// else if (features_type == "orb")
// {
// finder = new OrbFeaturesFinder();
// }
// else
// {
// // cout << "Unknown 2D features type: '" << features_type << "'.\n";
// s.showMessage("Unknown 2D features type: '" +QString::fromStdString(features_type));
// return -1;
// }
//
// Mat full_img, img;
// vector<ImageFeatures> features(num_images);
// vector<Mat> images(num_images);
// vector<Size> full_img_sizes(num_images);
// double seam_work_aspect = 1;
//
// for (int i = 0; i < num_images; ++i)
// {
// /*full_img = imread(img_names[i].replace()));*/
//
// full_img = imread(img_names[i]);
// full_img_sizes[i] = full_img.size();
//
// if (full_img.empty())
// {
// //LOGLN("Can't open image " << img_names[i]);
// s.showMessage("Can't open image " + QString::fromStdString(img_names[i]));
// return -1;
// }
//
// if (work_megapix < 0)//图像匹配的分辨率大小
// {
// img = full_img;
// work_scale = 1;
// is_work_scale_set = true;
// }
// else
// {
// if (!is_work_scale_set)
// {
// //work_scale参数设定图像大小(当图像尺寸大于1e6时,缩小图像,提高特征点检测速度),来寻找特征点。
// work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));
// is_work_scale_set = true;
// }
// resize(full_img, img, Size(), work_scale, work_scale);
// }
//
// if (!is_seam_scale_set)////默认值seam_megapix=0.1
// {
// seam_scale = min(1.0, sqrt(seam_megapix * 1e6 / full_img.size().area()));
// seam_work_aspect = seam_scale / work_scale;
// is_seam_scale_set = true;
// }
//
// (*finder)(img, features[i]);
// features[i].img_idx = i;
// // LOGLN("Features in image #" << i + 1 << ": " << features[i].keypoints.size());
// // s.showMessage("Features in image # " + QString::number(i + 1) + ":" + QString::number(features[i].keypoints.size()));
// //按照seam_scale调整图像大小,作为后面缝合缝寻找(seam_finder)的输入图像
// resize(full_img, img, Size(), seam_scale, seam_scale);
// images[i] = img.clone();
// }
//
// finder->collectGarbage();
// full_img.release();
// img.release();
//
//// LOGLN("Finding features, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
//
// progress.setValue(3);
// /*
// 特征点匹配
// */
// vector<MatchesInfo> pairwise_matches;
// BestOf2NearestMatcher matcher=new BestOf2NearestMatcher(try_gpu,match_conf);
//
// try{
// progress.setLabelText(QString::fromLocal8Bit("特征点匹配...."));
// matcher(features, pairwise_matches);
// matcher.collectGarbage();
// }
// catch(Exception){
// s.showMessage(QString::fromLocal8Bit("计算失败,请重试..."));
// return -1;
// }
//
//
//// Check if we should save matches graph
// if (save_graph)
// {
// ofstream f(save_graph_to.c_str());
// f << matchesGraphAsString(img_names, pairwise_matches, conf_thresh);
// }
//
// // Leave only images we are sure are from the same panorama
// vector<int> indices = leaveBiggestComponent(features, pairwise_matches, conf_thresh);
// vector<Mat> img_subset;
// vector<string> img_names_subset;
// vector<Size> full_img_sizes_subset;
//
// for (size_t i = 0; i < indices.size(); ++i)
// {
// img_names_subset.push_back(img_names[indices[i]]);
// img_subset.push_back(images[indices[i]]);
// full_img_sizes_subset.push_back(full_img_sizes[indices[i]]);
// }
//
// images = img_subset;
// img_names = img_names_subset;
// full_img_sizes = full_img_sizes_subset;
//
// // Check if we still have enough images
// num_images = static_cast<int>(img_names.size());
// if (num_images < 2)
// {
// //LOGLN("Need more images");
// s.showMessage("Need more images");
// return -1;
// }
//
// progress.setValue(4);
// progress.setLabelText(QString::fromLocal8Bit("估计相机参数,计算变换矩阵...."));
// //CameraParams 是结构体参数为 Focal length(焦距),double aspect( Aspect ratio纵横比),double ppx 主点x; double ppy 主点y; Mat R// Rotation,Mat t//Translation
// HomographyBasedEstimator estimator;
// vector<CameraParams> cameras;
//
// //投影矩阵k,旋转矩阵R
// estimator(features, pairwise_matches, cameras);
//
//
// for (size_t i = 0; i < cameras.size(); ++i)
// {
// Mat R;
// cameras[i].R.convertTo(R, CV_32F);
// //cout << R << std::endl;
// cameras[i].R = R;
// //LOGLN("Initial intrinsics #" << indices[i] + 1 << ":\n" << cameras[i].K());
// }
//
// Ptr<detail::BundleAdjusterBase> adjuster;
// if (ba_cost_func == "reproj") adjuster = new detail::BundleAdjusterReproj();
// else if (ba_cost_func == "ray") adjuster = new detail::BundleAdjusterRay();
// else
// {
// // cout << "Unknown bundle adjustment cost function: '" << ba_cost_func << "'.\n";
// s.showMessage("Unknown bundle adjustment cost function: '" + QString::fromStdString(ba_cost_func));
//
// return -1;
// }
// adjuster->setConfThresh(conf_thresh);
// Mat_<uchar> refine_mask = Mat::zeros(3, 3, CV_8U);
// if (ba_refine_mask[0] == 'x') refine_mask(0, 0) = 1;
// if (ba_refine_mask[1] == 'x') refine_mask(0, 1) = 1;
// if (ba_refine_mask[2] == 'x') refine_mask(0, 2) = 1;
// if (ba_refine_mask[3] == 'x') refine_mask(1, 1) = 1;
// if (ba_refine_mask[4] == 'x') refine_mask(1, 2) = 1;
// adjuster->setRefinementMask(refine_mask);
// (*adjuster)(features, pairwise_matches, cameras);
//
// // Find median focal length
//
// vector<double> focals;
// for (size_t i = 0; i < cameras.size(); ++i)
// {
// // LOGLN("Camera #" << indices[i] + 1 << ":\n" << cameras[i].K());
// focals.push_back(cameras[i].focal);
// }
//
// sort(focals.begin(), focals.end());
// float warped_image_scale; //赋值为所有焦距的中值
// if (focals.size() % 2 == 1)
// warped_image_scale = static_cast<float>(focals[focals.size() / 2]);
// else
// warped_image_scale = static_cast<float>(focals[focals.size() / 2 - 1] + focals[focals.size() / 2]) * 0.5f;
//
// progress.setValue(5);
//
// if (do_wave_correct)
// {
// vector<Mat> rmats;
// for (size_t i = 0; i < cameras.size(); ++i)
// rmats.push_back(cameras[i].R);
// waveCorrect(rmats, wave_correct);
// for (size_t i = 0; i < cameras.size(); ++i)
// cameras[i].R = rmats[i];
// }
//
// vector<Point> corners(num_images);
// vector<Mat> masks_warped(num_images);
// vector<Mat> images_warped(num_images);
// vector<Size> sizes(num_images);
// vector<Mat> masks(num_images);
//
// // Preapre images masks
// for (int i = 0; i < num_images; ++i)
// {
// masks[i].create(images[i].size(), CV_8U);
// masks[i].setTo(Scalar::all(255));
// }
//
// progress.setValue(6);
// // Warp images and their masks
// progress.setLabelText(QString::fromLocal8Bit("柱面投影...."));
//
// Ptr<WarperCreator> warper_creator;
//#if defined(HAVE_OPENCV_GPU)
// if (try_gpu && gpu::getCudaEnabledDeviceCount() > 0)
// {
// if (warp_type == "plane") warper_creator = new cv::PlaneWarperGpu();
// else if (warp_type == "cylindrical") warper_creator = new cv::CylindricalWarperGpu();
// else if (warp_type == "spherical") warper_creator = new cv::SphericalWarperGpu();
// }
// else
//#endif
// {
// if (warp_type == "plane") warper_creator = new cv::PlaneWarper();
// else if (warp_type == "cylindrical") warper_creator = new cv::CylindricalWarper();
// else if (warp_type == "spherical") warper_creator = new cv::SphericalWarper();
// else if (warp_type == "fisheye") warper_creator = new cv::FisheyeWarper();
// else if (warp_type == "stereographic") warper_creator = new cv::StereographicWarper();
// else if (warp_type == "compressedPlaneA2B1") warper_creator = new cv::CompressedRectilinearWarper(2, 1);
// else if (warp_type == "compressedPlaneA1.5B1") warper_creator = new cv::CompressedRectilinearWarper(1.5, 1);
// else if (warp_type == "compressedPlanePortraitA2B1") warper_creator = new cv::CompressedRectilinearPortraitWarper(2, 1);
// else if (warp_type == "compressedPlanePortraitA1.5B1") warper_creator = new cv::CompressedRectilinearPortraitWarper(1.5, 1);
// else if (warp_type == "paniniA2B1") warper_creator = new cv::PaniniWarper(2, 1);
// else if (warp_type == "paniniA1.5B1") warper_creator = new cv::PaniniWarper(1.5, 1);
// else if (warp_type == "paniniPortraitA2B1") warper_creator = new cv::PaniniPortraitWarper(2, 1);
// else if (warp_type == "paniniPortraitA1.5B1") warper_creator = new cv::PaniniPortraitWarper(1.5, 1);
// else if (warp_type == "mercator") warper_creator = new cv::MercatorWarper();
// else if (warp_type == "transverseMercator") warper_creator = new cv::TransverseMercatorWarper();
// }
//
// if (warper_creator.empty())
// {
// cout << "Can't create the following warper '" << warp_type << "'\n";
// return 1;
// }
//
// // 投影变换
// Ptr<RotationWarper> warper = warper_creator->create(static_cast<float>(warped_image_scale * seam_work_aspect));
//
// for (int i = 0; i < num_images; ++i)
// {
// Mat_<float> K;
// cameras[i].K().convertTo(K, CV_32F);
// float swa = (float)seam_work_aspect;
// K(0, 0) *= swa; K(0, 2) *= swa;
// K(1, 1) *= swa; K(1, 2) *= swa;
//
// corners[i] = warper->warp(images[i], K, cameras[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]);
// //QMessageBox::warning(this, QString::fromLocal8Bit("提示"), content, QMessageBox::Yes | QMessageBox::No);
//
// sizes[i] = images_warped[i].size();
//
// warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
// }
//
// vector<Mat> images_warped_f(num_images);
// for (int i = 0; i < num_images; ++i)
// images_warped[i].convertTo(images_warped_f[i], CV_32F);
//
// //LOGLN("Warping images, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
//
// progress.setValue(7);
// Ptr<ExposureCompensator> compensator = ExposureCompensator::createDefault(expos_comp_type);
// compensator->feed(corners, images_warped, masks_warped);
//
// progress.setValue(8);
// Ptr<SeamFinder> seam_finder;
// if (seam_find_type == "no")
// seam_finder = new detail::NoSeamFinder();
// else if (seam_find_type == "voronoi")
// seam_finder = new detail::VoronoiSeamFinder();
// else if (seam_find_type == "gc_color")
// {
//#if defined(HAVE_OPENCV_GPU)
// if (try_gpu && gpu::getCudaEnabledDeviceCount() > 0)
// seam_finder = new detail::GraphCutSeamFinderGpu(GraphCutSeamFinderBase::COST_COLOR);
// else
//#endif
// seam_finder = new detail::GraphCutSeamFinder(GraphCutSeamFinderBase::COST_COLOR);
// }
// else if (seam_find_type == "gc_colorgrad")
// {
//#if defined(HAVE_OPENCV_GPU)
// if (try_gpu && gpu::getCudaEnabledDeviceCount() > 0)
// seam_finder = new detail::GraphCutSeamFinderGpu(GraphCutSeamFinderBase::COST_COLOR_GRAD);
// else
//#endif
// seam_finder = new detail::GraphCutSeamFinder(GraphCutSeamFinderBase::COST_COLOR_GRAD);
// }
// else if (seam_find_type == "dp_color")
// seam_finder = new detail::DpSeamFinder(DpSeamFinder::COLOR);
// else if (seam_find_type == "dp_colorgrad")
// seam_finder = new detail::DpSeamFinder(DpSeamFinder::COLOR_GRAD);
// if (seam_finder.empty())
// {
// cout << "Can't create the following seam finder '" << seam_find_type << "'\n";
// return 1;
// }
//
// seam_finder->find(images_warped_f, corners, masks_warped);
//
// // Release unused memory
// images.clear();
// images_warped.clear();
// images_warped_f.clear();
// masks.clear();
//
// //LOGLN("Compositing...");
////#if ENABLE_LOG
//// t = getTickCount();
////#endif
//
// progress.setValue(9);
// progress.setLabelText(QString::fromLocal8Bit("图像融合...."));
// Mat img_warped, img_warped_s;
// Mat dilated_mask, seam_mask, mask, mask_warped;
//
// //图像融合
// Ptr<Blender> blender;
// //double compose_seam_aspect = 1;
// double compose_work_aspect = 1;
//
// for (int img_idx = 0; img_idx < num_images; ++img_idx)
// {
// //LOGLN("Compositing image #" << indices[img_idx] + 1);
// /*
// 由于以前进行处理的图片都是以work_scale(3.1节有介绍)进行缩放的,
// 所以图像的内参,corner(同一坐标后的顶点),mask(融合的掩码)都需要重新计算。
// 以及将之前计算的光照增强的gain也要计算进去
// */
// // Read image and resize it if necessary
// full_img = imread(img_names[img_idx]);
// if (!is_compose_scale_set)
// {
// if (compose_megapix > 0)
// compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area()));
// is_compose_scale_set = true;
//
// // Compute relative scales
// //compose_seam_aspect = compose_scale / seam_scale;
// compose_work_aspect = compose_scale / work_scale;
//
// // Update warped image scale
// warped_image_scale *= static_cast<float>(compose_work_aspect);
// warper = warper_creator->create(warped_image_scale);
//
// // Update corners and sizes
// for (int i = 0; i < num_images; ++i)
// {
// // Update intrinsics
// cameras[i].focal *= compose_work_aspect;
// cameras[i].ppx *= compose_work_aspect;
// cameras[i].ppy *= compose_work_aspect;
//
// // Update corner and size
// Size sz = full_img_sizes[i];
// if (std::abs(compose_scale - 1) > 1e-1)
// {
// sz.width = cvRound(full_img_sizes[i].width * compose_scale);
// sz.height = cvRound(full_img_sizes[i].height * compose_scale);
// }
//
// Mat K;
// cameras[i].K().convertTo(K, CV_32F);
// Rect roi = warper->warpRoi(sz, K, cameras[i].R);
// corners[i] = roi.tl();
// sizes[i] = roi.size();
// }
// }
//
// if (abs(compose_scale - 1) > 1e-1)
// resize(full_img, img, Size(), compose_scale, compose_scale);
// else
// img = full_img;
// full_img.release();
// Size img_size = img.size();
//
// Mat K;
// cameras[img_idx].K().convertTo(K, CV_32F);
//
// progress.setValue(10);
// // Warp the current image
// warper->warp(img, K, cameras[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped);
//
// // Warp the current image mask
// mask.create(img_size, CV_8U);
// mask.setTo(Scalar::all(255));
// warper->warp(mask, K, cameras[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped);
//
// // Compensate exposure,光照补偿
// progress.setLabelText(QString::fromLocal8Bit("光照补偿...."));
// compensator->apply(img_idx, corners[img_idx], img_warped, mask_warped);
//
// img_warped.convertTo(img_warped_s, CV_16S);
// img_warped.release();
// img.release();
// mask.release();
//
// dilate(masks_warped[img_idx], dilated_mask, Mat());
// resize(dilated_mask, seam_mask, mask_warped.size());
// mask_warped = seam_mask & mask_warped;
//
// /*
// 进行多波段融合,首先初始化blend,确定blender的融合的方式,默认是多波段融合MULTI_BAND,
// 以及根据corners顶点和图像的大小确定最终全景图的尺寸
// */
//
// if (blender.empty())
// {
// blender = Blender::createDefault(blend_type, try_gpu);
// Size dst_sz = resultRoi(corners, sizes).size();//计算最后图像的大小
// float blend_width = sqrt(static_cast<float>(dst_sz.area())) * blend_strength / 100.f;
// if (blend_width < 1.f)
// blender = Blender::createDefault(Blender::NO, try_gpu);
// else if (blend_type == Blender::MULTI_BAND)
// {
// MultiBandBlender* mb = dynamic_cast<MultiBandBlender*>(static_cast<Blender*>(blender));
// mb->setNumBands(static_cast<int>(ceil(log(blend_width) / log(2.)) - 1.));
// //LOGLN("Multi-band blender, number of bands: " << mb->numBands());
// }
// else if (blend_type == Blender::FEATHER)
// {
// FeatherBlender* fb = dynamic_cast<FeatherBlender*>(static_cast<Blender*>(blender));
// fb->setSharpness(1.f / blend_width);
// //LOGLN("Feather blender, sharpness: " << fb->sharpness());
// }
// blender->prepare(corners, sizes);////根据corners顶点和图像的大小确定最终全景图的尺寸
// }
//
// /*
// *然后对每幅图图形构建金字塔,层数可以由输入的系数确定,默认是5层。
// 先对顶点以及图像的宽和高做处理,使其能被2^num_bands除尽,
// 这样才能将进行向下采样num_bands次,首先从源图像pyrDown向下采样,
// 在由最底部的图像pyrUp向上采样,把对应层得上采样和下采样的相减,
// 就得到了图像的高频分量,存储到每一个金字塔中。然后根据mask,
// 将每幅图像的各层金字塔分别写入最终的金字塔层dst_pyr_laplace中。
// *
// */
//
// // Blend the current image
// //将图像写入金字塔中
// blender->feed(img_warped_s, mask_warped, corners[img_idx]);
// }
// progress.setLabelText(QString::fromLocal8Bit("根据corners顶点和图像大小确定最终全景图尺寸...."));
//
// progress.setValue(11);
// Mat result, result_mask;
// blender->blend(result, result_mask);////将多层金字塔图形叠加
//
// progress.setValue(12);
// //s.showMessage("Finished!");
// s.showMessage(QString::fromLocal8Bit("计算结束!"));
return 0;
}
void controlProgress(int status){
}