36 vector<Point3D>& point_data, vector<Point2D>& measurements,
37 vector<int>& ptidx, vector<int>& camidx,
38 vector<string>& names, vector<int>& ptc);
40 vector<Point3D>& point_data, vector<Point2D>& measurements,
41 vector<int>& ptidx, vector<int>& camidx, vector<string>& names,
44 vector<Point3D>& point_data,
45 vector<Point2D>& measurements, vector<int>& ptidx,
49 void AddNoise(vector<CameraT>& camera_data, vector<Point3D>& point_data,
51 void AddStableNoise(vector<CameraT>& camera_data, vector<Point3D>& point_data,
52 const vector<int>& ptidx,
const vector<int>& camidx,
55 vector<Point3D>& point_data, vector<int>& ptidx,
56 vector<int>& camidx, vector<Point2D>& measurements,
57 vector<string>& names, vector<int>& ptc);
60 bool LoadNVM(ifstream& in, vector<CameraT>& camera_data,
61 vector<Point3D>& point_data, vector<Point2D>& measurements,
62 vector<int>& ptidx, vector<int>& camidx, vector<string>& names,
64 int rotation_parameter_num = 4;
65 bool format_r9t =
false;
67 if (in.peek() ==
'N') {
69 if (strstr(token.c_str(),
"R9T")) {
70 rotation_parameter_num = 9;
75 int ncam = 0, npoint = 0, nproj = 0;
78 if (ncam <= 1)
return false;
81 camera_data.resize(ncam);
83 for (
int i = 0; i < ncam; ++i) {
84 double f, q[9], c[3], d[2];
86 for (
int j = 0; j < rotation_parameter_num; ++j) in >> q[j];
87 in >> c[0] >> c[1] >> c[2] >> d[0] >> d[1];
89 camera_data[i].SetFocalLength(f);
91 camera_data[i].SetMatrixRotation(q);
92 camera_data[i].SetTranslation(c);
95 camera_data[i].SetQuaternionRotation(q);
96 camera_data[i].SetCameraCenterAfterRotation(
99 camera_data[i].SetNormalizedMeasurementDistortion(d[0]);
105 if (npoint <= 0)
return false;
108 point_data.resize(npoint);
109 for (
int i = 0; i < npoint; ++i) {
112 in >> pt[0] >> pt[1] >> pt[2] >> cc[0] >> cc[1] >> cc[2] >> npj;
113 for (
int j = 0; j < npj; ++j) {
116 in >> cidx >> fidx >> imx >> imy;
118 camidx.push_back(cidx);
122 measurements.push_back(
Point2D(imx, imy));
125 point_data[i].SetPoint(pt);
126 ptc.insert(ptc.end(), cc, cc + 3);
129 std::cout << ncam <<
" cameras; " << npoint <<
" 3D points; " << nproj
136 vector<Point3D>& point_data, vector<Point2D>& measurements,
137 vector<int>& ptidx, vector<int>& camidx, vector<string>& names,
139 std::cout <<
"Saving model to " <<
filename <<
"...\n";
142 out <<
"NVM_V3_R9T\n" << camera_data.size() <<
'\n' << std::setprecision(12);
143 if (names.size() < camera_data.size())
144 names.resize(camera_data.size(),
string(
"unknown"));
145 if (ptc.size() < 3 * point_data.size()) ptc.resize(point_data.size() * 3, 0);
148 for (
size_t i = 0; i < camera_data.size(); ++i) {
151 for (
int j = 0; j < 9; ++j) out << cam.
m[0][j] <<
' ';
152 out << cam.
t[0] <<
' ' << cam.
t[1] <<
' ' << cam.
t[2] <<
' '
156 out << point_data.size() <<
'\n';
158 for (
size_t i = 0, j = 0; i < point_data.size(); ++i) {
160 int* pc = &ptc[i * 3];
161 out << pt.
xyz[0] <<
' ' << pt.
xyz[1] <<
' ' << pt.
xyz[2] <<
' ' << pc[0]
162 <<
' ' << pc[1] <<
' ' << pc[2] <<
' ';
165 while (je < ptidx.size() && ptidx[je] == (
int)i) je++;
167 out << (je - j) <<
' ';
170 out << camidx[j] <<
' ' <<
" 0 " << measurements[j].x <<
' '
171 << measurements[j].y <<
' ';
178 vector<CameraT>& camera_data, vector<Point3D>& point_data,
179 vector<Point2D>& measurements, vector<int>& ptidx,
180 vector<int>& camidx, vector<string>& names,
182 int rotation_parameter_num = 9;
184 while (in.peek() ==
'#') std::getline(in, token);
186 char listpath[1024], filepath[1024];
187 strcpy(listpath,
name);
188 char* ext = strstr(listpath,
".out");
189 strcpy(ext,
"-list.txt\0");
192 ifstream listin(listpath);
193 if (!listin.is_open()) {
196 char* slash = strrchr(listpath,
'/');
197 if (slash ==
NULL) slash = strrchr(listpath,
'\\');
198 slash = slash ? slash + 1 : listpath;
199 strcpy(slash,
"image_list.txt");
200 listin.open(listpath);
202 if (listin) std::cout <<
"Using image list: " << listpath <<
'\n';
205 int ncam = 0, npoint = 0, nproj = 0;
206 in >> ncam >> npoint;
207 if (ncam <= 1 || npoint <= 1)
return false;
208 std::cout << ncam <<
" cameras; " << npoint <<
" 3D points;\n";
211 camera_data.resize(ncam);
214 bool det_checked =
false;
215 for (
int i = 0; i < ncam; ++i) {
216 float f, q[9], c[3], d[2];
217 in >> f >> d[0] >> d[1];
218 for (
int j = 0; j < rotation_parameter_num; ++j) in >> q[j];
219 in >> c[0] >> c[1] >> c[2];
221 camera_data[i].SetFocalLength(f);
222 camera_data[i].SetInvertedR9T(q, c);
223 camera_data[i].SetProjectionDistortion(d[0]);
225 if (listin >> filepath && f != 0) {
226 char* slash = strrchr(filepath,
'/');
227 if (slash ==
NULL) slash = strchr(filepath,
'\\');
228 names[i] = (slash ? (slash + 1) : filepath);
229 std::getline(listin, token);
232 float det = camera_data[i].GetRotationMatrixDeterminant();
233 std::cout <<
"Check rotation matrix: " << det <<
'\n';
237 names[i] =
"unknown";
242 point_data.resize(npoint);
243 for (
int i = 0; i < npoint; ++i) {
246 in >> pt[0] >> pt[1] >> pt[2] >> cc[0] >> cc[1] >> cc[2] >> npj;
247 for (
int j = 0; j < npj; ++j) {
250 in >> cidx >> fidx >> imx >> imy;
252 camidx.push_back(cidx);
256 measurements.push_back(
Point2D(imx, -imy));
259 point_data[i].SetPoint(pt[0], pt[1], pt[2]);
260 ptc.insert(ptc.end(), cc, cc + 3);
263 std::cout << ncam <<
" cameras; " << npoint <<
" 3D points; " << nproj
269 vector<Point3D>& point_data, vector<Point2D>& measurements,
270 vector<int>& ptidx, vector<int>& camidx,
271 vector<string>& names, vector<int>& ptc) {
274 char* ext = strstr(listpath,
".out");
275 if (ext ==
NULL)
return;
276 strcpy(ext,
"-list.txt\0");
279 out <<
"# Bundle file v0.3\n";
280 out << std::setprecision(12);
281 out << camera_data.size() <<
" " << point_data.size() <<
'\n';
284 for (
size_t i = 0; i < camera_data.size(); ++i) {
289 for (
int j = 0; j < 9; ++j) out << q[j] << (((j % 3) == 2) ?
'\n' :
' ');
290 out << c[0] <<
' ' << c[1] <<
' ' << c[2] <<
'\n';
293 for (
size_t i = 0, j = 0; i < point_data.size(); ++i) {
294 int npj = 0, *ci = &ptc[i * 3];
296 while (j + npj < point_data.size() && ptidx[j + npj] == ptidx[j]) npj++;
298 out << pt.
xyz[0] <<
' ' << pt.
xyz[1] <<
' ' << pt.
xyz[2] <<
'\n';
299 out << ci[0] <<
' ' << ci[1] <<
' ' << ci[2] <<
'\n';
301 for (
int k = 0; k < npj; ++k)
302 out << camidx[j + k] <<
" 0 " << measurements[j + k].x <<
' '
303 << -measurements[j + k].y <<
'\n';
308 ofstream listout(listpath);
309 for (
size_t i = 0; i < names.size(); ++i) listout << names[i] <<
'\n';
312 template <
class CameraT,
class Po
int3D>
314 vector<Point3D>& point_data,
315 vector<Point2D>& measurements, vector<int>& ptidx,
316 vector<int>& camidx) {
318 size_t ncam = 0, npt = 0, nproj = 0;
319 if (!(in >> ncam >> npt >> nproj))
return false;
321 std::cout << ncam <<
" cameras; " << npt <<
" 3D points; " << nproj
324 camera_data.resize(ncam);
325 point_data.resize(npt);
326 measurements.resize(nproj);
327 camidx.resize(nproj);
330 for (
size_t i = 0; i < nproj; ++i) {
333 in >> cidx >> pidx >> x >> y;
334 if (((
size_t)pidx) == npt && camidx.size() > i) {
337 measurements.resize(i);
338 std::cout <<
"Truncate measurements to " << i <<
'\n';
339 }
else if (((
size_t)pidx) >= npt) {
344 measurements[i].SetPoint2D(x, -y);
348 for (
size_t i = 0; i < ncam; ++i) {
350 for (
int j = 0; j < 9; ++j) in >> p[j];
357 for (
size_t i = 0; i < npt; ++i) {
359 in >> pt[0] >> pt[1] >> pt[2];
360 point_data[i].SetPoint(pt);
366 vector<Point3D>& point_data,
367 vector<Point2D>& measurements, vector<int>& ptidx,
368 vector<int>& camidx) {
369 std::cout <<
"Saving model to " <<
filename <<
"...\n";
371 out << std::setprecision(12);
372 out << camera_data.size() <<
' ' << point_data.size() <<
' '
373 << measurements.size() <<
'\n';
374 for (
size_t i = 0; i < measurements.size(); ++i) {
375 out << camidx[i] <<
' ' << ptidx[i] <<
' ' << measurements[i].x <<
' '
376 << -measurements[i].y <<
'\n';
379 for (
size_t i = 0; i < camera_data.size(); ++i) {
383 out << r[0] <<
' ' << r[1] <<
' ' << r[2] <<
' ' << t[0] <<
' ' << t[1]
388 for (
size_t i = 0; i < point_data.size(); ++i) {
390 out << pt.
xyz[0] <<
' ' << pt.
xyz[1] <<
' ' << pt.
xyz[2] <<
'\n';
395 vector<Point3D>& point_data, vector<Point2D>& measurements,
396 vector<int>& ptidx, vector<int>& camidx,
397 vector<string>& names, vector<int>& ptc) {
401 std::cout <<
"Loading cameras/points: " <<
name <<
"\n";
402 if (!in.is_open())
return false;
404 if (strstr(
name,
".nvm"))
405 return LoadNVM(in, camera_data, point_data, measurements, ptidx, camidx,
407 else if (strstr(
name,
".out"))
409 ptidx, camidx, names, ptc);
416 return (rand() % 101 - 50) * 0.02f * percent + 1.0f;
419 void AddNoise(vector<CameraT>& camera_data, vector<Point3D>& point_data,
421 std::srand((
unsigned int)time(
NULL));
422 for (
size_t i = 0; i < camera_data.size(); ++i) {
428 camera_data[i].GetRodriguesRotation(e);
432 camera_data[i].SetRodriguesRotation(e);
435 for (
size_t i = 0; i < point_data.size(); ++i) {
443 const vector<int>& ptidx,
const vector<int>& camidx,
446 std::srand((
unsigned int)time(
NULL));
448 vector<float> zz0(ptidx.size());
449 vector<CameraT> backup = camera_data;
450 vector<float> vx(point_data.size()), vy(point_data.size()),
451 vz(point_data.size());
452 for (
size_t i = 0; i < point_data.size(); ++i) {
460 size_t median_idx = point_data.size() / 2;
462 std::nth_element(vx.begin(), vx.begin() + median_idx, vx.end());
463 std::nth_element(vy.begin(), vy.begin() + median_idx, vy.end());
464 std::nth_element(vz.begin(), vz.begin() + median_idx, vz.end());
465 float cx = vx[median_idx], cy = vy[median_idx], cz = vz[median_idx];
467 for (
size_t i = 0; i < ptidx.size(); ++i) {
468 CameraT& cam = camera_data[camidx[i]];
469 Point3D& pt = point_data[ptidx[i]];
470 zz0[i] = cam.
m[2][0] * pt.
xyz[0] + cam.
m[2][1] * pt.
xyz[1] +
471 cam.
m[2][2] * pt.
xyz[2] + cam.
t[2];
474 vector<float> z2 = zz0;
475 median_idx = ptidx.size() / 2;
476 std::nth_element(z2.begin(), z2.begin() + median_idx, z2.end());
477 float mz = z2[median_idx];
478 float dist_noise_base = mz * 0.2f;
482 for (
size_t i = 0; i < point_data.size(); ++i) {
489 vector<bool> need_modification(camera_data.size(),
true);
490 int invalid_count = 0, modify_iteration = 1;
494 std::cout <<
"NOTE" << std::setw(2) << modify_iteration <<
": modify "
495 << invalid_count <<
" camera to fix visibility\n";
498 for (
size_t i = 0; i < camera_data.size(); ++i) {
499 if (!need_modification[i])
continue;
507 c[0] = c[0] - cx + dist_noise_base *
random_ratio(percent);
508 c[1] = c[1] - cy + dist_noise_base *
random_ratio(percent);
509 c[2] = c[2] - cz + dist_noise_base *
random_ratio(percent);
521 vector<bool> invalidc(camera_data.size(),
false);
524 for (
size_t i = 0; i < ptidx.size(); ++i) {
526 if (need_modification[cid] ==
false)
continue;
527 if (invalidc[cid])
continue;
528 CameraT& cam = camera_data[cid];
529 Point3D& pt = point_data[ptidx[i]];
530 float z = cam.
m[2][0] * pt.
xyz[0] + cam.
m[2][1] * pt.
xyz[1] +
531 cam.
m[2][2] * pt.
xyz[2] + cam.
t[2];
532 if (z * zz0[i] > 0)
continue;
533 if (zz0[i] == 0 && z > 0)
continue;
535 invalidc[cid] =
true;
538 need_modification = invalidc;
541 }
while (invalid_count && modify_iteration < 20);
546 vector<CameraD> camera_data;
547 vector<Point3B> point_data;
548 vector<int> ptidx, camidx;
549 vector<Point2D> measurements;
550 ifstream in(input_filename);
555 double d1 = 100, d2 = 100;
556 std::cout <<
"checking visibility...\n";
557 vector<double> zz(ptidx.size());
558 for (
size_t i = 0; i < ptidx.size(); ++i) {
559 CameraD& cam = camera_data[camidx[i]];
560 Point3B& pt = point_data[ptidx[i]];
561 double dz = cam.m[2][0] * pt.xyz[0] + cam.m[2][1] * pt.xyz[1] +
562 cam.m[2][2] * pt.xyz[2] + cam.t[2];
570 cam.GetCameraCenter(c);
576 double fz = camt.
m[2][0] * ptt.
xyz[0] + camt.
m[2][1] * ptt.
xyz[1] +
577 camt.
m[2][2] * ptt.
xyz[2] + camt.
t[2];
578 double fz2 = camt.
m[2][0] * (ptt.
xyz[0] - c[0]) +
579 camt.
m[2][1] * (ptt.
xyz[1] - c[1]) +
580 camt.
m[2][2] * (ptt.
xyz[2] - c[2]);
584 if (dz * fz <= 0 || fz == 0) {
587 <<
"; double: " << dz <<
"; float " << fz <<
"; float2 " << fz2
604 std::cout <<
count <<
" points moved to wrong side " << d1 <<
", " << d2
609 vector<Point3D>& point_data, vector<int>& ptidx,
610 vector<int>& camidx, vector<Point2D>& measurements,
611 vector<string>& names, vector<int>& ptc) {
612 vector<float> zz(ptidx.size());
613 for (
size_t i = 0; i < ptidx.size(); ++i) {
614 CameraT& cam = camera_data[camidx[i]];
615 Point3D& pt = point_data[ptidx[i]];
616 zz[i] = cam.
m[2][0] * pt.
xyz[0] + cam.
m[2][1] * pt.
xyz[1] +
617 cam.
m[2][2] * pt.
xyz[2] + cam.
t[2];
619 size_t median_idx = ptidx.size() / 2;
620 std::nth_element(zz.begin(), zz.begin() + median_idx, zz.end());
621 float dist_threshold = zz[median_idx] * 0.001f;
624 vector<bool> pmask(point_data.size(),
true);
625 int points_removed = 0;
626 for (
size_t i = 0; i < ptidx.size(); ++i) {
627 int cid = camidx[i], pid = ptidx[i];
628 if (!pmask[pid])
continue;
629 CameraT& cam = camera_data[cid];
631 bool visible = (cam.
m[2][0] * pt.
xyz[0] + cam.
m[2][1] * pt.
xyz[1] +
632 cam.
m[2][2] * pt.
xyz[2] + cam.
t[2] >
634 pmask[pid] = visible;
635 if (!visible) points_removed++;
637 if (points_removed == 0)
return false;
638 vector<int> cv(camera_data.size(), 0);
640 int min_observation = 20;
644 std::fill(cv.begin(), cv.end(), 0);
645 for (
size_t i = 0; i < ptidx.size(); ++i) {
646 int cid = camidx[i], pid = ptidx[i];
647 if (pmask[pid]) cv[cid]++;
651 vector<int> pv(point_data.size(), 0);
652 for (
size_t i = 0; i < ptidx.size(); ++i) {
653 int cid = camidx[i], pid = ptidx[i];
654 if (!pmask[pid])
continue;
655 if (cv[cid] < min_observation)
664 for (
size_t i = 0; i < point_data.size(); ++i) {
665 if (pmask[i] ==
false)
continue;
666 if (pv[i] >= 2)
continue;
670 }
while (points_removed > 0);
673 vector<bool> cmask(camera_data.size(),
true);
674 for (
size_t i = 0; i < camera_data.size(); ++i)
675 cmask[i] = cv[i] >= min_observation;
678 vector<int> cidx(camera_data.size());
679 vector<int> pidx(point_data.size());
682 vector<CameraT> camera_data2;
683 vector<Point3D> point_data2;
686 vector<Point2D> measurements2;
687 vector<string> names2;
691 if (names.size() < camera_data.size())
692 names.resize(camera_data.size(),
string(
"unknown"));
693 if (ptc.size() < 3 * point_data.size()) ptc.resize(point_data.size() * 3, 0);
696 int new_camera_count = 0, new_point_count = 0;
697 for (
size_t i = 0; i < camera_data.size(); ++i) {
698 if (!cmask[i])
continue;
699 camera_data2.push_back(camera_data[i]);
700 names2.push_back(names[i]);
701 cidx[i] = new_camera_count++;
704 for (
size_t i = 0; i < point_data.size(); ++i) {
705 if (!pmask[i])
continue;
706 point_data2.push_back(point_data[i]);
707 ptc.push_back(ptc[i]);
708 pidx[i] = new_point_count++;
711 int new_observation_count = 0;
712 for (
size_t i = 0; i < ptidx.size(); ++i) {
713 int pid = ptidx[i], cid = camidx[i];
714 if (!pmask[pid] || !cmask[cid])
continue;
715 ptidx2.push_back(pidx[pid]);
716 camidx2.push_back(cidx[cid]);
717 measurements2.push_back(measurements[i]);
718 new_observation_count++;
721 std::cout <<
"NOTE: removing " << (camera_data.size() - new_camera_count)
722 <<
" cameras; " << (point_data.size() - new_point_count)
723 <<
" 3D Points; " << (measurements.size() - new_observation_count)
724 <<
" Observations;\n";
726 camera_data2.swap(camera_data);
728 point_data2.swap(point_data);
731 camidx2.swap(camidx);
732 measurements2.swap(measurements);
738 vector<Point3D>& point_data, vector<Point2D>& measurements,
739 vector<int>& ptidx, vector<int>& camidx,
740 vector<string>& names, vector<int>& ptc) {
741 if (outpath ==
NULL)
return;
742 if (strstr(outpath,
".nvm"))
743 SaveNVM(outpath, camera_data, point_data, measurements, ptidx, camidx,
745 else if (strstr(outpath,
".out"))
746 SaveBundlerOut(outpath, camera_data, point_data, measurements, ptidx,
__host__ __device__ float2 fabs(float2 v)
bool LoadBundlerModel(ifstream &in, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx)
bool LoadBundlerOut(const char *name, ifstream &in, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx, vector< string > &names, vector< int > &ptc)
bool LoadModelFile(const char *name, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx, vector< string > &names, vector< int > &ptc)
void SaveNVM(const char *filename, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx, vector< string > &names, vector< int > &ptc)
float random_ratio(float percent)
void SaveBundlerModel(const char *filename, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx)
void AddStableNoise(vector< CameraT > &camera_data, vector< Point3D > &point_data, const vector< int > &ptidx, const vector< int > &camidx, float percent)
bool RemoveInvisiblePoints(vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< int > &ptidx, vector< int > &camidx, vector< Point2D > &measurements, vector< string > &names, vector< int > &ptc)
bool LoadNVM(ifstream &in, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx, vector< string > &names, vector< int > &ptc)
void ExamineVisiblity(const char *input_filename)
void SaveModelFile(const char *outpath, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx, vector< string > &names, vector< int > &ptc)
void SaveBundlerOut(const char *filename, vector< CameraT > &camera_data, vector< Point3D > &point_data, vector< Point2D > &measurements, vector< int > &ptidx, vector< int > &camidx, vector< string > &names, vector< int > &ptc)
void AddNoise(vector< CameraT > &camera_data, vector< Point3D > &point_data, float percent)
void GetInvertedRT(Float e[3], Float T[3]) const
void GetRodriguesRotation(Float r[3]) const
void GetInvertedR9T(Float e[9], Float T[3]) const
void SetProjectionDistortion(Float r)
float_t GetFocalLength() const
float_t GetNormalizedMeasurementDistortion() const
void SetCameraCenterAfterRotation(const Float c[3])
void SetInvertedRT(const Float e[3], const Float T[3])
void SetCameraT(const CameraX &cam)
void SetFocalLength(Float F)
void SetRodriguesRotation(const Float r[3])
float_t GetProjectionDistortion() const
void GetCameraCenter(Float c[3])
void SetPoint(Float x, Float y, Float z)