From 7a1f7887877eb1885eb003846b8e85337bcd42d4 Mon Sep 17 00:00:00 2001 From: Alberto en Bishop Date: Fri, 15 Feb 2019 10:58:44 +0100 Subject: [PATCH 1/2] Added various camera models to the calibrations (from dso). The calibration is saved into the camera folder. --- CMakeLists.txt | 6 +- README.md | 40 ++ src/BenchmarkDatasetReader.h | 16 +- src/Undistorter.cpp | 856 +++++++++++++++++++++++++++++++++++ src/Undistorter.h | 141 ++++++ src/main_responseCalib.cpp | 16 +- src/main_vignetteCalib.cpp | 42 +- 7 files changed, 1085 insertions(+), 32 deletions(-) create mode 100644 src/Undistorter.cpp create mode 100644 src/Undistorter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad0904..c3380f3 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,10 +25,10 @@ include_directories( ) -add_executable(responseCalib src/main_responseCalib.cpp src/FOVUndistorter.cpp src/PhotometricUndistorter.cpp) +add_executable(responseCalib src/main_responseCalib.cpp src/FOVUndistorter.cpp src/Undistorter.cpp src/PhotometricUndistorter.cpp) target_link_libraries(responseCalib ${OpenCV_LIBS} ${LIBZIP_LIBRARY}) -add_executable(playDataset src/main_playbackDataset.cpp src/FOVUndistorter.cpp src/PhotometricUndistorter.cpp) +add_executable(playDataset src/main_playbackDataset.cpp src/FOVUndistorter.cpp src/Undistorter.cpp src/PhotometricUndistorter.cpp) target_link_libraries(playDataset ${OpenCV_LIBS} ${LIBZIP_LIBRARY}) @@ -40,7 +40,7 @@ SET(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/lib/cmake/ ) find_package(aruco) IF(aruco_FOUND) - add_executable(vignetteCalib src/main_vignetteCalib.cpp src/FOVUndistorter.cpp src/PhotometricUndistorter.cpp) + add_executable(vignetteCalib src/main_vignetteCalib.cpp src/FOVUndistorter.cpp src/Undistorter.cpp src/PhotometricUndistorter.cpp) target_link_libraries(vignetteCalib ${OpenCV_LIBS} ${aruco_LIBS} ${LIBZIP_LIBRARY}) ELSE() message("================ aruco not found. not compiling vignetteCalib. ========================") diff --git a/README.md b/README.md index f2e51ae..b54ff6b 100755 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ # Install +Update (AlbertoJaenal): the calibration accepts various camera model. The code was copied from [https://github.com/JakobEngel/dso](https://github.com/JakobEngel/dso) and reformed to fit. + #### 1. Install Eigen & OpenCV (if you don't have it): sudo apt-get install libeigen3-dev libopencv-dev @@ -69,6 +71,44 @@ vignetteSmoothed.png is a slightly smoothed version, mainly to remove the black **WARNING: requires a lot of Memory (16GB ram for 1000 input images)**! Can easily be changed at the cost of slightly slower runtime... you'll have to do that yourself though. +##### Geometric Calibration File (from [https://github.com/JakobEngel/dso](https://github.com/JakobEngel/dso)) + + +###### Calibration File for Pre-Rectified Images + + Pinhole fx fy cx cy 0 + in_width in_height + "crop" / "full" / "none" / "fx fy cx cy 0" + out_width out_height + +###### Calibration File for FOV camera model: + + FOV fx fy cx cy omega + in_width in_height + "crop" / "full" / "fx fy cx cy 0" + out_width out_height + + +###### Calibration File for Radio-Tangential camera model + + RadTan fx fy cx cy k1 k2 r1 r2 + in_width in_height + "crop" / "full" / "fx fy cx cy 0" + out_width out_height + + +###### Calibration File for Equidistant camera model + + EquiDistant fx fy cx cy k1 k2 r1 r2 + in_width in_height + "crop" / "full" / "fx fy cx cy 0" + out_width out_height + + +(note: for backwards-compatibility, "Pinhole", "FOV" and "RadTan" can be omitted). See the respective +`::distortCoordinates` implementation in `Undistorter.cpp` for the exact corresponding projection function. +Furthermore, it should be straight-forward to implement other camera models. + # Usage: Matlab evaluation code Implements Sim(3) alignment of a tracked trajectory to the ground-truth segments, and subsequent computation of the different error values. See MatlabEvaluationCode/Example.m for an example, and some documentation regarding the computed values. Further, we include example results computed with DSO for all 50 sequences. diff --git a/src/BenchmarkDatasetReader.h b/src/BenchmarkDatasetReader.h index 6dafdc1..b83471e 100755 --- a/src/BenchmarkDatasetReader.h +++ b/src/BenchmarkDatasetReader.h @@ -35,7 +35,8 @@ #include #include "opencv2/opencv.hpp" -#include "FOVUndistorter.h" +//#include "FOVUndistorter.h" +#include "Undistorter.h" #include "PhotometricUndistorter.h" #include "zip.h" @@ -132,7 +133,8 @@ class DatasetReader // create undistorter. - undistorter = new UndistorterFOV((path+"camera.txt").c_str()); + //undistorter = new UndistorterFOV((path+"camera.txt").c_str()); + undistorter = Undistort::getUndistorterForFile((path+"camera.txt").c_str()); photoUndistorter = new PhotometricUndistorter(path+"pcalib.txt", path+"vignette.png",undistorter->getInputDims()[0],undistorter->getInputDims()[1]); @@ -156,7 +158,12 @@ class DatasetReader } - UndistorterFOV* getUndistorter() + /*UndistorterFOV* getUndistorter() + { + return undistorter; + }*/ + + Undistort* getUndistorter() { return undistorter; } @@ -336,7 +343,8 @@ class DatasetReader // internal structures. - UndistorterFOV* undistorter; + //UndistorterFOV* undistorter; + Undistort* undistorter; PhotometricUndistorter* photoUndistorter; zip_t* ziparchive; char* databuffer; diff --git a/src/Undistorter.cpp b/src/Undistorter.cpp new file mode 100644 index 0000000..1780e22 --- /dev/null +++ b/src/Undistorter.cpp @@ -0,0 +1,856 @@ +/** +* This file is part of DSO. +* +* Copyright 2016 Technical University of Munich and Intel. +* Developed by Jakob Engel , +* for more information see . +* If you use this code, please cite the respective publications as +* listed on the above website. +* +* DSO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DSO. If not, see . +*/ + + + + +#include +#include +#include + +#include +#include +#include "Undistorter.h" + + + +Undistort::~Undistort() +{ + if(remapX != 0) delete[] remapX; + if(remapY != 0) delete[] remapY; +} + +Undistort* Undistort::getUndistorterForFile(const char* configFilename) +{ + printf("Reading Calibration from file %s", configFilename); + + // read parameters + std::ifstream infile(configFilename); + if(!infile.good()) + { + printf("Failed to read camera calibration (invalid format?)\nCalibration file: %s\n", configFilename); + return 0; + } + + printf(" ... found!\n"); + std::string l1; + std::getline(infile,l1); + + float ic[10]; + + Undistort* u; + + // for backwards-compatibility: Use RadTan model for 8 parameters. + if(std::sscanf(l1.c_str(), "%f %f %f %f %f %f %f %f", + &ic[0], &ic[1], &ic[2], &ic[3], + &ic[4], &ic[5], &ic[6], &ic[7]) == 8) + { + printf("found RadTan (OpenCV) camera model, building rectifier.\n"); + u = new UndistortRadTan(configFilename, true); + if(!u->isValid()) {delete u; return 0; } + } + + // for backwards-compatibility: Use Pinhole / FoV model for 5 parameter. + else if(std::sscanf(l1.c_str(), "%f %f %f %f %f", + &ic[0], &ic[1], &ic[2], &ic[3], &ic[4]) == 5) + { + if(ic[4]==0) + { + printf("found PINHOLE camera model, building rectifier.\n"); + u = new UndistortPinhole(configFilename, true); + if(!u->isValid()) {delete u; return 0; } + } + else + { + printf("found FOV camera model, building rectifier.\n"); + u = new UndistortFOV(configFilename, true); + if(!u->isValid()) {delete u; return 0; } + } + } + + + + + + // clean model selection implementation. + else if(std::sscanf(l1.c_str(), "KannalaBrandt %f %f %f %f %f %f %f %f", + &ic[0], &ic[1], &ic[2], &ic[3], + &ic[4], &ic[5], &ic[6], &ic[7]) == 8) + { + u = new UndistortKB(configFilename, false); + if(!u->isValid()) {delete u; return 0; } + } + + + else if(std::sscanf(l1.c_str(), "RadTan %f %f %f %f %f %f %f %f", + &ic[0], &ic[1], &ic[2], &ic[3], + &ic[4], &ic[5], &ic[6], &ic[7]) == 8) + { + u = new UndistortRadTan(configFilename, false); + if(!u->isValid()) {delete u; return 0; } + } + + + else if(std::sscanf(l1.c_str(), "EquiDistant %f %f %f %f %f %f %f %f", + &ic[0], &ic[1], &ic[2], &ic[3], + &ic[4], &ic[5], &ic[6], &ic[7]) == 8) + { + u = new UndistortEquidistant(configFilename, false); + if(!u->isValid()) {delete u; return 0; } + } + + + else if(std::sscanf(l1.c_str(), "FOV %f %f %f %f %f", + &ic[0], &ic[1], &ic[2], &ic[3], + &ic[4]) == 5) + { + u = new UndistortFOV(configFilename, false); + if(!u->isValid()) {delete u; return 0; } + } + + + else if(std::sscanf(l1.c_str(), "Pinhole %f %f %f %f %f", + &ic[0], &ic[1], &ic[2], &ic[3], + &ic[4]) == 5) + { + u = new UndistortPinhole(configFilename, false); + if(!u->isValid()) {delete u; return 0; } + } + + + else + { + printf("could not read calib file! exit."); + exit(1); + } + + return u; +} + + +template +void Undistort::undistort(const T* in_data, float* out_data, int nPixIn, int nPixOut) const +{ + if(!valid) return; + + if(nPixIn != wOrg*hOrg) + { + printf("ERROR: undistort called with wrong input image dismesions (expected %d pixel, got %d pixel)\n", + wOrg*hOrg, nPixIn); + return; + } + if(nPixOut != w*h) + { + printf("ERROR: undistort called with wrong output image dismesions (expected %d pixel, got %d pixel)\n", + w*h, nPixOut); + return; + } + + + for(int idx = w*h-1;idx>=0;idx--) + { + + // get interp. values + float xx = remapX[idx]; + float yy = remapY[idx]; + + if(xx<0) + out_data[idx] = 0; + else + { + // get integer and rational parts + int xxi = xx; + int yyi = yy; + xx -= xxi; + yy -= yyi; + float xxyy = xx*yy; + + // get array base pointer + const T* src = in_data + xxi + yyi * wOrg; + + // interpolate (bilinear) + out_data[idx] = xxyy * src[1+wOrg] + + (yy-xxyy) * src[wOrg] + + (xx-xxyy) * src[1] + + (1-xx-yy+xxyy) * src[0]; + } + } + +} +template void Undistort::undistort(const float* in_data, float* out_data, int nPixIn, int nPixOut) const; +template void Undistort::undistort(const unsigned char* in_data, float* out_data, int nPixIn, int nPixOut) const; + + +void Undistort::makeOptimalK_crop() +{ + printf("finding CROP optimal new model!\n"); + K.setIdentity(); + + // 1. stretch the center lines as far as possible, to get initial coarse quess. + float* tgX = new float[100000]; + float* tgY = new float[100000]; + float minX = 0; + float maxX = 0; + float minY = 0; + float maxY = 0; + + for(int x=0; x<100000;x++) + {tgX[x] = (x-50000.0f) / 10000.0f; tgY[x] = 0;} + distortCoordinates(tgX, tgY,tgX, tgY,100000); + for(int x=0; x<100000;x++) + { + if(tgX[x] > 0 && tgX[x] < wOrg-1) + { + if(minX==0) minX = (x-50000.0f) / 10000.0f; + maxX = (x-50000.0f) / 10000.0f; + } + } + for(int y=0; y<100000;y++) + {tgY[y] = (y-50000.0f) / 10000.0f; tgX[y] = 0;} + distortCoordinates(tgX, tgY,tgX, tgY,100000); + for(int y=0; y<100000;y++) + { + if(tgY[y] > 0 && tgY[y] < hOrg-1) + { + if(minY==0) minY = (y-50000.0f) / 10000.0f; + maxY = (y-50000.0f) / 10000.0f; + } + } + delete[] tgX; + delete[] tgY; + + minX *= 1.01; + maxX *= 1.01; + minY *= 1.01; + maxY *= 1.01; + + + + printf("initial range: x: %.4f - %.4f; y: %.4f - %.4f!\n", minX, maxX, minY, maxY); + + + + // 2. while there are invalid pixels at the border: shrink square at the side that has invalid pixels, + // if several to choose from, shrink the wider dimension. + bool oobLeft=true, oobRight=true, oobTop=true, oobBottom=true; + int iteration=0; + while(oobLeft || oobRight || oobTop || oobBottom) + { + oobLeft=oobRight=oobTop=oobBottom=false; + for(int y=0;y 0 && remapX[2*y] < wOrg-1)) + oobLeft = true; + if(!(remapX[2*y+1] > 0 && remapX[2*y+1] < wOrg-1)) + oobRight = true; + } + + + + for(int x=0;x 0 && remapY[2*x] < hOrg-1)) + oobTop = true; + if(!(remapY[2*x+1] > 0 && remapY[2*x+1] < hOrg-1)) + oobBottom = true; + } + + + if((oobLeft || oobRight) && (oobTop || oobBottom)) + { + if((maxX-minX) > (maxY-minY)) + oobBottom = oobTop = false; // only shrink left/right + else + oobLeft = oobRight = false; // only shrink top/bottom + } + + if(oobLeft) minX *= 0.995; + if(oobRight) maxX *= 0.995; + if(oobTop) minY *= 0.995; + if(oobBottom) maxY *= 0.995; + + iteration++; + + + printf("iteration %05d: range: x: %.4f - %.4f; y: %.4f - %.4f!\n", iteration, minX, maxX, minY, maxY); + if(iteration > 500) + { + printf("FAILED TO COMPUTE GOOD CAMERA MATRIX - SOMETHING IS SERIOUSLY WRONG. ABORTING \n"); + exit(1); + } + } + + K(0,0) = ((float)w-1.0f)/(maxX-minX); + K(1,1) = ((float)h-1.0f)/(maxY-minY); + K(0,2) = -minX*K(0,0); + K(1,2) = -minY*K(1,1); + +} + +void Undistort::makeOptimalK_full() +{ + // todo + assert(false); +} + +void Undistort::readFromFile(const char* configFileName, int nPars, std::string prefix) +{ + valid = false; + passthrough=false; + remapX = 0; + remapY = 0; + + float outputCalibration[5]; + + parsOrg = VecX(nPars); + + // read parameters + std::ifstream infile(configFileName); + assert(infile.good()); + + std::string l1,l2,l3,l4; + + std::getline(infile,l1); + std::getline(infile,l2); + std::getline(infile,l3); + std::getline(infile,l4); + + // l1 & l2 + if(nPars == 5) // fov model + { + char buf[1000]; + snprintf(buf, 1000, "%s%%f %%f %%f %%f %%f", prefix.c_str()); + + if(std::sscanf(l1.c_str(), buf, &parsOrg[0], &parsOrg[1], &parsOrg[2], &parsOrg[3], &parsOrg[4]) == 5 && + std::sscanf(l2.c_str(), "%d %d", &wOrg, &hOrg) == 2) + { + printf("Input resolution: %d %d\n",wOrg, hOrg); + printf("In: %f %f %f %f %f\n", + parsOrg[0], parsOrg[1], parsOrg[2], parsOrg[3], parsOrg[4]); + } + else + { + printf("Failed to read camera calibration (invalid format?)\nCalibration file: %s\n", configFileName); + infile.close(); + return; + } + } + else if(nPars == 8) // KB, equi & radtan model + { + char buf[1000]; + snprintf(buf, 1000, "%s%%f %%f %%f %%f %%f %%f %%f %%f %%f %%f", prefix.c_str()); + + if(std::sscanf(l1.c_str(), buf, + &parsOrg[0], &parsOrg[1], &parsOrg[2], &parsOrg[3], &parsOrg[4], + &parsOrg[5], &parsOrg[6], &parsOrg[7]) == 8 && + std::sscanf(l2.c_str(), "%d %d", &wOrg, &hOrg) == 2) + { + printf("Input resolution: %d %d\n",wOrg, hOrg); + printf("In: %s%f %f %f %f %f %f %f %f\n", + prefix.c_str(), + parsOrg[0], parsOrg[1], parsOrg[2], parsOrg[3], parsOrg[4], parsOrg[5], parsOrg[6], parsOrg[7]); + } + else + { + printf("Failed to read camera calibration (invalid format?)\nCalibration file: %s\n", configFileName); + infile.close(); + return; + } + } + else + { + printf("called with invalid number of parameters.... forgot to implement me?\n"); + infile.close(); + return; + } + + + + + if(parsOrg[2] < 1 && parsOrg[3] < 1) + { + printf("\n\nFound fx=%f, fy=%f, cx=%f, cy=%f.\n I'm assuming this is the \"relative\" calibration file format," + "and will rescale this by image width / height to fx=%f, fy=%f, cx=%f, cy=%f.\n\n", + parsOrg[0], parsOrg[1], parsOrg[2], parsOrg[3], + parsOrg[0] * wOrg, parsOrg[1] * hOrg, parsOrg[2] * wOrg - 0.5, parsOrg[3] * hOrg - 0.5 ); + + // rescale and substract 0.5 offset. + // the 0.5 is because I'm assuming the calibration is given such that the pixel at (0,0) + // contains the integral over intensity over [0,0]-[1,1], whereas I assume the pixel (0,0) + // to contain a sample of the intensity ot [0,0], which is best approximated by the integral over + // [-0.5,-0.5]-[0.5,0.5]. Thus, the shift by -0.5. + parsOrg[0] = parsOrg[0] * wOrg; + parsOrg[1] = parsOrg[1] * hOrg; + parsOrg[2] = parsOrg[2] * wOrg - 0.5; + parsOrg[3] = parsOrg[3] * hOrg - 0.5; + } + + + + // l3 + if(l3 == "crop") + { + outputCalibration[0] = -1; + printf("Out: Rectify Crop\n"); + } + else if(l3 == "full") + { + outputCalibration[0] = -2; + printf("Out: Rectify Full\n"); + } + else if(l3 == "none") + { + outputCalibration[0] = -3; + printf("Out: No Rectification\n"); + } + else if(std::sscanf(l3.c_str(), "%f %f %f %f %f", &outputCalibration[0], &outputCalibration[1], &outputCalibration[2], &outputCalibration[3], &outputCalibration[4]) == 5) + { + printf("Out: %f %f %f %f %f\n", + outputCalibration[0], outputCalibration[1], outputCalibration[2], outputCalibration[3], outputCalibration[4]); + + } + else + { + printf("Out: Failed to Read Output pars... not rectifying.\n"); + infile.close(); + return; + } + + + + // l4 + if(std::sscanf(l4.c_str(), "%d %d", &w, &h) == 2) + { + if(benchmarkSetting_width != 0) + { + w = benchmarkSetting_width; + if(outputCalibration[0] == -3) + outputCalibration[0] = -1; // crop instead of none, since probably resolution changed. + } + if(benchmarkSetting_height != 0) + { + h = benchmarkSetting_height; + if(outputCalibration[0] == -3) + outputCalibration[0] = -1; // crop instead of none, since probably resolution changed. + } + + printf("Output resolution: %d %d\n",w, h); + } + else + { + printf("Out: Failed to Read Output resolution... not rectifying.\n"); + valid = false; + } + + remapX = new float[w*h]; + remapY = new float[w*h]; + + if(outputCalibration[0] == -1) + makeOptimalK_crop(); + else if(outputCalibration[0] == -2) + makeOptimalK_full(); + else if(outputCalibration[0] == -3) + { + if(w != wOrg || h != hOrg) + { + printf("ERROR: rectification mode none requires input and output dimenstions to match!\n\n"); + exit(1); + } + K.setIdentity(); + K(0,0) = parsOrg[0]; + K(1,1) = parsOrg[1]; + K(0,2) = parsOrg[2]; + K(1,2) = parsOrg[3]; + passthrough = true; + } + else + { + + + if(outputCalibration[2] > 1 || outputCalibration[3] > 1) + { + printf("\n\n\nWARNING: given output calibration (%f %f %f %f) seems wrong. It needs to be relative to image width / height!\n\n\n", + outputCalibration[0],outputCalibration[1],outputCalibration[2],outputCalibration[3]); + } + + + K.setIdentity(); + K(0,0) = outputCalibration[0] * w; + K(1,1) = outputCalibration[1] * h; + K(0,2) = outputCalibration[2] * w - 0.5; + K(1,2) = outputCalibration[3] * h - 0.5; + } + + if(benchmarkSetting_fxfyfac != 0) + { + K(0,0) = fmax(benchmarkSetting_fxfyfac, (float)K(0,0)); + K(1,1) = fmax(benchmarkSetting_fxfyfac, (float)K(1,1)); + passthrough = false; // cannot pass through when fx / fy have been overwritten. + } + + + for(int y=0;y 0 && iy > 0 && ix < wOrg-1 && iy < hOrg-1) + { + remapX[x+y*w] = ix; + remapY[x+y*w] = iy; + } + else + { + remapX[x+y*w] = -1; + remapY[x+y*w] = -1; + } + } + + valid = true; + + Korg.setIdentity(); + Korg(0,0) = parsOrg[0] * wOrg; + Korg(1,1) = parsOrg[1] * hOrg; + Korg(0,2) = parsOrg[2] * wOrg - 0.5; + Korg(1,2) = parsOrg[3] * hOrg - 0.5; + + + printf("\nRectified Kamera Matrix:\n"); + std::cout << K << "\n\n"; + +} + + +UndistortFOV::UndistortFOV(const char* configFileName, bool noprefix) +{ + printf("Creating FOV undistorter\n"); + + if(noprefix) + readFromFile(configFileName, 5); + else + readFromFile(configFileName, 5, "FOV "); +} +UndistortFOV::~UndistortFOV() +{ +} + +void UndistortFOV::distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const +{ + float dist = parsOrg[4]; + float d2t = 2.0f * tan(dist / 2.0f); + + + + // current camera parameters + float fx = parsOrg[0]; + float fy = parsOrg[1]; + float cx = parsOrg[2]; + float cy = parsOrg[3]; + + + + float ofx = K(0,0); + float ofy = K(1,1); + float ocx = K(0,2); + float ocy = K(1,2); + + for(int i=0;i 1e-8) ? thetad / r : 1.0; + float ox = fx*ix*scaling + cx; + float oy = fy*iy*scaling + cy; + + out_x[i] = ox; + out_y[i] = oy; + + } +} + + + +UndistortKB::UndistortKB(const char* configFileName, bool noprefix) +{ + printf("Creating KannalaBrandt undistorter\n"); + + if(noprefix) + readFromFile(configFileName, 8); + else + readFromFile(configFileName, 8,"KannalaBrandt "); +} +UndistortKB::~UndistortKB() +{ +} + +void UndistortKB::distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const +{ + const float fx = parsOrg[0]; + const float fy = parsOrg[1]; + const float cx = parsOrg[2]; + const float cy = parsOrg[3]; + const float k0 = parsOrg[4]; + const float k1 = parsOrg[5]; + const float k2 = parsOrg[6]; + const float k3 = parsOrg[7]; + + const float ofx = K(0,0); + const float ofy = K(1,1); + const float ocx = K(0,2); + const float ocy = K(1,2); + + + for(int i=0;i, +* for more information see . +* If you use this code, please cite the respective publications as +* listed on the above website. +* +* DSO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DSO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DSO. If not, see . +*/ + + +#pragma once + +#include "Eigen/Core" +#include "ExposureImage.h" + +typedef Eigen::Matrix3f Mat33; +typedef Eigen::VectorXf VecX; + + +class Undistort +{ +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW; + virtual ~Undistort(); + + virtual void distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const = 0; + + inline const Mat33 getK() const {return K;}; + inline Eigen::Matrix3f getK_rect() const {return K;}; + + inline Eigen::Matrix3f getK_org() const {return Korg;}; + + inline const Eigen::Vector2i getSize() const {return Eigen::Vector2i(w,h);}; + const Eigen::Vector2i getOutputDims() const {return Eigen::Vector2i(w,h);}; + + inline const VecX getOriginalParameter() const {return parsOrg;}; + const Eigen::VectorXf getOriginalCalibration() const {return parsOrg;}; + inline float getOmega() const { return parsOrg[4];} + + inline const Eigen::Vector2i getOriginalSize() {return Eigen::Vector2i(wOrg,hOrg);}; + const Eigen::Vector2i getInputDims() const {return Eigen::Vector2i(wOrg,hOrg);}; + + inline bool isValid() {return valid;}; + + template + void undistort(const T* in_data, float* out_data, int nPixIn, int nPixOut) const; + static Undistort* getUndistorterForFile(const char* configFileName); + + int benchmarkSetting_width = 0; + int benchmarkSetting_height = 0; + float benchmarkSetting_fxfyfac = 0; + + +protected: + int w, h, wOrg, hOrg, wUp, hUp; + int upsampleUndistFactor; + Mat33 K; + Mat33 Korg; + VecX parsOrg; + bool valid; + bool passthrough; + + float* remapX; + float* remapY; + + void applyBlurNoise(float* img) const; + + void makeOptimalK_crop(); + void makeOptimalK_full(); + + void readFromFile(const char* configFileName, int nPars, std::string prefix = ""); +}; + +class UndistortFOV : public Undistort +{ +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW; + + UndistortFOV(const char* configFileName, bool noprefix); + ~UndistortFOV(); + void distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const; + +}; + +class UndistortRadTan : public Undistort +{ +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW; + UndistortRadTan(const char* configFileName, bool noprefix); + ~UndistortRadTan(); + void distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const; + +}; + +class UndistortEquidistant : public Undistort +{ +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW; + UndistortEquidistant(const char* configFileName, bool noprefix); + ~UndistortEquidistant(); + void distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const; + +}; + +class UndistortPinhole : public Undistort +{ +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW; + UndistortPinhole(const char* configFileName, bool noprefix); + ~UndistortPinhole(); + void distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const; + +private: + float inputCalibration[8]; +}; + +class UndistortKB : public Undistort +{ +public: + EIGEN_MAKE_ALIGNED_OPERATOR_NEW; + UndistortKB(const char* configFileName, bool noprefix); + ~UndistortKB(); + void distortCoordinates(float* in_x, float* in_y, float* out_x, float* out_y, int n) const; + +}; + + diff --git a/src/main_responseCalib.cpp b/src/main_responseCalib.cpp index 4de2303..ddf5c34 100755 --- a/src/main_responseCalib.cpp +++ b/src/main_responseCalib.cpp @@ -180,6 +180,7 @@ int main( int argc, char** argv ) for(int i=2; igetUndistorter()->getK_rect(); @@ -218,7 +221,6 @@ int main( int argc, char** argv ) int wI = reader->getUndistorter()->getInputDims()[0]; int hI = reader->getUndistorter()->getInputDims()[1]; - float meanExposure = 0; for(int i=0;igetNumImages();i+=imageSkip) meanExposure+=reader->getExposure(i); @@ -231,6 +233,7 @@ int main( int argc, char** argv ) { std::vector Markers; ExposureImage* img = reader->getImage(i,true, false, false, false); + std::cout << i << std::endl; cv::Mat InImage; cv::Mat(h_out, w_out, CV_32F, img->image).convertTo(InImage, CV_8U, 1, 0); @@ -264,7 +267,6 @@ int main( int argc, char** argv ) ExposureImage* imgRaw = reader->getImage(i,false, true, false, false); - float* plane2imgX = new float[gw*gh]; float* plane2imgY = new float[gw*gh]; @@ -276,12 +278,18 @@ int main( int argc, char** argv ) for(int x=0;x 0){ + plane2imgX[idx] = pp[0] / pp[2]; + plane2imgY[idx] = pp[1] / pp[2]; + }else{ + plane2imgX[idx] = NAN; + plane2imgY[idx] = NAN; + } idx++; } - reader->getUndistorter()->distortCoordinates(plane2imgX, plane2imgY, gw*gh); + reader->getUndistorter()->distortCoordinates(plane2imgX, plane2imgY, plane2imgX, plane2imgY, gw*gh); if(imgRaw->exposure_time == 0) imgRaw->exposure_time = 1; @@ -361,8 +369,8 @@ int main( int argc, char** argv ) if(rand()%40==0) { char buf[1000]; - snprintf(buf,1000,"vignetteCalibResult/img%d.png",i); - cv::imwrite(buf, dbgImg); + snprintf(buf,1000, "vignetteCalibResult/img%d.png",i); + cv::imwrite(path + "/" + std::string(buf), dbgImg); } cv::waitKey(1); @@ -370,10 +378,10 @@ int main( int argc, char** argv ) p2imgX.push_back(plane2imgX); p2imgY.push_back(plane2imgY); } - + std::ofstream logFile; - logFile.open("vignetteCalibResult/log.txt", std::ios::trunc | std::ios::out); + logFile.open(path + "/" + "vignetteCalibResult/log.txt", std::ios::trunc | std::ios::out); logFile.precision(15); @@ -445,7 +453,7 @@ int main( int argc, char** argv ) else planeColor[pi] = planeColorFC[pi] / planeColorFF[pi]; } - displayImage(planeColor, gw, gh, "Plane"); + displayImage(planeColor, gw, gh, "Plane", path); printf("%f residual terms => %f\n", R, sqrtf(E/R)); @@ -570,7 +578,7 @@ int main( int argc, char** argv ) cv::Mat wrap = cv::Mat(hI, wI, CV_32F, vignetteFactorTT)*254.9*254.9; cv::Mat wrap16; wrap.convertTo(wrap16, CV_16U,1,0); - cv::imwrite("vignetteCalibResult/vignetteSmoothed.png", wrap16); + cv::imwrite(path + "/" + "vignetteCalibResult/vignetteSmoothed.png", wrap16); cv::waitKey(50); } { @@ -578,7 +586,7 @@ int main( int argc, char** argv ) cv::Mat wrap = cv::Mat(hI, wI, CV_32F, vignetteFactor)*254.9*254.9; cv::Mat wrap16; wrap.convertTo(wrap16, CV_16U,1,0); - cv::imwrite("vignetteCalibResult/vignette.png", wrap16); + cv::imwrite(path + "/" + "vignetteCalibResult/vignette.png", wrap16); cv::waitKey(50); } } From 08bb2aafae4d02f4b2f3b9fdfd8e709b345cbf97 Mon Sep 17 00:00:00 2001 From: Alberto en Bishop Date: Fri, 15 Feb 2019 11:01:13 +0100 Subject: [PATCH 2/2] Reformed README --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b54ff6b..0cfe303 100755 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ - +Update (AlbertoJaenal): the calibration accepts various camera model. The code was copied from [https://github.com/JakobEngel/dso](https://github.com/JakobEngel/dso) and reformed to fit. # Install -Update (AlbertoJaenal): the calibration accepts various camera model. The code was copied from [https://github.com/JakobEngel/dso](https://github.com/JakobEngel/dso) and reformed to fit. - #### 1. Install Eigen & OpenCV (if you don't have it): sudo apt-get install libeigen3-dev libopencv-dev @@ -71,7 +69,7 @@ vignetteSmoothed.png is a slightly smoothed version, mainly to remove the black **WARNING: requires a lot of Memory (16GB ram for 1000 input images)**! Can easily be changed at the cost of slightly slower runtime... you'll have to do that yourself though. -##### Geometric Calibration File (from [https://github.com/JakobEngel/dso](https://github.com/JakobEngel/dso)) +##### Geometric Calibration File (from [https://github.com/JakobEngel/dso](https://github.com/JakobEngel/dso#geometric-calibration-file)) ###### Calibration File for Pre-Rectified Images