We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
okay'ish positions but rotation still off
#include <gflags/gflags.h> #include <Eigen/Dense> #include <Eigen/Geometry> #include <algorithm> #include <cmath> #include <fstream> #include <iomanip> #include <iostream> #include <map> #include <opencv2/core.hpp> #include <opencv2/opencv.hpp> #include <set> #include <sstream> #include <string> #include <unordered_map> #include <vector> #include "algo/lm_algo.h" #include "edge/base_edge.h" #include "geo/geo.cuh" #include "linear_system/schur_LM_linear_system.h" #include "problem/base_problem.h" #include "solver/schur_pcg_solver.h" #include "vertex/base_vertex.h" using namespace Eigen; // Define M_PI if not defined #ifndef M_PI #define M_PI 3.14159265358979323846 #endif // Structs to hold parsed data struct Camera { int id = 0; std::string model = ""; int width = 0; int height = 0; std::vector<double> params; double fx = 0.0; double fy = 0.0; double cx = 0.0; double cy = 0.0; double k1 = 0.0; double k2 = 0.0; }; struct Image { int id = 0; Eigen::Quaterniond quaternion; Eigen::Vector3d translation; int camera_id = 0; std::string name = ""; std::vector<Eigen::Vector2d> keypoints; std::vector<int> point3D_ids; int width = 0; int height = 0; double fx = 0.0; double fy = 0.0; double cx = 0.0; double cy = 0.0; double k1 = 0.0; double k2 = 0.0; }; struct Point3D { int id = 0; Eigen::Vector3d position = Eigen::Vector3d::Zero(); Eigen::Vector3i color = Eigen::Vector3i::Zero(); double error = 0.0; std::vector<std::pair<int, int>> observations; }; struct Observation { int image_id; int point3D_id; Eigen::Vector2d keypoint; // For sorting bool operator<(const Observation& other) const { if (point3D_id != other.point3D_id) return point3D_id < other.point3D_id; return image_id < other.image_id; } }; // Function prototypes bool readCameras(const std::string& path, std::vector<Camera>& cameras); bool readImages(const std::string& path, std::vector<Image>& images, const std::vector<Camera>& cameras, int& nameCount); bool readPoints3D(const std::string& path, std::vector<Point3D>& points3D); int countPoints3D(const std::vector<Point3D>& points3D); int countObservations(const std::vector<Point3D>& points3D); void generateSummary(int nameCount, int numPoints3D, int numObservations, std::ostringstream& summaryOutput); std::vector<Observation> collectObservations( const std::vector<Image>& images, const std::vector<Point3D>& points3D); void generateObservations(const std::vector<Observation>& observations, std::ostringstream& observationsOutput); void generateCameraDetails(const std::vector<Image>& images, const std::vector<Camera>& cameras, std::ostringstream& cameraDetailsOutput); void generatePoints3D(const std::vector<Point3D>& points3D, std::ostringstream& points3DOutput); void renumberPoint3DIds(std::vector<Observation>& observations); void saveToFile(const std::string& summaryPath, const std::string& observationsPath, const std::string& cameraDetailsPath, const std::string& points3DPath, const std::ostringstream& summaryOutput, const std::ostringstream& observationsOutput, const std::ostringstream& cameraDetailsOutput, const std::ostringstream& points3DOutput); bool readCameras(const std::string& path, std::vector<Camera>& cameras) { std::ifstream fin(path); if (!fin) { std::cerr << "Error opening file: " << path << std::endl; return false; } std::string line; while (std::getline(fin, line)) { if (line.empty() || line[0] == '#') continue; std::istringstream iss(line); Camera cam; iss >> cam.id >> cam.model >> cam.width >> cam.height; cam.params.assign(std::istream_iterator<double>(iss), std::istream_iterator<double>()); // Set default values if parameters are missing cam.fx = (cam.params.size() > 0) ? cam.params[0] : 1000.0; cam.fy = (cam.params.size() > 1) ? cam.params[1] : cam.fx; cam.cx = (cam.params.size() > 2) ? cam.params[2] : cam.width / 2.0; cam.cy = (cam.params.size() > 3) ? cam.params[3] : cam.height / 2.0; cam.k1 = (cam.params.size() > 4) ? cam.params[4] : 0.0; cam.k2 = (cam.params.size() > 5) ? cam.params[5] : 0.0; cameras.push_back(cam); } return true; } // Funkcja czytająca obrazy z pliku bool readImages(const std::string& path, std::vector<Image>& images, const std::vector<Camera>& cameras, int& nameCount) { std::ifstream fin(path); if (!fin) { std::cerr << "Error opening file: " << path << std::endl; return false; } std::string line; std::set<std::string> uniqueNames; while (std::getline(fin, line)) { if (line.empty() || line[0] == '#') continue; std::istringstream iss(line); Image img; double qw, qx, qy, qz; // Read quaternion components iss >> img.id >> qw >> qx >> qy >> qz; img.quaternion = Eigen::Quaterniond(qw, qx, qy, qz); // Store the quaternion in the img object iss >> img.translation.x() >> img.translation.y() >> img.translation.z(); iss >> img.camera_id; iss >> img.name; uniqueNames.insert(img.name); // Przeczytaj kluczowe punkty std::string keypoints_line; if (std::getline(fin, keypoints_line)) { std::istringstream keypoints_iss(keypoints_line); double x, y; int pt3d_id; while (keypoints_iss >> x >> y >> pt3d_id) { img.keypoints.emplace_back(x, y); img.point3D_ids.push_back(pt3d_id); } } // Pobierz parametry kamery i ustaw domyślne, jeśli to konieczne auto it = std::find_if(cameras.begin(), cameras.end(), [camera_id = img.camera_id](const Camera& cam) { return cam.id == camera_id; }); if (it != cameras.end()) { const Camera& cam = *it; img.fx = (cam.params.size() > 0) ? cam.params[0] : 1000.0; img.fy = (cam.params.size() > 1) ? cam.params[1] : img.fx; img.cx = (cam.params.size() > 2) ? cam.params[2] : 1920; // Przykład szerokości obrazu img.cy = (cam.params.size() > 3) ? cam.params[3] : 1080; // Przykład wysokości obrazu img.k1 = (cam.params.size() > 4) ? cam.params[4] : 0.0; img.k2 = (cam.params.size() > 5) ? cam.params[5] : 0.0; } else { img.fx = img.fy = img.cx = img.cy = img.k1 = img.k2 = 0.0; } images.push_back(img); } nameCount = static_cast<int>(uniqueNames.size()); return true; } bool readPoints3D(const std::string& path, std::vector<Point3D>& points3D) { std::ifstream fin(path); if (!fin) { std::cerr << "Error opening file: " << path << std::endl; return false; } std::string line; while (std::getline(fin, line)) { if (line.empty() || line[0] == '#') continue; std::istringstream iss(line); Point3D pt3d; iss >> pt3d.id >> pt3d.position.x() >> pt3d.position.y() >> pt3d.position.z(); int image_id, keypoint_index; while (iss >> image_id >> keypoint_index) { pt3d.observations.emplace_back(image_id, keypoint_index); } points3D.push_back(pt3d); } return true; } int countPoints3D(const std::vector<Point3D>& points3D) { return static_cast<int>(points3D.size()); } int countObservations(const std::vector<Observation>& observations) { return static_cast<int>(observations.size()); } void generateSummary(int nameCount, int numPoints3D, int numObservations, std::ostringstream& summaryOutput) { summaryOutput << nameCount << ' ' << numPoints3D << ' ' << numObservations; } std::vector<Observation> collectObservations( const std::vector<Image>& images, const std::vector<Point3D>& points3D) { std::vector<Observation> observations; for (const auto& image : images) { for (size_t i = 0; i < image.keypoints.size(); ++i) { const auto& pt3D_id = image.point3D_ids[i]; if (pt3D_id >= 0 && pt3D_id < points3D.size()) { observations.push_back({image.id, pt3D_id, image.keypoints[i]}); } } } return observations; } void generateObservations(const std::vector<Observation>& observations, std::ostringstream& observationsOutput, const std::vector<Image>& images) { for (const auto& observation : observations) { const auto& image = images[observation.image_id]; // Przesunięcie współrzędnych o cx i cy double adjusted_x = observation.keypoint.x(); double adjusted_y = observation.keypoint.y(); // Decrement image_id by 1 (jeśli jest to wymagane przez format wyjściowy) observationsOutput << (observation.image_id - 1) << ' ' << observation.point3D_id << ' ' << adjusted_x << ' ' << adjusted_y << '\n'; } } using namespace cv; using namespace std; // Define the function to convert Rodrigues' rotation vector to a rotation // matrix Eigen::Matrix3d fromRodrigues(const Eigen::Vector3d& x) { double theta2 = x.squaredNorm(); if (theta2 > std::numeric_limits<double>::epsilon()) { double angle = x.norm(); Eigen::Vector3d axis = x.normalized(); Eigen::AngleAxisd rotation(angle, axis); return rotation.toRotationMatrix(); } else { // Taylor series approximation from ceres-solver Eigen::Matrix3d rotation; rotation << 1.0, x.z(), -x.y(), -x.z(), 1.0, x.x(), x.y(), -x.x(), 1.0; return rotation; } } // Function to convert rotation matrix to quaternion Eigen::Quaternion<double> rotationMatrixToQuaternion( const Eigen::Matrix3d& rotation) { return Eigen::Quaternion<double>(rotation); } Vector3d QuaternionToRodrigues(const Quaterniond& quat) { // Krok 1: Konwertuj kwaternion na macierz rotacji Matrix3d rotationMatrix = quat.toRotationMatrix(); // Krok 2: Oblicz wektor Rodrigueza z macierzy rotacji // Wektor Rodrigueza jest definiowany przez cosinus kąta rotacji oraz oś // rotacji Vector3d rodrigues; double angle = acos((rotationMatrix.trace() - 1) / 2.0); if (angle != 0) { double sin_angle = sin(angle); rodrigues(0) = (rotationMatrix(2, 1) - rotationMatrix(1, 2)) / (2 * sin_angle); rodrigues(1) = (rotationMatrix(0, 2) - rotationMatrix(2, 0)) / (2 * sin_angle); rodrigues(2) = (rotationMatrix(1, 0) - rotationMatrix(0, 1)) / (2 * sin_angle); rodrigues *= angle; } else { rodrigues << 0, 0, 0; } return rodrigues; } void cvMatToEigen(const cv::Mat& cvMat, Eigen::Matrix3d& eigenMat) { assert(cvMat.rows == 3 && cvMat.cols == 3 && cvMat.type() == CV_64F); // Kopiuj wartości z cv::Mat do Eigen::Matrix3d for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { eigenMat(i, j) = cvMat.at<double>(i, j); } } } // Function to convert Eigen quaternion to (w, x, y, z) format void quaternionToWXYZ(const Eigen::Quaterniond& quat, double& w, double& x, double& y, double& z) { w = quat.w(); x = quat.x(); y = quat.y(); z = quat.z(); } template <typename T> T clamp(T value, T low, T high) { return (value < low) ? low : (value > high) ? high : value; } // Function to generate camera details void generateCameraDetails(const vector<Image>& images, const vector<Camera>& cameras, ostringstream& cameraDetailsOutput) { unordered_map<int, string> imageIdToName; for (const auto& image : images) { imageIdToName[image.id] = image.name; } unordered_map<int, int> idMap; int newId = 0; for (const auto& image : images) { idMap[image.id] = newId++; } unordered_map<int, Camera> cameraMap; for (const auto& cam : cameras) { cameraMap[cam.id] = cam; } for (const auto& image : images) { int newImageId = idMap[image.id]; const auto& cam = cameraMap[image.camera_id]; Quaterniond quat(image.quaternion); Matrix3d rotationMatrix = quat.toRotationMatrix(); Matrix4d w2c = Matrix4d::Identity(); w2c.block<3, 3>(0, 0) = rotationMatrix; w2c.block<3, 1>(0, 3) = image.translation; Matrix4d c2w = w2c.inverse(); Vector3d translationFromMatrix = c2w.block<3, 1>(0, 3); Matrix3d rotationMatrixWorld = c2w.block<3, 3>(0, 0); Vector3d rodrigues = QuaternionToRodrigues(quat); cameraDetailsOutput << rodrigues[0] << '\n' << rodrigues[1] << '\n' << rodrigues[2] << '\n' << translationFromMatrix[0] << '\n' << translationFromMatrix[1] << '\n' << translationFromMatrix[2] << '\n' << (cam.fx + cam.fy) / 2.0 << '\n' << cam.k1 << '\n' << cam.k2 << '\n'; } } // Funkcja generująca punkty 3D void generatePoints3D(const std::vector<Point3D>& points3D, std::ostringstream& points3DOutput) { for (const auto& point3D : points3D) { Eigen::Vector3d position = point3D.position; points3DOutput << position.x() << '\n' << position.y() << '\n' << position.z() << '\n'; } } void saveToFile(const std::string& outputPath, const std::ostringstream& summaryOutput, const std::ostringstream& observationsOutput, const std::ostringstream& cameraDetailsOutput, const std::ostringstream& points3DOutput) { // Open the output file std::ofstream fout(outputPath); if (!fout) { std::cerr << "Error opening file for writing: " << outputPath << std::endl; return; } // Write summary fout << summaryOutput.str(); fout << std::endl; // Write observations fout << observationsOutput.str(); // Write camera details fout << cameraDetailsOutput.str(); // Write points3D fout << points3DOutput.str(); fout.close(); } void renumberPoint3DIds(std::vector<Observation>& observations) { std::unordered_map<int, int> oldToNewIdMap; int newId = 0; for (const auto& obs : observations) { if (oldToNewIdMap.find(obs.point3D_id) == oldToNewIdMap.end()) { oldToNewIdMap[obs.point3D_id] = newId++; } } for (auto& obs : observations) { obs.point3D_id = oldToNewIdMap[obs.point3D_id]; } } void saveToFile(const std::string& summaryPath, const std::string& observationsPath, const std::string& cameraDetailsPath, const std::string& points3DPath, const std::ostringstream& summaryOutput, const std::ostringstream& observationsOutput, const std::ostringstream& cameraDetailsOutput, const std::ostringstream& points3DOutput) { // Save summary std::ofstream summaryFile(summaryPath); if (summaryFile) { summaryFile << summaryOutput.str(); summaryFile.close(); } else { std::cerr << "Error opening file for writing: " << summaryPath << std::endl; } // Save observations std::ofstream observationsFile(observationsPath); if (observationsFile) { observationsFile << observationsOutput.str(); observationsFile.close(); } else { std::cerr << "Error opening file for writing: " << observationsPath << std::endl; } // Save camera details std::ofstream cameraDetailsFile(cameraDetailsPath); if (cameraDetailsFile) { cameraDetailsFile << cameraDetailsOutput.str(); cameraDetailsFile.close(); } else { std::cerr << "Error opening file for writing: " << cameraDetailsPath << std::endl; } // Save points3D std::ofstream points3DFile(points3DPath); if (points3DFile) { points3DFile << points3DOutput.str(); points3DFile.close(); } else { std::cerr << "Error opening file for writing: " << points3DPath << std::endl; } } template <typename T> class BAL_Edge : public MegBA::BaseEdge<T> { public: MegBA::JVD<T> forward() override { using MappedJVD = Eigen::Map<const MegBA::geo::JVD<T>>; const auto& Vertices = this->getVertices(); MappedJVD angle_axisd{&Vertices[0].getEstimation()(0, 0), 3, 1}; MappedJVD t{&Vertices[0].getEstimation()(3, 0), 3, 1}; MappedJVD intrinsics{&Vertices[0].getEstimation()(6, 0), 3, 1}; const auto& point_xyz = Vertices[1].getEstimation(); const auto& obs_uv = this->getMeasurement(); auto R = MegBA::geo::AngleAxisToRotationKernelMatrix(angle_axisd); Eigen::Matrix<MegBA::JetVector<T>, 3, 1> re_projection = R * point_xyz + t; re_projection = -re_projection / re_projection(2); // f, k1, k2 = intrinsics auto fr = MegBA::geo::RadialDistortion(re_projection, intrinsics); MegBA::JVD<T> error = fr * re_projection.head(2) - obs_uv; return error; } }; namespace { template <typename Derived> bool writeVector(std::ostream& os, const Eigen::DenseBase<Derived>& b) { for (int i = 0; i < b.size(); i++) os << b(i) << " "; return os.good(); } template <typename Derived> bool readVector(std::istream& is, Eigen::DenseBase<Derived>& b) { for (int i = 0; i < b.size() && is.good(); i++) is >> b(i); return is.good() || is.eof(); } } // namespace DEFINE_int32(world_size, 1, "World size"); DEFINE_string(out_path, "output.txt", "Path to save the results"); DEFINE_string(path, "", "Path to your dataset"); DEFINE_int32(max_iter, 20, "LM solve iteration"); DEFINE_int32(solver_max_iter, 50, "Linear solver iteration"); DEFINE_double(solver_tol, 10., "The tolerance of the linear solver"); DEFINE_double(solver_refuse_ratio, 1., "The refuse ratio of the linear solver"); DEFINE_double(tau, 1., "Initial trust region"); DEFINE_double(epsilon1, 1., "Parameter of LM"); DEFINE_double(epsilon2, 1e-10, "Parameter of LM"); int main(int argc, char* argv[]) { GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true); std::cout << "solving " << FLAGS_path << ", world_size: " << FLAGS_world_size << ", max iter: " << FLAGS_max_iter << ", solver_tol: " << FLAGS_solver_tol << ", solver_refuse_ratio: " << FLAGS_solver_refuse_ratio << ", solver_max_iter: " << FLAGS_solver_max_iter << ", tau: " << FLAGS_tau << ", epsilon1: " << FLAGS_epsilon1 << ", epsilon2: " << FLAGS_epsilon2 << std::endl; typedef double T; const std::string cameras_path = "cameras.txt"; const std::string images_path = "images.txt"; const std::string points3D_path = "points3D.txt"; std::vector<Camera> cameras; std::vector<Image> images; std::vector<Point3D> points3D; int nameCount = 0; if (!readCameras(cameras_path, cameras)) { std::cerr << "Error reading cameras file" << std::endl; return 1; } if (!readImages(images_path, images, cameras, nameCount)) { std::cerr << "Error reading images file" << std::endl; return 1; } if (!readPoints3D(points3D_path, points3D)) { std::cerr << "Error reading points3D file" << std::endl; return 1; } auto observations = collectObservations(images, points3D); std::sort(observations.begin(), observations.end()); // Renumber the point3D_ids renumberPoint3DIds(observations); int numPoints3D = countPoints3D(points3D); int numObservations = countObservations(observations); std::ostringstream summaryOutput; std::ostringstream observationsOutput; std::ostringstream cameraDetailsOutput; std::ostringstream points3DOutput; generateSummary(nameCount, numPoints3D, numObservations, summaryOutput); generateObservations(observations, observationsOutput, images); generateCameraDetails(images, cameras, cameraDetailsOutput); generatePoints3D(points3D, points3DOutput); // Save all data to a single file saveToFile(FLAGS_out_path, summaryOutput, observationsOutput, cameraDetailsOutput, points3DOutput); std::ifstream fin(FLAGS_path); if (!fin) { std::cerr << "Error opening input file: " << FLAGS_path << std::endl; return 1; } fin >> nameCount; fin >> numPoints3D; fin >> numObservations; MegBA::ProblemOption problemOption{}; problemOption.nItem = numObservations; problemOption.N = 12; for (int i = 0; i < FLAGS_world_size; ++i) { problemOption.deviceUsed.push_back(i); } MegBA::SolverOption solverOption{}; solverOption.solverOptionPCG.maxIter = FLAGS_solver_max_iter; solverOption.solverOptionPCG.tol = FLAGS_solver_tol; solverOption.solverOptionPCG.refuseRatio = FLAGS_solver_refuse_ratio; MegBA::AlgoOption algoOption{}; algoOption.algoOptionLM.maxIter = FLAGS_max_iter; algoOption.algoOptionLM.initialRegion = FLAGS_tau; algoOption.algoOptionLM.epsilon1 = FLAGS_epsilon1; algoOption.algoOptionLM.epsilon2 = FLAGS_epsilon2; std::unique_ptr<MegBA::BaseAlgo<T>> algo{ new MegBA::LMAlgo<T>{problemOption, algoOption}}; std::unique_ptr<MegBA::BaseSolver<T>> solver{ new MegBA::SchurPCGSolver<T>{problemOption, solverOption}}; std::unique_ptr<MegBA::BaseLinearSystem<T>> linearSystem{ new MegBA::SchurLMLinearSystem<T>{problemOption, std::move(solver)}}; MegBA::BaseProblem<T> problem{problemOption, std::move(algo), std::move(linearSystem)}; std::vector<std::tuple<int, int, Eigen::Matrix<T, 2, 1>>> edge; std::vector<std::tuple<int, Eigen::Matrix<T, 9, 1>>> camera_vertices; std::vector<std::tuple<int, Eigen::Matrix<T, 3, 1>>> point_vertices; int counter = 0; // Read edges while (!fin.eof()) { if (counter < numObservations) { int idx1, idx2; fin >> idx1 >> idx2; idx2 += nameCount; Eigen::Matrix<T, 2, 1> observations; readVector(fin, observations); edge.emplace_back(idx1, idx2, std::move(observations)); } else { break; } counter++; } // Read vertices and modify camera orientation counter = 0; while (!fin.eof()) { int idx = counter; if (counter < nameCount) { Eigen::Matrix<T, 9, 1> camera_vector9; readVector(fin, camera_vector9); camera_vertices.emplace_back(idx, std::move(camera_vector9)); } else { Eigen::Matrix<T, 3, 1> point_Vector3; readVector(fin, point_Vector3); point_vertices.emplace_back(idx, std::move(point_Vector3)); } counter++; if (!fin.good()) break; } for (int n = 0; n < nameCount; ++n) { problem.appendVertex(std::get<0>(camera_vertices[n]), new MegBA::CameraVertex<T>()); problem.getVertex(std::get<0>(camera_vertices[n])) .setEstimation(std::get<1>(std::move(camera_vertices[n]))); } for (int n = 0; n < numPoints3D; ++n) { problem.appendVertex(std::get<0>(point_vertices[n]), new MegBA::PointVertex<T>()); problem.getVertex(std::get<0>(point_vertices[n])) .setEstimation(std::get<1>(std::move(point_vertices[n]))); } for (int j = 0; j < numObservations; ++j) { auto edgePtr = new BAL_Edge<T>; edgePtr->appendVertex(&problem.getVertex(std::get<0>(edge[j]))); edgePtr->appendVertex(&problem.getVertex(std::get<1>(edge[j]))); edgePtr->setMeasurement(std::get<2>(std::move(edge[j]))); problem.appendEdge(*edgePtr); } problem.solve(); // Write results to output file std::ofstream fout(FLAGS_out_path); if (!fout) { std::cerr << "Error opening output file: " << FLAGS_out_path << std::endl; return 1; } // Write number of cameras, points, and observations in one line // Write number of cameras, points, and observations in one line fout << nameCount << " " << numPoints3D << " " << numObservations << std::endl; // Write observations (edges) first for (const auto& e : edge) { fout << std::get<0>(e) << " " << std::get<1>(e) << " "; writeVector(fout, std::get<2>(e)); fout << std::endl; } for (const auto& camera_vertex : camera_vertices) { Eigen::Matrix<double, 9, 1> camera_vector = std::get<1>(camera_vertex); Eigen::Vector3d rvec(camera_vector(0), camera_vector(1), camera_vector(2)); Eigen::Vector3d translation(camera_vector(3), camera_vector(4), camera_vector(5)); Eigen::Vector3d intrinsics(camera_vector(6), camera_vector(7), camera_vector(8)); // Convert Rodrigues' vector to rotation matrix Eigen::Matrix3d rotationMatrix = fromRodrigues(rvec); // Convert rotation matrix to quaternion Eigen::Quaternion<double> quaternion = rotationMatrixToQuaternion(rotationMatrix); // Extract quaternion components double w = quaternion.w(); double x = quaternion.x(); double y = quaternion.y(); double z = quaternion.z(); // Write quaternion and other parameters to the file fout << w << " " << x << " " << y << " " << z << " "; fout << translation.x() << " " << translation.y() << " " << translation.z() << " "; fout << intrinsics.x() << " " << intrinsics.y() << " " << intrinsics.z() << std::endl; } // Write point vertices for (const auto& point_vertex : point_vertices) { // Comment out or remove the ID part if not needed // fout << std::get<0>(point_vertex) << " "; writeVector(fout, std::get<1>(point_vertex)); fout << std::endl; } // Clean up and close the file gflags::ShutDownCommandLineFlags(); fout.close(); return 0; }
im not sure what am i doing wrong
import numpy as np import open3d as o3d from scipy.spatial.transform import Rotation as R def qvec2rotmat(qvec: np.ndarray) -> np.ndarray: """Convert a quaternion vector to a rotation matrix.""" q0, q1, q2, q3 = qvec return np.array([ [1 - 2 * (q2**2 + q3**2), 2 * (q1 * q2 - q0 * q3), 2 * (q1 * q3 + q0 * q2)], [2 * (q1 * q2 + q0 * q3), 1 - 2 * (q1**2 + q3**2), 2 * (q2 * q3 - q0 * q1)], [2 * (q1 * q3 - q0 * q2), 2 * (q2 * q3 + q0 * q1), 1 - 2 * (q1**2 + q2**2)] ]) def read_bal_data(file_name): """ Reads BAL data from a text file. """ with open(file_name, "r") as file: n_cameras, n_points, n_observations = map(int, file.readline().split()) points_2d = np.empty((n_observations, 2)) camera_indices = np.empty(n_observations, dtype=int) point_indices = np.empty(n_observations, dtype=int) points_3d_dict = {} for i in range(n_observations): try: camera_index, point_index, x, y = file.readline().split() camera_indices[i] = int(camera_index) point_indices[i] = int(point_index) points_2d[i] = [float(x), float(y)] except ValueError: print(f"Warning: Malformed observation line at index {i}") camera_params = np.empty((n_cameras, 10)) # 4 quaternion values + 3 translation values + 1 focal + 2 distortion coefficients for i in range(n_cameras): try: line = file.readline().split() quaternion = list(map(float, line[0:4])) # Quaternion (WXYZ) translation = list(map(float, line[4:7])) # Translation focal = float(line[7]) k1 = float(line[8]) k2 = float(line[9]) camera_params[i] = quaternion + translation + [focal, k1, k2] except ValueError: print(f"Warning: Malformed camera parameters line at index {i}") for i in range(n_points): try: line = file.readline().split() point_coords = list(map(float, line[0:3])) if len(point_coords) == 2: point_coords.append(0.0) points_3d_dict[i] = point_coords except ValueError: print(f"Warning: Malformed 3D point line at index {i}") points_3d = np.full((n_points, 3), np.nan) for index, coords in points_3d_dict.items(): points_3d[index] = coords return camera_params, points_3d, camera_indices, point_indices, points_2d def create_camera_frustum(): """ Creates a frustum to represent the camera's view. """ # Define frustum corners in camera space frustum_points = np.array([ [0, 0, 0], # Apex [0.05, 0.05, 0.1], # Near upper right [-0.05, 0.05, 0.1], # Near upper left [-0.05, -0.05, 0.1], # Near lower left [0.05, -0.05, 0.1], # Near lower right [0.05, 0.05, 0.2], # Far upper right [-0.05, 0.05, 0.2], # Far upper left [-0.05, -0.05, 0.2], # Far lower left [0.05, -0.05, 0.2], # Far lower right ]) # Define frustum lines frustum_lines = np.array([ [0, 1], [0, 2], [0, 3], [0, 4], # Apex to near plane [1, 2], [2, 3], [3, 4], [4, 1], # Near plane [5, 6], [6, 7], [7, 8], [8, 5], # Far plane [1, 5], [2, 6], [3, 7], [4, 8] # Near to far plane ]) lines = o3d.geometry.LineSet() lines.points = o3d.utility.Vector3dVector(frustum_points) lines.lines = o3d.utility.Vector2iVector(frustum_lines) # Set color colors = np.array([[0.5, 0.5, 0.5] for _ in frustum_lines]) lines.colors = o3d.utility.Vector3dVector(colors) return lines def create_global_axes(): """ Creates global axes as a reference. """ lines = o3d.geometry.LineSet() axis_length = 0.1 points = np.array([ [0, 0, 0], # Origin [axis_length, 0, 0], # X-axis [0, axis_length, 0], # Y-axis [0, 0, axis_length] # Z-axis ]) lines.lines = o3d.utility.Vector2iVector([ [0, 1], # X-axis [0, 2], # Y-axis [0, 3] # Z-axis ]) lines.points = o3d.utility.Vector3dVector(points) colors = np.array([ [1, 0, 0], # X-axis color (red) [0, 1, 0], # Y-axis color (green) [0, 0, 1] # Z-axis color (blue) ]) lines.colors = o3d.utility.Vector3dVector(colors) return lines def visualize_scene(camera_params, points_3d): vis = o3d.visualization.Visualizer() vis.create_window() # Add the 3D points point_cloud = o3d.geometry.PointCloud() point_cloud.points = o3d.utility.Vector3dVector(points_3d) vis.add_geometry(point_cloud) # Add global axes global_axes = create_global_axes() vis.add_geometry(global_axes) for camera_id, param in enumerate(camera_params): quaternion = param[:4] # Quaternion (WXYZ) translation = param[4:7] # Translation # Convert quaternion to rotation matrix rot = R.from_quat(quaternion) # WXYZ format for conversion rotation_matrix = rot.as_matrix() frustum = create_camera_frustum() frustum.rotate(rotation_matrix, center=(0, 0, 0)) frustum.translate(translation) vis.add_geometry(frustum) vis.run() vis.destroy_window() def main(): # Replace 'path/to/your/data.txt' with the actual path to your BAL file file_name = "output.txt" # Read BAL data camera_params, points_3d, _, _, _ = read_bal_data(file_name) # Visualize the scene visualize_scene(camera_params, points_3d) if __name__ == "__main__": main()
The text was updated successfully, but these errors were encountered:
No branches or pull requests
okay'ish positions but rotation still off
im not sure what am i doing wrong
The text was updated successfully, but these errors were encountered: