24 #include <QApplication>
27 #include <QFileDialog>
29 #include <QInputDialog>
63 QStringList{
"out"},
"out",
64 QStringList{
"Snavely's Bundler output (*.out)"},
84 const QString& _altKeypointsFilename ,
85 bool _undistortImages ,
86 bool _generateColoredDTM ,
87 unsigned _coloredDTMVerticesCount ,
88 float _scaleFactor ) {
93 QTextStream stream(&f);
96 QString currentLine = stream.readLine();
98 CVLog::Error(
"File should start by '# Bundle file vX.Y'!");
101 unsigned majorVer = 0, minorVer = 0;
102 sscanf(qPrintable(currentLine),
"# Bundle file v%u.%u", &majorVer,
104 if (majorVer != 0 || (minorVer != 3 && minorVer != 4)) {
106 "Only version 0.3 and 0.4 of Bundler files are supported!");
111 currentLine = stream.readLine();
114 if (list.size() != 2) {
116 "[Bundler] Second line should be <num_cameras> <num_points>!");
119 unsigned camCount = list[0].toInt();
123 unsigned ptsCount = list[1].toInt();
125 CVLog::Warning(
"[Bundler] No keypoints defined in Bundler file!");
128 bool importKeypoints =
false;
129 bool useAltKeypoints =
false;
130 bool importImages =
false;
131 bool undistortImages =
false;
132 bool orthoRectifyImagesAsClouds =
false;
133 bool orthoRectifyImagesAsImages =
false;
134 bool orthoRectifyImages =
false;
135 bool generateColoredDTM =
false;
136 unsigned coloredDTMVerticesCount = 1000000;
137 float scaleFactor = 1.0f;
138 bool keepImagesInMemory =
false;
139 bool applyOptMatrix =
false;
146 QString imageListFilename = QFileInfo(f).dir().absoluteFilePath(
"list.txt");
147 QString altKeypointsFilename =
148 QFileInfo(f).dir().absoluteFilePath(
"pmvs.ply");
155 biDlg.
setVer(majorVer, minorVer);
178 orthoRectifyImagesAsImages =
true;
179 useAltKeypoints = !_altKeypointsFilename.isEmpty();
180 if (useAltKeypoints) altKeypointsFilename = _altKeypointsFilename;
181 undistortImages = _undistortImages;
182 generateColoredDTM = _generateColoredDTM;
183 if (generateColoredDTM)
184 coloredDTMVerticesCount = _coloredDTMVerticesCount;
185 scaleFactor = _scaleFactor;
191 orthoRectifyImagesAsClouds || orthoRectifyImagesAsImages;
194 std::vector<BundlerCamera> cameras;
197 typedef std::pair<unsigned, ccCameraSensor::KeyPoint> KeypointAndCamIndex;
198 std::vector<KeypointAndCamIndex> keypointsDescriptors;
203 QScopedPointer<ecvProgressDialog> pDlg(0);
207 pDlg->setMethodTitle(QObject::tr(
"Open Bundler file"));
208 pDlg->setInfo(QObject::tr(
"Cameras: %1\nPoints: %2")
215 camCount + (importKeypoints || orthoRectifyImages ||
221 cameras.resize(camCount);
222 unsigned camIndex = 0;
223 for (std::vector<BundlerCamera>::iterator it = cameras.begin();
224 it != cameras.end(); ++it, ++camIndex) {
226 currentLine = stream.readLine();
232 bool ok[3] = {
true,
true,
true};
233 it->f_pix = tokens[0].toFloat(ok);
234 it->k1 = tokens[1].toFloat(ok + 1);
235 it->k2 = tokens[2].toFloat(ok + 2);
239 double* mat = (importImages ? it->trans.data() : 0);
241 for (
unsigned l = 0; l < 3; ++l) {
242 currentLine = stream.readLine();
248 bool ok[3] = {
true,
true,
true};
249 mat[l] = tokens[0].toDouble(ok);
250 mat[4 + l] = tokens[1].toDouble(ok + 1);
251 mat[8 + l] = tokens[2].toDouble(ok + 2);
252 if (!ok[0] || !ok[1] || !ok[2])
254 sum +=
fabs(mat[l]) +
fabs(mat[4 + l]) +
fabs(mat[8 + l]);
264 currentLine = stream.readLine();
270 bool ok[3] = {
true,
true,
true};
271 mat[12] = tokens[0].toDouble(ok);
272 mat[13] = tokens[1].toDouble(ok + 1);
273 mat[14] = tokens[2].toDouble(ok + 2);
277 if (pDlg && !nprogress.
oneStep())
284 if (!useAltKeypoints &&
285 (importKeypoints || orthoRectifyImages || generateColoredDTM)) {
287 if (!keypointsCloud->
reserve(ptsCount)) {
288 delete keypointsCloud;
292 bool hasColors =
false;
293 if (importKeypoints) {
297 "[Bundler] Not enough memory to load colors!");
302 bool storeKeypoints = orthoRectifyImages ;
304 std::vector<bool> camUsage;
308 camUsage.resize(cameras.size(),
false);
309 }
catch (
const std::bad_alloc&) {
315 for (
unsigned i = 0; i < ptsCount; ++i) {
317 currentLine = stream.readLine();
318 if (currentLine.startsWith(
322 currentLine = stream.readLine();
323 if (currentLine.isEmpty()) {
324 delete keypointsCloud;
333 if (tokens.size() < 3) {
334 delete keypointsCloud;
338 bool ok[3] = {
true,
true,
true};
339 Pd.
x = tokens[0].toDouble(ok);
340 Pd.
y = tokens[1].toDouble(ok + 1);
341 Pd.
z = tokens[2].toDouble(ok + 2);
342 if (!ok[0] || !ok[1] || !ok[2]) {
343 delete keypointsCloud;
350 bool preserveCoordinateShift =
true;
353 if (preserveCoordinateShift) {
356 for (
size_t j = 0; j < cameras.size(); ++j) {
365 "[Bundler] Cloud has been recentered! "
366 "Translation: (%.2f ; %.2f ; %.2f)",
367 Pshift.
x, Pshift.
y, Pshift.
z);
373 currentLine = stream.readLine();
374 if (currentLine.isEmpty()) {
375 delete keypointsCloud;
378 QStringList colorParts =
380 if (colorParts.size() == 3) {
382 QStringList tokens = currentLine.split(
384 if (tokens.size() < 3) {
385 delete keypointsCloud;
388 int R = tokens[0].toInt();
389 int G = tokens[1].toInt();
390 int B = tokens[2].toInt();
400 currentLine = stream.readLine();
401 }
else if (colorParts.size() > 3) {
406 "[Bundler] Keypoint #%i has no associated color!",
412 delete keypointsCloud;
417 if (currentLine.isEmpty()) {
418 delete keypointsCloud;
422 if (storeKeypoints || !camUsage.empty()) {
425 if (!parts.isEmpty()) {
427 unsigned nviews = parts[0].toInt(&ok);
428 if (!ok || nviews * 4 + 1 >
static_cast<unsigned>(
431 "[Bundler] View list for point #%i is "
436 for (
unsigned n = 0; n < nviews; ++n) {
437 int cam = parts[pos++].toInt();
443 static_cast<unsigned>(cam) >= camCount) {
447 if (!camUsage.empty()) {
448 camUsage[cam] =
true;
450 if (storeKeypoints) {
464 KeypointAndCamIndex lastKeyPoint;
466 static_cast<unsigned>(cam);
467 lastKeyPoint.second.index = i;
468 lastKeyPoint.second.x =
475 lastKeyPoint.second.y =
482 keypointsDescriptors.push_back(
484 }
catch (
const std::bad_alloc&) {
486 "[Bundler] Not enough memory "
487 "to store keypoints!");
488 keypointsDescriptors.clear();
489 orthoRectifyImages =
false;
490 storeKeypoints =
false;
498 if (pDlg && !nprogress.
oneStep())
500 delete keypointsCloud;
505 if (!camUsage.empty()) {
506 for (
size_t i = 0; i < camUsage.size(); ++i) {
509 "associated keypoints!")
515 if (applyOptMatrix) {
519 "[Bundler] Keypoints cloud has been transformed with "
525 if (importKeypoints) container.
addChild(keypointsCloud);
530 QApplication::processEvents();
535 if (useAltKeypoints) {
539 altKeypointsFilename, altKeypointsParams,
result);
540 if (!altKeypointsContainer ||
545 if (!altKeypointsContainer)
546 CVLog::Error(QString(
"[Bundler] Failed to load alternative "
547 "keypoints file:\n'%1'")
548 .arg(altKeypointsFilename));
551 "[Bundler] Can't use this kind of entities as "
552 "keypoints (need one and only one cloud or mesh)");
556 altEntity = altKeypointsContainer->
getChild(0);
557 if (importKeypoints) container.
addChild(altEntity);
563 assert(camCount > 0);
571 QStringList imageFilenames;
573 imageFilenames.clear();
574 QFile imageListFile(imageListFilename);
575 if (!imageListFile.exists() ||
576 !imageListFile.open(QIODevice::ReadOnly)) {
578 QString(
"[Bundler] Failed to open image list file! (%1)")
579 .arg(imageListFilename));
580 if (!importKeypoints && keypointsCloud)
delete keypointsCloud;
581 if (!importKeypoints && altEntity)
delete altEntity;
586 imageDir = QFileInfo(imageListFile).dir();
587 QTextStream imageListStream(&imageListFile);
589 for (
unsigned lineIndex = 0; lineIndex < camCount; ++lineIndex) {
590 QString nextLine = imageListStream.readLine();
591 if (nextLine.isEmpty())
break;
595 if (parts.size() > 0)
596 imageFilenames << parts[0];
598 CVLog::Error(QString(
"[Bundler] Couldn't extract image name "
599 "from line %1 in file '%2'!")
601 .arg(imageListFilename));
607 if (imageFilenames.size() <
608 static_cast<int>(camCount))
610 if (imageFilenames.isEmpty())
611 CVLog::Error(QString(
"[Bundler] No filename could be extracted "
613 .arg(imageListFilename));
615 CVLog::Error(QString(
"[Bundler] Only %1 filenames (out of %2) "
616 "could be extracted\nfrom file '%3'!")
617 .arg(imageFilenames.size())
619 .arg(imageListFilename));
620 if (!importKeypoints && keypointsCloud)
delete keypointsCloud;
621 if (!importKeypoints && altEntity)
delete altEntity;
626 QScopedPointer<ecvProgressDialog> ipDlg(0);
630 ipDlg->setMethodTitle(QObject::tr(
"Open & process images"));
631 ipDlg->setInfo(QObject::tr(
"Images: %1").arg(camCount));
633 QApplication::processEvents();
637 assert(imageFilenames.size() >=
static_cast<int>(camCount));
642 int* mntColors =
nullptr;
644 if (generateColoredDTM) {
645 QScopedPointer<ecvProgressDialog> toDlg(0);
649 toDlg->setMethodTitle(QObject::tr(
"Preparing colored DTM"));
651 QApplication::processEvents();
663 std::string errorStr;
665 altKeypoints ? altKeypoints : keypointsCloud,
669 .arg(QString::fromStdString(errorStr)));
677 coloredDTMVerticesCount);
678 if (!baseDTMMesh)
delete dummyMesh;
685 mntColors =
new int[4 *
count];
689 "Not enough memory to store DTM colors! DTM "
690 "generation cancelled");
693 generateColoredDTM =
false;
695 memset(mntColors, 0,
sizeof(
int) * 4 *
count);
701 std::vector<ORImageInfo> OR_infos;
702 double OR_pixelSize = -1.0;
703 double OR_globalCorners[4] = {0, 0, 0, 0};
707 if (orthoRectifyImages) {
711 _keypointsCloud = (altKeypoints ? altKeypoints : keypointsCloud);
716 bool cancelledByUser =
false;
717 for (
unsigned i = 0; i < camCount; ++i) {
723 if (!
image->load(imageDir.absoluteFilePath(imageFilenames[i]),
726 .arg(errorStr, imageFilenames[i]));
732 image->setName(imageFilenames[i]);
733 image->setEnabled(
false);
734 image->setAlpha(0.75f);
740 params.arrayWidth =
static_cast<int>(
image->getW());
741 params.arrayHeight =
static_cast<int>(
image->getH());
753 ccGLMatrix transf(cameras[i].trans.inverse().data());
765 sensor->
setName(QString(
"Camera #%1").arg(i + 1));
775 if (cameras[i].k1 != 0 || cameras[i].k2 != 0) {
778 distParams->
k1 = cameras[i].k1;
779 distParams->
k2 = cameras[i].k2;
786 if (applyOptMatrix) {
795 image->setAssociatedSensor(sensor);
799 if (orthoRectifyImages) {
800 assert(sensor && _keypointsCloud);
803 std::vector<ccCameraSensor::KeyPoint> keypointsImage;
805 if (_keypointsCloud ==
808 for (std::vector<KeypointAndCamIndex>::const_iterator key =
809 keypointsDescriptors.begin();
810 key != keypointsDescriptors.end(); ++key) {
811 if (key->first == i) {
812 keypointsImage.push_back(key->second);
813 keypointsImageBB.
add(
814 CCVector3(key->second.x, key->second.y, 0));
819 _keypointsCloud->placeIteratorAtBeginning();
820 int half_w = (
image->getW() >> 1);
821 int half_h = (
image->getH() >> 1);
823 unsigned keyptsCount = _keypointsCloud->size();
824 for (
unsigned k = 0; k < keyptsCount; ++k) {
825 CCVector3 P(*_keypointsCloud->getPointPersistentPtr(k));
829 kp.
x = -cam.
f_pix *
static_cast<float>(P.
x / P.
z);
830 kp.
y = cam.
f_pix *
static_cast<float>(P.
y / P.
z);
831 if (
static_cast<int>(kp.
x) > -half_w &&
832 static_cast<int>(kp.
x < half_w) &&
833 static_cast<int>(kp.
y) > -half_h &&
834 static_cast<int>(kp.
y < half_h)) {
836 keypointsImage.push_back(kp);
842 if (keypointsImage.size() < 4) {
844 "descriptors for image '%1'!")
845 .arg(
image->getName()));
846 }
else if (!keypointsImageBB.
isValid() ||
849 QString(
"[Bundler] Keypoints descriptors for image "
850 "'%1' are invalid (= all the same)")
851 .arg(
image->getName()));
853 if (orthoRectifyImagesAsImages) {
862 image, _keypointsCloud, keypointsImage,
863 OR_pixelSize, info.
minC, info.
maxC, corners);
873 _keypointsCloud->getBoundingBox(bbMin, bbMax);
877 image, Z0, OR_pixelSize,
884 assert(!orthoImage->
data().isNull());
885 info.
name = QString(
"ortho_%1.png")
886 .arg(QFileInfo(imageFilenames[i])
888 info.
w = orthoImage->
getW();
889 info.
h = orthoImage->
getH();
890 orthoImage->
data().save(
891 imageDir.absoluteFilePath(info.
name));
893 QString(
"[Bundler] Ortho-rectified version of "
894 "image '%1' (%2 x %3) saved to '%4'")
895 .arg(imageFilenames[i])
898 .arg(imageDir.absoluteFilePath(
901 #ifdef TEST_TEXTURED_BUNDLER_IMPORT
905 #define TBI_DEFAULT_TILE_POW 10
906 const unsigned tileDim = (1 << TBI_DEFAULT_TILE_POW);
907 unsigned horiTile = (info.
w >> TBI_DEFAULT_TILE_POW);
908 if (info.
w - horiTile * tileDim != 0) ++horiTile;
909 unsigned vertTile = (info.
h >> TBI_DEFAULT_TILE_POW);
910 if (info.
h - vertTile * tileDim != 0) ++vertTile;
911 unsigned tiles = horiTile * vertTile;
912 unsigned verts = (horiTile + 1) * (vertTile + 1);
931 texCoords->reserve(4);
937 float TA[2] = {minu, minu};
938 float TB[2] = {maxu, minu};
939 float TC[2] = {maxu, maxu};
940 float TD[2] = {minu, maxu};
952 double dcx = info.
maxC[0] - info.
minC[0];
953 double dcy = info.
maxC[1] - info.
minC[1];
956 for (
unsigned ti = 0; ti <= horiTile; ++ti) {
957 unsigned x =
std::min(ti * tileDim, info.
w);
958 double xRel =
static_cast<double>(x) / info.
w;
959 for (
unsigned tj = 0; tj <= vertTile; ++tj) {
960 unsigned y =
std::min(tj * tileDim, info.
h);
961 double yRel =
static_cast<double>(y) / info.
h;
965 info.
maxC[1] - dcy * yRel, 0);
972 if (ti < horiTile && tj < vertTile) {
973 unsigned w =
std::min(info.
w - x, tileDim);
974 unsigned h =
std::min(info.
h - y, tileDim);
977 unsigned tileIndex = matSet->size();
979 matSet->back().texture =
980 orthoImage->
data().copy(x, y, w, h);
983 unsigned iA = ti * (vertTile + 1) + tj;
985 (ti + 1) * (vertTile + 1) + tj;
986 unsigned iC = iB + 1;
987 unsigned iD = iA + 1;
1016 OR_infos.push_back(info);
1019 if (OR_globalCorners[0] > info.
minC[0])
1020 OR_globalCorners[0] = info.
minC[0];
1021 if (OR_globalCorners[1] > info.
minC[1])
1022 OR_globalCorners[1] = info.
minC[1];
1023 if (OR_globalCorners[2] < info.
maxC[0])
1024 OR_globalCorners[2] = info.
maxC[0];
1025 if (OR_globalCorners[3] < info.
maxC[1])
1026 OR_globalCorners[3] = info.
maxC[1];
1029 "ortho-rectify image '%1'!")
1030 .arg(
image->getName()));
1034 if (orthoRectifyImagesAsClouds) {
1036 image, _keypointsCloud, keypointsImage);
1039 _keypointsCloud->getGlobalScale());
1041 _keypointsCloud->getGlobalShift());
1045 QString(
"[Bundler] Failed to ortho-rectify "
1046 "image '%1' as a cloud!")
1047 .arg(
image->getName()));
1054 if (sensor && undistortImages)
1057 QString(
"[Bundler] Failed to undistort image '%1'!")
1058 .arg(
image->getName()));
1061 if (sensor && generateColoredDTM) {
1062 assert(mntSamples && mntColors);
1063 unsigned sampleCount = mntSamples->
size();
1064 const QRgb blackValue = qRgb(0, 0, 0);
1070 for (
unsigned k = 0; k < sampleCount; ++k) {
1074 sensorMatrix.
apply(P);
1083 int px =
static_cast<int>(
image->getW() / 2.0f + pprime.
x);
1084 if (px >= 0 && px <
static_cast<int>(
image->getW())) {
1085 int py =
static_cast<int>(
image->getH() / 2.0f -
1087 if (
py >= 0 &&
py <
static_cast<int>(
image->getH())) {
1088 QRgb rgb =
image->data().pixel(px,
py);
1089 if (qAlpha(rgb) != 0 &&
1092 int* col = mntColors + 4 * k;
1093 col[0] += qRed(rgb);
1094 col[1] += qGreen(rgb);
1095 col[2] += qBlue(rgb);
1104 if (keepImagesInMemory) {
1111 QApplication::processEvents();
1113 if (ipDlg && !inprogress.
oneStep()) {
1114 cancelledByUser =
true;
1119 if (!importKeypoints && keypointsCloud)
delete keypointsCloud;
1122 if (!importKeypoints && altEntity)
delete altEntity;
1127 if (orthoRectifyImages && OR_pixelSize > 0) {
1129 QFile f(imageDir.absoluteFilePath(
"ortho_rectification_log.txt"));
1130 if (f.open(QIODevice::WriteOnly | QIODevice::Text)) {
1131 QTextStream stream(&f);
1132 stream.setRealNumberNotation(QTextStream::FixedNotation);
1133 stream.setRealNumberPrecision(12);
1135 stream <<
"Global3DBBox" <<
' ' << OR_globalCorners[0] <<
' '
1136 << OR_globalCorners[1] <<
' ' << OR_globalCorners[2] <<
' '
1138 int globalWidth =
static_cast<int>(
1139 (OR_globalCorners[2] - OR_globalCorners[0]) / OR_pixelSize);
1140 int globalHeight =
static_cast<int>(
1141 (OR_globalCorners[3] - OR_globalCorners[1]) / OR_pixelSize);
1142 stream <<
"Global2DBBox" <<
' ' << 0 <<
' ' << 0 <<
' '
1143 << globalWidth - 1 <<
' ' << globalHeight - 1
1146 for (
unsigned i = 0; i < OR_infos.size(); ++i) {
1147 stream <<
"Image" <<
' ' << OR_infos[i].name <<
' ';
1148 stream <<
"Local3DBBox" <<
' ' << OR_infos[i].minC[0] <<
' '
1149 << OR_infos[i].minC[1] <<
' ' << OR_infos[i].maxC[0]
1150 <<
' ' << OR_infos[i].maxC[1] <<
' ';
1151 int xShiftGlobal =
static_cast<int>(
1152 (OR_infos[i].minC[0] - OR_globalCorners[0]) /
1154 int yShiftGlobal =
static_cast<int>(
1155 (OR_globalCorners[3] - OR_infos[i].maxC[1]) /
1157 stream <<
"Local2DBBox" <<
' ' << xShiftGlobal <<
' '
1158 << yShiftGlobal <<
' '
1159 << xShiftGlobal + (
static_cast<int>(OR_infos[i].w) - 1)
1161 << yShiftGlobal + (
static_cast<int>(OR_infos[i].h) - 1)
1166 "Failed to save orthorectification log file! "
1167 "(ortho_rectification_log.txt)");
1171 if (generateColoredDTM) {
1172 assert(mntSamples && mntColors);
1174 if (!cancelledByUser) {
1176 unsigned sampleCount = mntSamples->
size();
1179 if (mntCloud->
reserve(sampleCount) &&
1182 unsigned realCount = 0;
1183 const int* col = mntColors;
1184 for (
unsigned i = 0; i < sampleCount; ++i, col += 4) {
1199 if (realCount != 0) {
1200 if (realCount < sampleCount) mntCloud->
resize(realCount);
1205 "[Bundler] DTM vertices successfully generated: "
1206 "clean it if necessary then use 'Edit > Mesh > "
1207 "Compute Delaunay 2D (Best LS plane)' then "
1208 "'Smooth' to get a proper mesh");
1213 QString outputFile = imageDir.absoluteFilePath(
1214 "colored_dtm_vertices.bin");
1217 if (bf.
saveToFile(mntCloud, outputFile, parameters) ==
1220 "automatically saved to '%2'")
1224 "DTM vertices to '%2'")
1229 "[Bundler] Failed to generate DTM! (no point "
1230 "viewed in images?)");
1234 "[Bundler] Failed to generate DTM vertices cloud! (not "
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
std::shared_ptr< core::Tensor > image
CC_FILE_ERROR
Typical I/O filter errors.
@ CC_FERR_CANCELED_BY_USER
@ CC_FERR_NOT_ENOUGH_MEMORY
@ CC_FERR_WRONG_FILE_TYPE
QStringList qtCompatSplitRegex(const QString &str, const QString &pattern, Qt::SplitBehavior behavior=Qt::KeepEmptyParts)
cmdLineReadable * params[]
CLOUDVIEWER dedicated binary point cloud I/O filter.
virtual CC_FILE_ERROR saveToFile(ccHObject *entity, const QString &filename, const SaveParameters ¶meters) override
Saves an entity (or a group of) to a file.
CC_FILE_ERROR loadFileExtended(const QString &filename, ccHObject &container, LoadParameters ¶meters, const QString &altKeypointsFilename=QString(), bool undistortImages=false, bool generateColoredDTM=false, unsigned coloredDTMVerticesCount=1000000, float scaleFactor=1.0f)
Specific load method.
virtual CC_FILE_ERROR loadFile(const QString &filename, ccHObject &container, LoadParameters ¶meters) override
Loads one or more entities from a file.
Dialog for importation of Snavely's Bundler files.
bool importImages() const
Returns whether images should be imported.
bool orthoRectifyImagesAsImages() const
Returns whether images should be ortho-rectified as images.
bool getOptionalTransfoMatrix(ccGLMatrix &mat)
Returns the optional transformation matrix (if defined)
bool importKeypoints() const
Returns whether keypoints should be imported.
unsigned getDTMVerticesCount() const
Returns desired number of vertices for DTM.
bool keepImagesInMemory() const
Returns images should be kept in memory or not.
QString getAltKeypointsFilename() const
Gets alternative keypoints filename (full path)
void setImageListFilename(const QString &filename)
Sets default image list filename (full path)
bool orthoRectifyImagesAsClouds() const
Returns whether images should be ortho-rectified as clouds.
void setVer(unsigned majorVer, unsigned minorVer)
Sets file version on initialization.
OrthoRectMethod getOrthorectificationMethod() const
Returns the ortho-rectification method (for images)
bool useAlternativeKeypoints() const
Returns whether alternative keypoints should be used.
void setCamerasCount(unsigned count)
Sets cameras count on initialization.
double getScaleFactor() const
Returns scale factor.
bool undistortImages() const
Returns whether images should be undistorted.
bool generateColoredDTM() const
Returns whether colored pseudo-DTM should be generated.
void setAltKeypointsFilename(const QString &filename)
Sets default alternative keypoints filename (full path)
void setKeypointsCount(unsigned count)
Sets keypoints count on initialization.
OrthoRectMethod
Image ortho-rectification methods.
QString getImageListFilename() const
Gets image list filename (full path)
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
static constexpr float DEFAULT_PRIORITY
static ccHObject * LoadFromFile(const QString &filename, LoadParameters ¶meters, Shared filter, CC_FILE_ERROR &result)
Loads one or more entities from a file with a known filter.
static bool HandleGlobalShift(const CCVector3d &P, CCVector3d &Pshift, bool &preserveCoordinateShift, LoadParameters &loadParameters, bool useInputCoordinatesShiftIfPossible=false)
Shortcut to the ecvGlobalShiftManager mechanism specific for files.
Array of 2D texture coordinates.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
void addElement(const Type &value)
Camera (projective) sensor.
ccImage * orthoRectifyAsImage(const ccImage *image, cloudViewer::GenericIndexedCloud *keypoints3D, std::vector< KeyPoint > &keypointsImage, double &pixelSize, double *minCorner=nullptr, double *maxCorner=nullptr, double *realCorners=nullptr) const
Projective ortho-rectification of an image (as image)
ccPointCloud * orthoRectifyAsCloud(const ccImage *image, cloudViewer::GenericIndexedCloud *keypoints3D, std::vector< KeyPoint > &keypointsImage) const
Projective ortho-rectification of an image (as cloud)
ccImage * orthoRectifyAsImageDirect(const ccImage *image, PointCoordinateType altitude, double &pixelSize, bool undistortImages=true, double *minCorner=nullptr, double *maxCorner=nullptr, double *realCorners=nullptr) const
Direct ortho-rectification of an image (as image)
static float ComputeFovRadFromFocalPix(float focal_pix, int imageSize_pix)
Helper: deduces camera f.o.v. (in radians) from focal (in pixels)
QImage undistort(const QImage &image) const
Undistorts an image based on the sensor distortion parameters.
void setDistortionParameters(LensDistortionParameters::Shared params)
Sets uncertainty parameters.
virtual void setVisible(bool state)
Sets entity visibility.
virtual void showColors(bool state)
Sets colors visibility.
Vector3Tpl< T > getTranslationAsVec3D() const
Returns a copy of the translation as a CCVector3.
void invert()
Inverts transformation.
ccGLMatrixTpl< T > inverse() const
Returns inverse transformation.
void apply(float vec[3]) const
Applies transformation to a 3D vector (in place) - float version.
void setTranslation(const Vector3Tpl< float > &Tr)
Sets translation (float version)
virtual void toIdentity()
Sets matrix to identity.
Float version of ccGLMatrixTpl.
Double version of ccGLMatrixTpl.
virtual void showMaterials(bool state)
Sets whether textures should be displayed or not.
A 3D cloud interface with associated features (color, normals, octree, etc.)
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
static ccGenericPointCloud * ToGenericPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccGenericPointCloud.
static ccGenericMesh * ToGenericMesh(ccHObject *obj)
Converts current object to ccGenericMesh (if possible)
Hierarchical CLOUDVIEWER Object.
void applyGLTransformation_recursive(const ccGLMatrix *trans=nullptr)
Applies the active OpenGL transformation to the entity (recursive)
unsigned getChildrenNumber() const
Returns the number of children.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
unsigned getW() const
Returns image width.
unsigned getH() const
Returns image height.
QImage & data()
Returns image data.
Mesh (triangle) material.
Mesh (triangle) material.
bool reservePerTriangleMtlIndexes()
Reserves memory to store per-triangle material index.
void addTriangleMtlIndex(int mtlIndex)
Adds triangle material index for next triangle.
void setMaterialSet(ccMaterialSet *materialSet, bool autoReleaseOldMaterialSet=true)
Sets associated material set (may be shared)
bool reserve(std::size_t n)
Reserves the memory to store the vertex indexes (3 per triangle)
void addTriangleTexCoordIndexes(int i1, int i2, int i3)
Adds a triplet of tex coords indexes for next triangle.
void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
void setTexCoordinatesTable(TextureCoordsContainer *texCoordsTable, bool autoReleaseOldTable=true)
Sets per-triangle texture coordinates array (may be shared)
bool reservePerTriangleTexCoordIndexes()
Reserves memory to store per-triangle triplets of tex coords indexes.
virtual void setName(const QString &name)
Sets object name.
virtual void setEnabled(bool state)
Sets the "enabled" property.
bool isKindOf(CV_CLASS_ENUM type) const
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
bool resize(unsigned numberOfPoints) override
Resizes all the active features arrays.
void addRGBColor(const ecvColor::Rgb &C)
Pushes an RGB color on stack.
virtual ccGLMatrix & getRigidTransformation()
virtual void setRigidTransformation(const ccGLMatrix &mat)
void setGraphicScale(PointCoordinateType scale)
Sets the sensor graphic representation scale.
virtual void setGlobalScale(double scale)
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
Vector3Tpl< T > getCenter() const
Returns center.
T getDiagNorm() const
Returns diagonal length.
bool isValid() const
Returns whether bounding box is valid or not.
void add(const Vector3Tpl< T > &P)
'Enlarges' the bounding box with a point
A generic mesh with index-based vertex access.
bool oneStep()
Increments total progress value of a single unit.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
const CCVector3 * getPointPersistentPtr(unsigned index) override
unsigned size() const override
Graphical progress indicator (thread-safe)
__host__ __device__ float2 fabs(float2 v)
unsigned char ColorCompType
Default color components type (R,G and B)
static double dist(double x1, double y1, double x2, double y2)
constexpr QRegularExpression::PatternOption CaseInsensitive
constexpr Qt::SplitBehavior SkipEmptyParts
QTextStream & endl(QTextStream &stream)
bool GreaterThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
@ DELAUNAY_2D_BEST_LS_PLANE
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
constexpr ColorCompType MAX
Max value of a single color component (default type)
float k2
Second radial distortion coef.
float f_pix
focal (in pixels)
float k1
First radial distortion coef.
ccGLMatrixd trans
Rotation + translation.
BundlerCamera()
Default constructor.
Generic loading parameters.
QWidget * parentWidget
Parent widget (if any)
bool alwaysDisplayLoadDialog
Generic saving parameters.
bool alwaysDisplaySaveDialog
Intrinsic parameters of the camera sensor.
unsigned index
Index in associated point cloud.
float y
2D 'y' coordinate (in pixels)
float x
2D 'x' coordinate (in pixels)
QSharedPointer< LensDistortionParameters > Shared
Shared pointer type.
Simple radial distortion model.
float k2
2nd radial distortion coefficient
float k1
1st radial distortion coefficient