mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-12 22:40:19 +08:00
0.19.6: Added auto brightness/contrast and texture format options to multiband approach. rtabmap-export moved from examples to tools directory.
This commit is contained in:
+1
-1
@@ -21,7 +21,7 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
|
||||
#######################
|
||||
SET(RTABMAP_MAJOR_VERSION 0)
|
||||
SET(RTABMAP_MINOR_VERSION 19)
|
||||
SET(RTABMAP_PATCH_VERSION 5)
|
||||
SET(RTABMAP_PATCH_VERSION 6)
|
||||
SET(RTABMAP_VERSION
|
||||
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
|
||||
|
||||
|
||||
@@ -147,7 +147,9 @@ cv::Mat RTABMAP_EXP brightnessAndContrastAuto(
|
||||
const cv::Mat & src,
|
||||
const cv::Mat & mask,
|
||||
float clipLowHistPercent=0,
|
||||
float clipHighHistPercent=0);
|
||||
float clipHighHistPercent=0,
|
||||
float * alphaOut = 0,
|
||||
float * betaOut = 0);
|
||||
|
||||
cv::Mat RTABMAP_EXP exposureFusion(
|
||||
const std::vector<cv::Mat> & images);
|
||||
|
||||
@@ -223,7 +223,8 @@ cv::Mat RTABMAP_EXP mergeTextures(
|
||||
const ProgressState * state = 0,
|
||||
unsigned char blankValue = 255, //Gray value for blank polygons (without texture)
|
||||
std::map<int, std::map<int, cv::Vec4d> > * gains = 0, // <Camera ID, Camera Sub Index (multi-cameras), gains Gray-R-G-B>
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGains = 0); // <Camera ID, Camera Sub Index (multi-cameras), gains>
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGains = 0, // <Camera ID, Camera Sub Index (multi-cameras), gains>
|
||||
std::pair<float, float> * contrastValues = 0); // Alpha/beta contrast values
|
||||
cv::Mat RTABMAP_EXP mergeTextures(
|
||||
pcl::TextureMesh & mesh,
|
||||
const std::map<int, cv::Mat> & images, // raw or compressed, can be empty if memory or dbDriver should be used
|
||||
@@ -244,13 +245,15 @@ cv::Mat RTABMAP_EXP mergeTextures(
|
||||
const ProgressState * state = 0,
|
||||
unsigned char blankValue = 255, //Gray value for blank polygons (without texture)
|
||||
std::map<int, std::map<int, cv::Vec4d> > * gains = 0, // <Camera ID, Camera Sub Index (multi-cameras), gains Gray-R-G-B>
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGains = 0); // <Camera ID, Camera Sub Index (multi-cameras), gains>
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGains = 0, // <Camera ID, Camera Sub Index (multi-cameras), gains>
|
||||
std::pair<float, float> * contrastValues = 0); // Alpha/beta contrast values
|
||||
|
||||
void RTABMAP_EXP fixTextureMeshForVisualization(pcl::TextureMesh & textureMesh);
|
||||
|
||||
bool RTABMAP_EXP multiBandTexturing(
|
||||
const std::string & outputOBJPath,
|
||||
const pcl::PolygonMesh & mesh,
|
||||
const pcl::PCLPointCloud2 & cloud,
|
||||
const std::vector<pcl::Vertices> & polygons,
|
||||
const std::map<int, Transform> & cameraPoses,
|
||||
const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels, // required output of util3d::createTextureMesh()
|
||||
const std::map<int, cv::Mat> & images, // raw or compressed, can be empty if memory or dbDriver should be used
|
||||
@@ -258,8 +261,10 @@ bool RTABMAP_EXP multiBandTexturing(
|
||||
const Memory * memory = 0, // Should be set if images are not set
|
||||
const DBDriver * dbDriver = 0, // Should be set if images and memory are not set
|
||||
int textureSize = 8192,
|
||||
const std::string & textureFormat = "jpg", // png, jpg
|
||||
const std::map<int, std::map<int, cv::Vec4d> > & gains = std::map<int, std::map<int, cv::Vec4d> >(), // optional output of util3d::mergeTextures()
|
||||
const std::map<int, std::map<int, cv::Mat> > & blendingGains = std::map<int, std::map<int, cv::Mat> >()); // optional output of util3d::mergeTextures()
|
||||
const std::map<int, std::map<int, cv::Mat> > & blendingGains = std::map<int, std::map<int, cv::Mat> >(), // optional output of util3d::mergeTextures()
|
||||
const std::pair<float, float> & contrastValues = std::pair<float, float>(0,0)); // optional output of util3d::mergeTextures()
|
||||
|
||||
cv::Mat RTABMAP_EXP computeNormals(
|
||||
const cv::Mat & laserScan,
|
||||
|
||||
@@ -604,7 +604,7 @@ void Optimizer::computeBACorrespondences(
|
||||
ParametersMap regParam;
|
||||
regParam.insert(ParametersPair(Parameters::kVisEstimationType(), "1"));
|
||||
regParam.insert(ParametersPair(Parameters::kVisPnPReprojError(), "5"));
|
||||
regParam.insert(ParametersPair(Parameters::kVisMinInliers(), "5"));
|
||||
regParam.insert(ParametersPair(Parameters::kVisMinInliers(), "6"));
|
||||
regParam.insert(ParametersPair(Parameters::kVisCorNNDR(), "0.6"));
|
||||
RegistrationVis reg(regParam);
|
||||
|
||||
|
||||
@@ -119,7 +119,11 @@ void RegistrationVis::parseParameters(const ParametersMap & parameters)
|
||||
Parameters::parse(parameters, Parameters::kVisMeanInliersDistance(), _maxInliersMeanDistance);
|
||||
uInsert(_bundleParameters, parameters);
|
||||
|
||||
UASSERT_MSG(_minInliers >= 1, uFormat("value=%d", _minInliers).c_str());
|
||||
if(_minInliers < 6)
|
||||
{
|
||||
UWARN("%s should be >= 6 but it is set to %d, setting to 6.", Parameters::kVisMinInliers().c_str(), _minInliers);
|
||||
_minInliers = 6;
|
||||
}
|
||||
UASSERT_MSG(_inlierDistance > 0.0f, uFormat("value=%f", _inlierDistance).c_str());
|
||||
UASSERT_MSG(_iterations > 0, uFormat("value=%d", _iterations).c_str());
|
||||
|
||||
|
||||
+16
-8
@@ -4468,15 +4468,12 @@ int Rtabmap::detectMoreLoopClosures(
|
||||
|
||||
std::map<int, int> mapIds;
|
||||
UDEBUG("remove all invalid or intermediate nodes, fill mapIds");
|
||||
for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end();++iter)
|
||||
for(std::map<int, Transform>::iterator iter=poses.upper_bound(0); iter!=poses.end();++iter)
|
||||
{
|
||||
if(iter->first > 0)
|
||||
if(signatures.at(iter->first).getWeight() >= 0)
|
||||
{
|
||||
if(signatures.at(iter->first).getWeight() >= 0)
|
||||
{
|
||||
posesToCheckLoopClosures.insert(*iter);
|
||||
mapIds.insert(std::make_pair(iter->first, signatures.at(iter->first).mapId()));
|
||||
}
|
||||
posesToCheckLoopClosures.insert(*iter);
|
||||
mapIds.insert(std::make_pair(iter->first, signatures.at(iter->first).mapId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4517,7 +4514,18 @@ int Rtabmap::detectMoreLoopClosures(
|
||||
(intraSession && mapIdFrom == mapIdTo))
|
||||
{
|
||||
|
||||
if(rtabmap::graph::findLink(checkedLoopClosures, from, to) == checkedLoopClosures.end())
|
||||
bool alreadyChecked = false;
|
||||
for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
|
||||
!alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
|
||||
++jter)
|
||||
{
|
||||
if(to == jter->second)
|
||||
{
|
||||
alreadyChecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!alreadyChecked)
|
||||
{
|
||||
// only add new links and one per cluster per iteration
|
||||
if(addedLinks.find(from) == addedLinks.end() &&
|
||||
|
||||
+11
-1
@@ -1939,7 +1939,7 @@ cv::Mat fastBilateralFiltering(const cv::Mat & depth, float sigmaS, float sigmaR
|
||||
* \note In case of BGRA image, we won't touch the transparency
|
||||
* See http://answers.opencv.org/question/75510/how-to-make-auto-adjustmentsbrightness-and-contrast-for-image-android-opencv-image-correction/
|
||||
*/
|
||||
cv::Mat brightnessAndContrastAuto(const cv::Mat &src, const cv::Mat & mask, float clipLowHistPercent, float clipHighHistPercent)
|
||||
cv::Mat brightnessAndContrastAuto(const cv::Mat &src, const cv::Mat & mask, float clipLowHistPercent, float clipHighHistPercent, float * alphaOut, float * betaOut)
|
||||
{
|
||||
|
||||
CV_Assert(clipLowHistPercent >= 0 && clipHighHistPercent>=0);
|
||||
@@ -2011,6 +2011,16 @@ cv::Mat brightnessAndContrastAuto(const cv::Mat &src, const cv::Mat & mask, floa
|
||||
int from_to[] = { 3, 3};
|
||||
cv::mixChannels(&src, 4, &dst,1, from_to, 1);
|
||||
}
|
||||
|
||||
if(alphaOut)
|
||||
{
|
||||
*alphaOut = alpha;
|
||||
}
|
||||
if(betaOut)
|
||||
{
|
||||
*betaOut = beta;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
+105
-50
@@ -53,6 +53,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <aliceVision/mesh/Mesh.hpp>
|
||||
#include <aliceVision/mesh/Texturing.hpp>
|
||||
#include <aliceVision/camera/Pinhole.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
using namespace aliceVision;
|
||||
#endif
|
||||
|
||||
@@ -1439,7 +1440,8 @@ cv::Mat mergeTextures(
|
||||
const ProgressState * state,
|
||||
unsigned char blankValue,
|
||||
std::map<int, std::map<int, cv::Vec4d> > * gains,
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGains)
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGains,
|
||||
std::pair<float, float> * contrastValues)
|
||||
{
|
||||
std::map<int, std::vector<CameraModel> > calibVectors;
|
||||
for(std::map<int, CameraModel>::const_iterator iter=calibrations.begin(); iter!=calibrations.end(); ++iter)
|
||||
@@ -1467,7 +1469,8 @@ cv::Mat mergeTextures(
|
||||
state,
|
||||
blankValue,
|
||||
gains,
|
||||
blendingGains);
|
||||
blendingGains,
|
||||
contrastValues);
|
||||
}
|
||||
cv::Mat mergeTextures(
|
||||
pcl::TextureMesh & mesh,
|
||||
@@ -1489,7 +1492,8 @@ cv::Mat mergeTextures(
|
||||
const ProgressState * state,
|
||||
unsigned char blankValue,
|
||||
std::map<int, std::map<int, cv::Vec4d> > * gainsOut,
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGainsOut)
|
||||
std::map<int, std::map<int, cv::Mat> > * blendingGainsOut,
|
||||
std::pair<float, float> * contrastValuesOut)
|
||||
{
|
||||
//get texture size, if disabled use default 1024
|
||||
UASSERT(textureSize%256 == 0);
|
||||
@@ -2109,40 +2113,43 @@ cv::Mat mergeTextures(
|
||||
|
||||
if(brightnessContrastRatioLow > 0 || brightnessContrastRatioHigh > 0)
|
||||
{
|
||||
for(int i=0; i<materials; ++i)
|
||||
if(exposureFusion)
|
||||
{
|
||||
cv::Mat globalTexturesROI = globalTextures(cv::Range::all(), cv::Range(i*globalTextures.rows, (i+1)*globalTextures.rows));
|
||||
cv::Mat globalTextureMasksROI = globalTextureMasks(cv::Range::all(), cv::Range(i*globalTextureMasks.rows, (i+1)*globalTextureMasks.rows));
|
||||
if(exposureFusion)
|
||||
std::vector<cv::Mat> images;
|
||||
images.push_back(globalTextures);
|
||||
if (brightnessContrastRatioLow > 0)
|
||||
{
|
||||
std::vector<cv::Mat> images;
|
||||
images.push_back(globalTexturesROI);
|
||||
if (brightnessContrastRatioLow > 0)
|
||||
{
|
||||
images.push_back(util2d::brightnessAndContrastAuto(
|
||||
globalTexturesROI,
|
||||
globalTextureMasksROI,
|
||||
images.push_back(util2d::brightnessAndContrastAuto(
|
||||
globalTextures,
|
||||
globalTextureMasks,
|
||||
(float)brightnessContrastRatioLow,
|
||||
0.0f));
|
||||
}
|
||||
if (brightnessContrastRatioHigh > 0)
|
||||
{
|
||||
images.push_back(util2d::brightnessAndContrastAuto(
|
||||
globalTexturesROI,
|
||||
globalTextureMasksROI,
|
||||
}
|
||||
if (brightnessContrastRatioHigh > 0)
|
||||
{
|
||||
images.push_back(util2d::brightnessAndContrastAuto(
|
||||
globalTextures,
|
||||
globalTextureMasks,
|
||||
0.0f,
|
||||
(float)brightnessContrastRatioHigh));
|
||||
}
|
||||
|
||||
util2d::exposureFusion(images).copyTo(globalTexturesROI);
|
||||
}
|
||||
else
|
||||
{
|
||||
util2d::brightnessAndContrastAuto(
|
||||
globalTexturesROI,
|
||||
globalTextureMasksROI,
|
||||
|
||||
globalTextures = util2d::exposureFusion(images);
|
||||
}
|
||||
else
|
||||
{
|
||||
float alpha, beta;
|
||||
globalTextures = util2d::brightnessAndContrastAuto(
|
||||
globalTextures,
|
||||
globalTextureMasks,
|
||||
(float)brightnessContrastRatioLow,
|
||||
(float)brightnessContrastRatioHigh).copyTo(globalTexturesROI);
|
||||
(float)brightnessContrastRatioHigh,
|
||||
&alpha,
|
||||
&beta);
|
||||
if(contrastValuesOut)
|
||||
{
|
||||
contrastValuesOut->first = alpha;
|
||||
contrastValuesOut->second = beta;
|
||||
}
|
||||
}
|
||||
if(state) state->callback(uFormat("Brightness and contrast auto %fs", timer.ticks()));
|
||||
@@ -2195,7 +2202,8 @@ void fixTextureMeshForVisualization(pcl::TextureMesh & textureMesh)
|
||||
|
||||
bool multiBandTexturing(
|
||||
const std::string & outputOBJPath,
|
||||
const pcl::PolygonMesh & mesh,
|
||||
const pcl::PCLPointCloud2 & cloud,
|
||||
const std::vector<pcl::Vertices> & polygons,
|
||||
const std::map<int, Transform> & cameraPoses,
|
||||
const std::vector<std::map<int, pcl::PointXY> > & vertexToPixels, // required output of util3d::createTextureMesh()
|
||||
const std::map<int, cv::Mat> & images, // raw or compressed, can be empty if memory or dbDriver should be used
|
||||
@@ -2203,8 +2211,10 @@ bool multiBandTexturing(
|
||||
const Memory * memory, // Should be set if images are not set
|
||||
const DBDriver * dbDriver, // Should be set if images and memory are not set
|
||||
int textureSize,
|
||||
const std::string & textureFormat,
|
||||
const std::map<int, std::map<int, cv::Vec4d> > & gains, // optional output of util3d::mergeTextures()
|
||||
const std::map<int, std::map<int, cv::Mat> > & blendingGains)// optional output of util3d::mergeTextures()
|
||||
const std::map<int, std::map<int, cv::Mat> > & blendingGains, // optional output of util3d::mergeTextures()
|
||||
const std::pair<float, float> & contrastValues) // optional output of util3d::mergeTextures()
|
||||
{
|
||||
#ifdef RTABMAP_ALICE_VISION
|
||||
if(ULogger::level() == ULogger::kDebug)
|
||||
@@ -2226,15 +2236,16 @@ bool multiBandTexturing(
|
||||
|
||||
sfmData::SfMData sfmData;
|
||||
pcl::PointCloud<pcl::PointXYZRGB> cloud2;
|
||||
pcl::fromPCLPointCloud2(mesh.cloud, cloud2);
|
||||
pcl::fromPCLPointCloud2(cloud, cloud2);
|
||||
UASSERT(vertexToPixels.size() == cloud2.size());
|
||||
UINFO("Input mesh: %d points %d polygons", (int)cloud2.size(), (int)mesh.polygons.size());
|
||||
UINFO("Input mesh: %d points %d polygons", (int)cloud2.size(), (int)polygons.size());
|
||||
mesh::Texturing texturing;
|
||||
texturing.me = new mesh::Mesh();
|
||||
texturing.me->pts = new StaticVector<Point3d>(cloud2.size());
|
||||
texturing.pointsVisibilities = new mesh::PointsVisibility();
|
||||
texturing.pointsVisibilities->reserve(cloud2.size());
|
||||
texturing.texParams.textureSide = textureSize;
|
||||
texturing.texParams.textureSide = 8192;
|
||||
texturing.texParams.downscale = 8192/textureSize;
|
||||
|
||||
std::vector<int> camIndexToId(uKeys(cameraModels));
|
||||
for(size_t i=0;i<cloud2.size();++i)
|
||||
@@ -2250,14 +2261,14 @@ bool multiBandTexturing(
|
||||
(*texturing.me->pts)[i] = Point3d(pt.x, pt.y, pt.z);
|
||||
}
|
||||
|
||||
texturing.me->tris = new StaticVector<mesh::Mesh::triangle>(mesh.polygons.size());
|
||||
for(size_t i=0;i<mesh.polygons.size();++i)
|
||||
texturing.me->tris = new StaticVector<mesh::Mesh::triangle>(polygons.size());
|
||||
for(size_t i=0;i<polygons.size();++i)
|
||||
{
|
||||
UASSERT(mesh.polygons[i].vertices.size() == 3);
|
||||
UASSERT(polygons[i].vertices.size() == 3);
|
||||
(*texturing.me->tris)[i] = mesh::Mesh::triangle(
|
||||
mesh.polygons[i].vertices[0],
|
||||
mesh.polygons[i].vertices[1],
|
||||
mesh.polygons[i].vertices[2]);
|
||||
polygons[i].vertices[0],
|
||||
polygons[i].vertices[1],
|
||||
polygons[i].vertices[2]);
|
||||
}
|
||||
UTimer timer;
|
||||
std::string outputDirectory = UDirectory::getDir(outputOBJPath);
|
||||
@@ -2274,6 +2285,7 @@ bool multiBandTexturing(
|
||||
!images.find(camId)->second.empty() &&
|
||||
cameraModels.find(camId) != cameraModels.end())
|
||||
{
|
||||
image = images.find(camId)->second;
|
||||
models = cameraModels.find(camId)->second;
|
||||
}
|
||||
else if(memory)
|
||||
@@ -2315,18 +2327,18 @@ bool multiBandTexturing(
|
||||
}
|
||||
if(models.empty())
|
||||
{
|
||||
UERROR("No camera models found for camera %d", iter->first);
|
||||
continue;
|
||||
UERROR("No camera models found for camera %d. Aborting multiband texturing...", iter->first);
|
||||
return false;
|
||||
}
|
||||
else if(models.size() != 1)
|
||||
{
|
||||
UERROR("Unwrapping not supporting multi-camera yet... ignoring %d", iter->first);
|
||||
continue;
|
||||
UERROR("Unwrapping not supporting multi-camera yet... ignoring %d. Aborting multiband texturing...", iter->first);
|
||||
return false;
|
||||
}
|
||||
if(image.empty())
|
||||
{
|
||||
UERROR("No image found for camera %d", iter->first);
|
||||
continue;
|
||||
UERROR("No image found for camera %d. Aborting multiband texturing...", iter->first);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(image.rows == 1 && image.type() == CV_8UC1)
|
||||
@@ -2400,13 +2412,14 @@ bool multiBandTexturing(
|
||||
UINFO("Unwrapping done. %fs", timer.ticks());
|
||||
|
||||
// save final obj file
|
||||
texturing.saveAsOBJ(outputDirectory, uSplit(UFile::getName(outputOBJPath), '.').front());
|
||||
UINFO("Saved %s. %fs\n", outputOBJPath, timer.ticks());
|
||||
std::string baseName = uSplit(UFile::getName(outputOBJPath), '.').front();
|
||||
texturing.saveAsOBJ(outputDirectory, baseName);
|
||||
UINFO("Saved %s. %fs", outputOBJPath, timer.ticks());
|
||||
|
||||
// generate textures
|
||||
UINFO("Generating textures...\n");
|
||||
UINFO("Generating textures...");
|
||||
texturing.generateTextures(mp, outputDirectory);
|
||||
UINFO("Generating textures done. %fs\n", timer.ticks());
|
||||
UINFO("Generating textures done. %fs", timer.ticks());
|
||||
|
||||
UINFO("Cleanup temporary directory \"%s\"...", tmpImageDirectory.c_str());
|
||||
UDirectory dir(tmpImageDirectory);
|
||||
@@ -2419,6 +2432,48 @@ bool multiBandTexturing(
|
||||
UDirectory::removeDir(tmpImageDirectory);
|
||||
UINFO("Cleanup temporary directory \"%s\"... done.", tmpImageDirectory.c_str());
|
||||
|
||||
UINFO("Rename/convert textures...");
|
||||
dir.setPath(outputDirectory, "png");
|
||||
std::map<std::string, std::string> texNames; // <old, new>
|
||||
std::string outputFormat = textureFormat;
|
||||
if(outputFormat.front() == '.')
|
||||
{
|
||||
outputFormat = outputFormat.substr(1, std::string::npos);
|
||||
}
|
||||
for(std::list<std::string>::const_iterator iter=dir.getFileNames().begin(); iter!=dir.getFileNames().end(); ++iter)
|
||||
{
|
||||
// Textures are called "texture_1001.png", "texture_1002.png", ...
|
||||
if(uStrContains(*iter, "texture_10"))
|
||||
{
|
||||
cv::Mat img = cv::imread(outputDirectory+"/"+*iter);
|
||||
if(contrastValues.first != 0.0f || contrastValues.second != 0.0f)
|
||||
{
|
||||
UASSERT(img.channels() == 3);
|
||||
// Re-use same contrast values with all images
|
||||
img.convertTo(img, -1, contrastValues.first, contrastValues.second);
|
||||
}
|
||||
std::string newName = *iter;
|
||||
boost::replace_all(newName, "png", outputFormat);
|
||||
boost::replace_all(newName, "texture", baseName);
|
||||
texNames.insert(std::make_pair(*iter, newName));
|
||||
cv::imwrite(outputDirectory+"/"+newName, img);
|
||||
UFile::erase(outputDirectory+"/"+*iter);
|
||||
}
|
||||
}
|
||||
std::ifstream fi(outputDirectory+"/"+baseName+".mtl");
|
||||
std::string mtlStr((std::istreambuf_iterator<char>(fi)),
|
||||
std::istreambuf_iterator<char>());
|
||||
fi.close();
|
||||
UFile::erase(outputDirectory+"/"+baseName);
|
||||
for(std::map<std::string, std::string>::iterator iter=texNames.begin(); iter!=texNames.end(); ++iter)
|
||||
{
|
||||
boost::replace_all(mtlStr, iter->first, iter->second);
|
||||
}
|
||||
std::ofstream fo(outputDirectory+"/"+baseName+".mtl");
|
||||
fo.write(mtlStr.c_str(), mtlStr.size());
|
||||
fo.close();
|
||||
UINFO("Rename/convert textures... done. %fs", timer.ticks());
|
||||
|
||||
return true;
|
||||
#else
|
||||
UERROR("Cannot unwrap texture mesh. RTAB-Map is not built with Alice Vision support! Returning false.");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
ADD_SUBDIRECTORY( BOWMapping )
|
||||
ADD_SUBDIRECTORY( Export )
|
||||
|
||||
IF(TARGET rtabmap_gui)
|
||||
ADD_SUBDIRECTORY( RGBDMapping )
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
IF(DEFINED PROJECT_NAME)
|
||||
set(internal TRUE)
|
||||
ENDIF(DEFINED PROJECT_NAME)
|
||||
|
||||
if(internal)
|
||||
# inside rtabmap project (see below for external build)
|
||||
SET(RTABMap_INCLUDE_DIRS
|
||||
${PROJECT_SOURCE_DIR}/utilite/include
|
||||
${PROJECT_SOURCE_DIR}/corelib/include
|
||||
)
|
||||
SET(RTABMap_LIBRARIES
|
||||
rtabmap_core
|
||||
rtabmap_utilite
|
||||
)
|
||||
else()
|
||||
# external build
|
||||
PROJECT( MyProject )
|
||||
|
||||
FIND_PACKAGE(RTABMap REQUIRED)
|
||||
FIND_PACKAGE(OpenCV REQUIRED)
|
||||
FIND_PACKAGE(PCL 1.7 REQUIRED)
|
||||
|
||||
endif()
|
||||
|
||||
if(POLICY CMP0020)
|
||||
cmake_policy(SET CMP0020 OLD)
|
||||
endif()
|
||||
|
||||
SET(INCLUDE_DIRS
|
||||
${RTABMap_INCLUDE_DIRS}
|
||||
${OpenCV_INCLUDE_DIRS}
|
||||
${PCL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
SET(LIBRARIES
|
||||
${RTABMap_LIBRARIES}
|
||||
${OpenCV_LIBRARIES}
|
||||
${PCL_LIBRARIES}
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
|
||||
|
||||
ADD_EXECUTABLE(export main.cpp)
|
||||
|
||||
TARGET_LINK_LIBRARIES(export ${LIBRARIES})
|
||||
|
||||
if(internal)
|
||||
SET_TARGET_PROPERTIES( export
|
||||
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-export)
|
||||
endif(internal)
|
||||
|
||||
INSTALL(TARGETS export
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
|
||||
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
|
||||
|
||||
|
||||
@@ -653,7 +653,7 @@ void ExportCloudsDialog::restoreDefaults()
|
||||
_ui->doubleSpinBox_cameraFilterVelRad->setValue(0);
|
||||
_ui->doubleSpinBox_laplacianVariance->setValue(0);
|
||||
_ui->spinBox_textureBrightnessContrastRatioLow->setValue(0);
|
||||
_ui->spinBox_textureBrightnessContrastRatioHigh->setValue(0);
|
||||
_ui->spinBox_textureBrightnessContrastRatioHigh->setValue(5);
|
||||
_ui->checkBox_exposureFusion->setChecked(false);
|
||||
_ui->checkBox_blending->setChecked(true);
|
||||
_ui->comboBox_blendingDecimation->setCurrentIndex(0);
|
||||
@@ -3840,10 +3840,15 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
cv::Mat globalTextures;
|
||||
bool texturesMerged = _ui->comboBox_meshingTextureSize->isEnabled() && _ui->comboBox_meshingTextureSize->currentIndex() > 0;
|
||||
if(texturesMerged && mesh->tex_materials.size()>1)
|
||||
{
|
||||
{
|
||||
_progressDialog->appendText(tr("Merging textures..."));
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
|
||||
std::map<int, std::map<int, cv::Vec4d> > gains;
|
||||
std::map<int, std::map<int, cv::Mat> > blendingGains;
|
||||
|
||||
std::pair<float, float> contrastValues(0,0);
|
||||
globalTextures = util3d::mergeTextures(
|
||||
*mesh,
|
||||
images,
|
||||
@@ -3851,7 +3856,7 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
0,
|
||||
_dbDriver,
|
||||
textureSize,
|
||||
_ui->spinBox_mesh_maxTextures->value(),
|
||||
_ui->checkBox_multiband->isEnabled() && _ui->checkBox_multiband->isChecked()?1:_ui->spinBox_mesh_maxTextures->value(),
|
||||
textureVertexToPixels,
|
||||
_ui->checkBox_gainCompensation->isChecked(),
|
||||
_ui->doubleSpinBox_gainBeta->value(),
|
||||
@@ -3864,17 +3869,25 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
0,
|
||||
0,
|
||||
&gains,
|
||||
&blendingGains);
|
||||
&blendingGains,
|
||||
&contrastValues);
|
||||
|
||||
_progressDialog->appendText(tr("Merging textures... done."));
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
|
||||
if(_ui->checkBox_multiband->isEnabled() && _ui->checkBox_multiband->isChecked() && mesh->tex_polygons.size() == 1)
|
||||
{
|
||||
pcl::PolygonMesh multibandMesh;
|
||||
multibandMesh.cloud = mesh->cloud;
|
||||
multibandMesh.polygons = mesh->tex_polygons[0];
|
||||
_progressDialog->appendText(tr("Multiband texturing... (this may take a couple of minutes!)"));
|
||||
QApplication::processEvents();
|
||||
uSleep(100);
|
||||
QApplication::processEvents();
|
||||
|
||||
success = util3d::multiBandTexturing(
|
||||
path.toStdString(),
|
||||
multibandMesh,
|
||||
mesh->cloud,
|
||||
mesh->tex_polygons[0],
|
||||
poses,
|
||||
textureVertexToPixels,
|
||||
images,
|
||||
@@ -3882,8 +3895,10 @@ void ExportCloudsDialog::saveTextureMeshes(
|
||||
0,
|
||||
_dbDriver,
|
||||
textureSize,
|
||||
_ui->comboBox_meshingTextureFormat->currentText().toStdString(),
|
||||
gains,
|
||||
blendingGains);
|
||||
blendingGains,
|
||||
contrastValues);
|
||||
if(success)
|
||||
{
|
||||
_progressDialog->incrementStep();
|
||||
|
||||
@@ -4741,6 +4741,13 @@ void MainWindow::openDatabase(const QString & path, const ParametersMap & overri
|
||||
different = false;
|
||||
}
|
||||
}
|
||||
else if(Parameters::getType(iter->first).compare("bool") == 0)
|
||||
{
|
||||
if(uStr2Bool(iter->second) == uStr2Bool(jter->second))
|
||||
{
|
||||
different = false;
|
||||
}
|
||||
}
|
||||
if(different)
|
||||
{
|
||||
differentParameters.insert(*iter);
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-1371</y>
|
||||
<y>0</y>
|
||||
<width>680</width>
|
||||
<height>3083</height>
|
||||
</rect>
|
||||
@@ -95,7 +95,7 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
<number>21</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_22">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
|
||||
@@ -16606,7 +16606,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="loopClosure_bowMinInliers">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
|
||||
@@ -10,6 +10,7 @@ ADD_SUBDIRECTORY( EurocDataset )
|
||||
ADD_SUBDIRECTORY( Recovery )
|
||||
ADD_SUBDIRECTORY( Reprocess )
|
||||
ADD_SUBDIRECTORY( DetectMoreLoopClosures )
|
||||
ADD_SUBDIRECTORY( Export )
|
||||
|
||||
IF(OPENCV_NONFREE_FOUND)
|
||||
ADD_SUBDIRECTORY( VocabularyComparison )
|
||||
|
||||
@@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <rtabmap/utilite/UMath.h>
|
||||
#include <rtabmap/utilite/UTimer.h>
|
||||
#include <rtabmap/utilite/UFile.h>
|
||||
#include <rtabmap/utilite/UStl.h>
|
||||
#include <pcl/filters/filter.h>
|
||||
#include <pcl/io/ply_io.h>
|
||||
#include <pcl/io/obj_io.h>
|
||||
@@ -54,7 +55,7 @@ void showUsage()
|
||||
" -i # Iterations (default 1).\n"
|
||||
" --intra Add only intra-session loop closures.\n"
|
||||
" --inter Add only inter-session loop closures.\n"
|
||||
"\n");
|
||||
"\n%s", Parameters::showUsage());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -98,7 +99,11 @@ int main(int argc, char * argv[])
|
||||
bool interSession = false;
|
||||
for(int i=1; i<argc-1; ++i)
|
||||
{
|
||||
if(std::strcmp(argv[i], "--intra") == 0)
|
||||
if(std::strcmp(argv[i], "--help") == 0)
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
else if(std::strcmp(argv[i], "--intra") == 0)
|
||||
{
|
||||
intraSession = true;
|
||||
if(interSession)
|
||||
@@ -151,6 +156,7 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
ParametersMap inputParams = Parameters::parseArguments(argc, argv);
|
||||
|
||||
std::string dbPath = argv[argc-1];
|
||||
if(!UFile::exists(dbPath))
|
||||
@@ -193,6 +199,7 @@ int main(int argc, char * argv[])
|
||||
// Get the global optimized map
|
||||
Rtabmap rtabmap;
|
||||
printf("Initialization...\n");
|
||||
uInsert(parameters, inputParams);
|
||||
rtabmap.init(parameters, dbPath);
|
||||
|
||||
PrintProgressState progress;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
SET(RTABMap_INCLUDE_DIRS
|
||||
${PROJECT_SOURCE_DIR}/utilite/include
|
||||
${PROJECT_SOURCE_DIR}/corelib/include
|
||||
)
|
||||
SET(RTABMap_LIBRARIES
|
||||
rtabmap_core
|
||||
rtabmap_utilite
|
||||
)
|
||||
|
||||
SET(INCLUDE_DIRS
|
||||
${RTABMap_INCLUDE_DIRS}
|
||||
${OpenCV_INCLUDE_DIRS}
|
||||
${PCL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
SET(LIBRARIES
|
||||
${RTABMap_LIBRARIES}
|
||||
${OpenCV_LIBRARIES}
|
||||
${PCL_LIBRARIES}
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
|
||||
|
||||
ADD_EXECUTABLE(export main.cpp)
|
||||
|
||||
TARGET_LINK_LIBRARIES(export ${LIBRARIES})
|
||||
|
||||
SET_TARGET_PROPERTIES( export
|
||||
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-export)
|
||||
|
||||
INSTALL(TARGETS export
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
|
||||
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
|
||||
|
||||
|
||||
@@ -52,18 +52,20 @@ void showUsage()
|
||||
"Options:\n"
|
||||
" --mesh Create a mesh.\n"
|
||||
" --texture Create a mesh with texture.\n"
|
||||
" --texture_size Texture size (default 4096.\n"
|
||||
" --texture_count Maximum textures generated (default 1).\n"
|
||||
" --texture_size # Texture size (default 4096).\n"
|
||||
" --texture_count # Maximum textures generated (default 1).\n"
|
||||
" --texture_range # Maximum camera range for texturing a polygon (default 0 meters: no limit).\n"
|
||||
" --ba Do global bundle adjustment before assembling the clouds.\n"
|
||||
" --no_gain Disable gain compensation when texturing.\n"
|
||||
" --no_blending Disable blending when texturing.\n"
|
||||
" --no_clean Disable cleaning colorless polygons.\n"
|
||||
" --multiband Enable multiband texturing (AliceVision dependency required).\n"
|
||||
" --poisson_depth # Set Poisson depth for mesh reconstruction.\n"
|
||||
" --max_polygons # Maximum polygons when creating a mesh (default 1000000, set 0 for no limit).\n"
|
||||
" --max_polygons # Maximum polygons when creating a mesh (default 500000, set 0 for no limit).\n"
|
||||
" --max_range # Maximum range of the created clouds (default 4 m).\n"
|
||||
" --decimation # Image decimation before creating the clouds (default 4).\n"
|
||||
" --decimation # Depth image decimation before creating the clouds (default 4).\n"
|
||||
" --voxel # Voxel size of the created clouds (default 0.01 m).\n"
|
||||
" --color_radius # Radius used to colorize polygons (default 0.05 m, set 0 for nearest color).\n"
|
||||
"\n%s", Parameters::showUsage());
|
||||
;
|
||||
exit(1);
|
||||
@@ -86,17 +88,22 @@ int main(int argc, char * argv[])
|
||||
bool doBlending = true;
|
||||
bool doClean = true;
|
||||
int poissonDepth = 0;
|
||||
int maxPolygons = 1000000;
|
||||
int maxPolygons = 500000;
|
||||
int decimation = 4;
|
||||
float maxRange = 4.0f;
|
||||
float voxelSize = 0.01f;
|
||||
int textureSize = 8192;
|
||||
int textureSize = 4096;
|
||||
int textureCount = 8;
|
||||
int textureRange = 0;
|
||||
bool multiband = false;
|
||||
ParametersMap params = Parameters::parseArguments(argc, argv, false);
|
||||
float colorRadius = 0.05;
|
||||
for(int i=1; i<argc-1; ++i)
|
||||
{
|
||||
if(std::strcmp(argv[i], "--mesh") == 0)
|
||||
if(std::strcmp(argv[i], "--help") == 0)
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
else if(std::strcmp(argv[i], "--mesh") == 0)
|
||||
{
|
||||
mesh = true;
|
||||
}
|
||||
@@ -129,6 +136,18 @@ int main(int argc, char * argv[])
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else if(std::strcmp(argv[i], "--texture_range") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i<argc-1)
|
||||
{
|
||||
textureRange = uStr2Int(argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else if(std::strcmp(argv[i], "--ba") == 0)
|
||||
{
|
||||
ba = true;
|
||||
@@ -147,7 +166,11 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
else if(std::strcmp(argv[i], "--multiband") == 0)
|
||||
{
|
||||
#ifdef RTABMAP_ALICE_VISION
|
||||
multiband = true;
|
||||
#else
|
||||
printf("\"--multiband\" option cannot be used vecause RTAB-Map is not built with AliceVision support. Ignoring multiband...\n");
|
||||
#endif
|
||||
}
|
||||
else if(std::strcmp(argv[i], "--poisson_depth") == 0)
|
||||
{
|
||||
@@ -209,7 +232,20 @@ int main(int argc, char * argv[])
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else if(std::strcmp(argv[i], "--color_radius") == 0)
|
||||
{
|
||||
++i;
|
||||
if(i<argc-1)
|
||||
{
|
||||
colorRadius = uStr2Float(argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
}
|
||||
ParametersMap params = Parameters::parseArguments(argc, argv, false);
|
||||
|
||||
std::string dbPath = argv[argc-1];
|
||||
|
||||
@@ -224,6 +260,7 @@ int main(int argc, char * argv[])
|
||||
else
|
||||
{
|
||||
UERROR("Cannot open database %s!", dbPath.c_str());
|
||||
return -1;
|
||||
}
|
||||
delete driver;
|
||||
|
||||
@@ -232,19 +269,24 @@ int main(int argc, char * argv[])
|
||||
printf("Added custom parameter %s=%s\n",iter->first.c_str(), iter->second.c_str());
|
||||
}
|
||||
|
||||
UTimer timer;
|
||||
|
||||
printf("Loading database \"%s\"...\n", dbPath.c_str());
|
||||
// Get the global optimized map
|
||||
Rtabmap rtabmap;
|
||||
uInsert(parameters, params);
|
||||
rtabmap.init(parameters, dbPath);
|
||||
printf("Loading database \"%s\"... done.\n", dbPath.c_str());
|
||||
printf("Loading database \"%s\"... done (%fs).\n", dbPath.c_str(), timer.ticks());
|
||||
|
||||
std::map<int, Signature> nodes;
|
||||
std::map<int, Transform> optimizedPoses;
|
||||
std::multimap<int, Link> links;
|
||||
printf("Optimizing the map...\n");
|
||||
rtabmap.get3DMap(nodes, optimizedPoses, links, true, true);
|
||||
printf("Optimizing the map... done.\n");
|
||||
printf("Optimizing the map... done (%fs).\n", timer.ticks());
|
||||
|
||||
std::string outputDirectory = UDirectory::getDir(dbPath);
|
||||
std::string baseName = uSplit(UFile::getName(dbPath), '.').front();
|
||||
|
||||
if(ba)
|
||||
{
|
||||
@@ -261,7 +303,7 @@ int main(int argc, char * argv[])
|
||||
cameraSingleModels.insert(std::make_pair(iter->first, node.sensorData().cameraModels().front()));
|
||||
}
|
||||
optimizedPoses = g2o.optimizeBA(optimizedPoses.begin()->first, optimizedPoses, links, cameraSingleModels, points3DMap, wordReferences);
|
||||
printf("Global bundle adjustment... done.\n");
|
||||
printf("Global bundle adjustment... done (%fs).\n", timer.ticks());
|
||||
}
|
||||
|
||||
// Construct the cloud
|
||||
@@ -317,7 +359,7 @@ int main(int argc, char * argv[])
|
||||
cameraDepths.insert(std::make_pair(iter->first, depth));
|
||||
}
|
||||
}
|
||||
printf("Create and assemble the clouds... done.\n");
|
||||
printf("Create and assemble the clouds... done (%fs, %d points).\n", timer.ticks(), (int)mergedClouds->size());
|
||||
|
||||
if(mergedClouds->size())
|
||||
{
|
||||
@@ -326,9 +368,10 @@ int main(int argc, char * argv[])
|
||||
printf("Voxel grid filtering of the assembled cloud (voxel=%f, %d points)\n", 0.01f, (int)mergedClouds->size());
|
||||
mergedClouds = util3d::voxelize(mergedClouds, voxelSize);
|
||||
|
||||
printf("Saving cloud.ply... (%d points)\n", (int)mergedClouds->size());
|
||||
pcl::io::savePLYFile("cloud.ply", *mergedClouds);
|
||||
printf("Saving cloud.ply... done!\n");
|
||||
std::string outputPath=outputDirectory+"/"+baseName+"_cloud.ply";
|
||||
printf("Saving %s... (%d points)\n", outputPath.c_str(), (int)mergedClouds->size());
|
||||
pcl::io::savePLYFile(outputPath, *mergedClouds);
|
||||
printf("Saving %s... done!\n", outputPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -355,9 +398,8 @@ int main(int argc, char * argv[])
|
||||
pcl::Poisson<pcl::PointXYZRGBNormal> poisson;
|
||||
poisson.setDepth(optimizedDepth);
|
||||
poisson.setInputCloud(mergedClouds);
|
||||
UTimer timer;
|
||||
poisson.reconstruct(*mesh);
|
||||
printf("Mesh reconstruction... done! %fs (%d polygons)\n", timer.ticks(), (int)mesh->polygons.size());
|
||||
printf("Mesh reconstruction... done (%fs, %d polygons).\n", timer.ticks(), (int)mesh->polygons.size());
|
||||
|
||||
if(mesh->polygons.size())
|
||||
{
|
||||
@@ -366,15 +408,17 @@ int main(int argc, char * argv[])
|
||||
0.0f,
|
||||
maxPolygons,
|
||||
mergedClouds,
|
||||
doClean?0.05:0,
|
||||
colorRadius,
|
||||
!texture,
|
||||
doClean);
|
||||
doClean,
|
||||
200);
|
||||
|
||||
if(!texture)
|
||||
{
|
||||
printf("Saving mesh.ply...\n");
|
||||
pcl::io::savePLYFile("mesh.ply", *mesh);
|
||||
printf("Saving mesh.ply... done!\n");
|
||||
std::string outputPath=outputDirectory+"/"+baseName+"_mesh.ply";
|
||||
printf("Saving %s...\n", outputPath.c_str());
|
||||
pcl::io::savePLYFile(outputPath, *mesh);
|
||||
printf("Saving %s... done!\n", outputPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -385,28 +429,36 @@ int main(int argc, char * argv[])
|
||||
cameraPoses,
|
||||
cameraModels,
|
||||
cameraDepths,
|
||||
3,
|
||||
textureRange,
|
||||
0.0f,
|
||||
0.0f,
|
||||
50,
|
||||
multiband?0:50, // Min polygons in camera view to be textured by this camera
|
||||
std::vector<float>(),
|
||||
0,
|
||||
&vertexToPixels);
|
||||
printf("Texturing... done! %fs\n", timer.ticks());
|
||||
printf("Texturing... done (%fs).\n", timer.ticks());
|
||||
|
||||
// Remove occluded polygons (polygons with no texture)
|
||||
if(doClean && textureMesh->tex_coordinates.size())
|
||||
{
|
||||
printf("Cleanup mesh...\n");
|
||||
rtabmap::util3d::cleanTextureMesh(*textureMesh, 0);
|
||||
printf("Cleanup mesh... done! %fs\n", timer.ticks());
|
||||
rtabmap::util3d::cleanTextureMesh(*textureMesh, 100); // Min polygons in a cluster to keep them
|
||||
printf("Cleanup mesh... done (%fs).\n", timer.ticks());
|
||||
}
|
||||
|
||||
if(textureMesh->tex_materials.size())
|
||||
{
|
||||
printf("Merging %d textures...\n", (int)textureMesh->tex_materials.size());
|
||||
if(multiband)
|
||||
{
|
||||
printf("Merging %d texture(s) to single one (multiband enabled)...\n", (int)textureMesh->tex_materials.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Merging %d texture(s)... (%d max textures)\n", (int)textureMesh->tex_materials.size(), textureCount);
|
||||
}
|
||||
std::map<int, std::map<int, cv::Vec4d> > gains;
|
||||
std::map<int, std::map<int, cv::Mat> > blendingGains;
|
||||
std::pair<float, float> contrastValues(0,0);
|
||||
cv::Mat textures = rtabmap::util3d::mergeTextures(
|
||||
*textureMesh,
|
||||
std::map<int, cv::Mat>(),
|
||||
@@ -414,14 +466,18 @@ int main(int argc, char * argv[])
|
||||
rtabmap.getMemory(),
|
||||
0,
|
||||
textureSize,
|
||||
textureCount,
|
||||
multiband?1:textureCount, // to get contrast values based on all images in multiband mode
|
||||
vertexToPixels,
|
||||
doGainCompensation, 10.0f, true ,doBlending, 0, 0, 0, false,
|
||||
0,
|
||||
0,
|
||||
doGainCompensation, 1.0f, true,
|
||||
doBlending, 0,
|
||||
0, 10, // low-high brightness/contrast balance
|
||||
false, // exposure fusion
|
||||
0, // state
|
||||
0, // blank value (0=black)
|
||||
&gains,
|
||||
&blendingGains);
|
||||
printf("Merging %d textures... done. %fs\n", (int)textureMesh->tex_materials.size(), timer.ticks());
|
||||
&blendingGains,
|
||||
&contrastValues);
|
||||
printf("Merging to %d texture(s)... done (%fs).\n", (int)textureMesh->tex_materials.size(), timer.ticks());
|
||||
|
||||
// TextureMesh OBJ
|
||||
bool success = false;
|
||||
@@ -444,29 +500,28 @@ int main(int argc, char * argv[])
|
||||
if(success)
|
||||
{
|
||||
|
||||
std::string filePath = "mesh.obj";
|
||||
printf("Saving obj (%d vertices) to %s.\n", (int)textureMesh->cloud.data.size()/textureMesh->cloud.point_step, filePath.c_str());
|
||||
success = pcl::io::saveOBJFile(filePath, *textureMesh) == 0;
|
||||
std::string outputPath=outputDirectory+"/"+baseName+"_mesh.obj";
|
||||
printf("Saving obj (%d vertices) to %s.\n", (int)textureMesh->cloud.data.size()/textureMesh->cloud.point_step, outputPath.c_str());
|
||||
success = pcl::io::saveOBJFile(outputPath, *textureMesh) == 0;
|
||||
|
||||
if(success)
|
||||
{
|
||||
printf("Saved obj to %s!\n", filePath.c_str());
|
||||
printf("Saved obj to %s!\n", outputPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
UERROR("Failed saving obj to %s!", filePath.c_str());
|
||||
UERROR("Failed saving obj to %s!", outputPath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(multiband)
|
||||
{
|
||||
#ifndef RTABMAP_ALICE_VISION
|
||||
UERROR("Cannot use --unwrap option, RTAB-Map is not built with AliceVision support.");
|
||||
#else
|
||||
timer.restart();
|
||||
printf("MultiBand texturing... \"mesh_multiband.obj\"\n");
|
||||
if(util3d::multiBandTexturing("mesh_multiband.obj",
|
||||
*mesh,
|
||||
std::string outputPath=outputDirectory+"/"+baseName+"_mesh_multiband.obj";
|
||||
printf("MultiBand texturing... \"%s\"\n", outputPath.c_str());
|
||||
if(util3d::multiBandTexturing(outputPath,
|
||||
textureMesh->cloud,
|
||||
textureMesh->tex_polygons[0],
|
||||
cameraPoses,
|
||||
vertexToPixels,
|
||||
std::map<int, cv::Mat >(),
|
||||
@@ -474,16 +529,17 @@ int main(int argc, char * argv[])
|
||||
rtabmap.getMemory(),
|
||||
0,
|
||||
textureSize,
|
||||
"jpg",
|
||||
gains,
|
||||
blendingGains))
|
||||
blendingGains,
|
||||
contrastValues))
|
||||
{
|
||||
printf("MultiBand texturing...done. %fs\n", timer.ticks());
|
||||
printf("MultiBand texturing...done (%fs).\n", timer.ticks());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("MultiBand texturing...failed! %fs\n", timer.ticks());
|
||||
printf("MultiBand texturing...failed! (%fs)\n", timer.ticks());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user