mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-04 16:57:46 +08:00
Export: fixed white squares in exported texture (shifting next tex coords to wrong sub texture). Transfer color radius option use nearest point when =0. Fixed a crash on export dense with texture when last materials are not used (they have no polygons associated).
This commit is contained in:
@@ -1824,7 +1824,7 @@ void concatenateTextureMaterials(pcl::TextureMesh & mesh, const cv::Size & image
|
|||||||
UDEBUG("scaledWidth=%f scaledHeight=%f lowerBorderSize=%f", scaledWidth, scaledHeight, lowerBorderSize);
|
UDEBUG("scaledWidth=%f scaledHeight=%f lowerBorderSize=%f", scaledWidth, scaledHeight, lowerBorderSize);
|
||||||
if(materialsKept)
|
if(materialsKept)
|
||||||
{
|
{
|
||||||
materialsKept->resize(mesh.tex_materials.size(), 0);
|
materialsKept->resize(mesh.tex_materials.size(), false);
|
||||||
}
|
}
|
||||||
for(unsigned int t=0; t<mesh.tex_materials.size(); ++t)
|
for(unsigned int t=0; t<mesh.tex_materials.size(); ++t)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ void ExportCloudsDialog::restoreDefaults()
|
|||||||
_ui->doubleSpinBox_gp3Radius->setValue(0.2);
|
_ui->doubleSpinBox_gp3Radius->setValue(0.2);
|
||||||
_ui->doubleSpinBox_gp3Mu->setValue(2.5);
|
_ui->doubleSpinBox_gp3Mu->setValue(2.5);
|
||||||
_ui->doubleSpinBox_meshDecimationFactor->setValue(0.0);
|
_ui->doubleSpinBox_meshDecimationFactor->setValue(0.0);
|
||||||
_ui->doubleSpinBox_transferColorRadius->setValue(0.2);
|
_ui->doubleSpinBox_transferColorRadius->setValue(0.0);
|
||||||
_ui->checkBox_cleanMesh->setChecked(true);
|
_ui->checkBox_cleanMesh->setChecked(true);
|
||||||
|
|
||||||
_ui->comboBox_meshingApproach->setCurrentIndex(1);
|
_ui->comboBox_meshingApproach->setCurrentIndex(1);
|
||||||
@@ -1356,10 +1356,10 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
}
|
}
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
|
|
||||||
if(_ui->doubleSpinBox_transferColorRadius->value() > 0.0 &&
|
if(_ui->doubleSpinBox_transferColorRadius->value() >= 0.0 &&
|
||||||
(!_ui->checkBox_textureMapping->isEnabled() || !_ui->checkBox_textureMapping->isChecked()))
|
(!_ui->checkBox_textureMapping->isEnabled() || !_ui->checkBox_textureMapping->isChecked()))
|
||||||
{
|
{
|
||||||
_progressDialog->appendText(tr("Transfering color from point cloud to mesh..."));
|
_progressDialog->appendText(tr("Transferring color from point cloud to mesh..."));
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
|
|
||||||
// transfer color from point cloud to mesh
|
// transfer color from point cloud to mesh
|
||||||
@@ -1375,7 +1375,14 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
pt.x = coloredCloud->at(i).x;
|
pt.x = coloredCloud->at(i).x;
|
||||||
pt.y = coloredCloud->at(i).y;
|
pt.y = coloredCloud->at(i).y;
|
||||||
pt.z = coloredCloud->at(i).z;
|
pt.z = coloredCloud->at(i).z;
|
||||||
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
if(_ui->doubleSpinBox_transferColorRadius->value() > 0.0)
|
||||||
|
{
|
||||||
|
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tree->nearestKSearch(pt, 1, kIndices, kDistances);
|
||||||
|
}
|
||||||
if(kIndices.size())
|
if(kIndices.size())
|
||||||
{
|
{
|
||||||
coloredCloud->at(i).r = mergedClouds->at(kIndices[0]).r;
|
coloredCloud->at(i).r = mergedClouds->at(kIndices[0]).r;
|
||||||
@@ -1469,10 +1476,10 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(lostColors &&
|
if(lostColors &&
|
||||||
_ui->doubleSpinBox_transferColorRadius->value() > 0.0 &&
|
_ui->doubleSpinBox_transferColorRadius->value() >= 0.0 &&
|
||||||
(!_ui->checkBox_textureMapping->isEnabled() || !_ui->checkBox_textureMapping->isChecked()))
|
(!_ui->checkBox_textureMapping->isEnabled() || !_ui->checkBox_textureMapping->isChecked()))
|
||||||
{
|
{
|
||||||
_progressDialog->appendText(tr("Transfering color from point cloud to mesh..."));
|
_progressDialog->appendText(tr("Transferring color from point cloud to mesh..."));
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
|
|
||||||
// transfer color from point cloud to mesh
|
// transfer color from point cloud to mesh
|
||||||
@@ -1489,7 +1496,14 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
pt.x = coloredCloud->at(i).x;
|
pt.x = coloredCloud->at(i).x;
|
||||||
pt.y = coloredCloud->at(i).y;
|
pt.y = coloredCloud->at(i).y;
|
||||||
pt.z = coloredCloud->at(i).z;
|
pt.z = coloredCloud->at(i).z;
|
||||||
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
if(_ui->doubleSpinBox_transferColorRadius->value() > 0.0)
|
||||||
|
{
|
||||||
|
tree->radiusSearch(pt, _ui->doubleSpinBox_transferColorRadius->value(), kIndices, kDistances);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tree->nearestKSearch(pt, 1, kIndices, kDistances);
|
||||||
|
}
|
||||||
if(kIndices.size())
|
if(kIndices.size())
|
||||||
{
|
{
|
||||||
coloredCloud->at(i).r = iter->second->at(kIndices[0]).r;
|
coloredCloud->at(i).r = iter->second->at(kIndices[0]).r;
|
||||||
@@ -1754,7 +1768,6 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
unsigned int allPolygonsIndex = 0;
|
unsigned int allPolygonsIndex = 0;
|
||||||
for(unsigned int t=0; t<textureMesh->tex_polygons.size(); ++t)
|
for(unsigned int t=0; t<textureMesh->tex_polygons.size(); ++t)
|
||||||
{
|
{
|
||||||
UASSERT(allPolygonsIndex < allPolygons.size());
|
|
||||||
std::vector<pcl::Vertices> filteredPolygons(textureMesh->tex_polygons[t].size());
|
std::vector<pcl::Vertices> filteredPolygons(textureMesh->tex_polygons[t].size());
|
||||||
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
#if PCL_VERSION_COMPARE(>=, 1, 8, 0)
|
||||||
std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > filteredCoordinates(textureMesh->tex_coordinates[t].size());
|
std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > filteredCoordinates(textureMesh->tex_coordinates[t].size());
|
||||||
@@ -1764,6 +1777,8 @@ bool ExportCloudsDialog::getExportedClouds(
|
|||||||
|
|
||||||
if(textureMesh->tex_polygons[t].size())
|
if(textureMesh->tex_polygons[t].size())
|
||||||
{
|
{
|
||||||
|
UASSERT_MSG(allPolygonsIndex < allPolygons.size(), uFormat("%d vs %d", (int)allPolygonsIndex, (int)allPolygons.size()).c_str());
|
||||||
|
|
||||||
// make index polygon to coordinate
|
// make index polygon to coordinate
|
||||||
std::vector<unsigned int> polygonToCoord(textureMesh->tex_polygons[t].size());
|
std::vector<unsigned int> polygonToCoord(textureMesh->tex_polygons[t].size());
|
||||||
unsigned int totalCoord = 0;
|
unsigned int totalCoord = 0;
|
||||||
@@ -2420,7 +2435,8 @@ cv::Mat ExportCloudsDialog::mergeTextures(pcl::TextureMesh & mesh, const QMap<in
|
|||||||
{
|
{
|
||||||
float scale = 0.0f;
|
float scale = 0.0f;
|
||||||
UDEBUG("");
|
UDEBUG("");
|
||||||
util3d::concatenateTextureMaterials(mesh, imageSize, textureSize, scale);
|
std::vector<bool> materialsKept;
|
||||||
|
util3d::concatenateTextureMaterials(mesh, imageSize, textureSize, scale, &materialsKept);
|
||||||
if(scale && mesh.tex_materials.size()==1)
|
if(scale && mesh.tex_materials.size()==1)
|
||||||
{
|
{
|
||||||
int cols = float(textureSize)/(scale*imageSize.width);
|
int cols = float(textureSize)/(scale*imageSize.width);
|
||||||
@@ -2429,31 +2445,36 @@ cv::Mat ExportCloudsDialog::mergeTextures(pcl::TextureMesh & mesh, const QMap<in
|
|||||||
|
|
||||||
// make a blank texture
|
// make a blank texture
|
||||||
cv::Mat emptyImage(int(imageSize.height*scale), int(imageSize.width*scale), imageType, cv::Scalar::all(255));
|
cv::Mat emptyImage(int(imageSize.height*scale), int(imageSize.width*scale), imageType, cv::Scalar::all(255));
|
||||||
for(int i=0; i<(int)textures.size(); ++i)
|
int oi=0;
|
||||||
|
for(int t=0; t<(int)textures.size(); ++t)
|
||||||
{
|
{
|
||||||
int u = i%cols * emptyImage.cols;
|
if(materialsKept.at(t))
|
||||||
int v = i/cols * emptyImage.rows;
|
|
||||||
UASSERT(u < textureSize-emptyImage.cols);
|
|
||||||
UASSERT(v < textureSize-emptyImage.rows);
|
|
||||||
if(textures[i]>=0)
|
|
||||||
{
|
{
|
||||||
QMap<int, Signature>::const_iterator iter = cachedSignatures.find(textures[i]);
|
int u = oi%cols * emptyImage.cols;
|
||||||
UASSERT(iter!=cachedSignatures.end() && !iter->sensorData().imageCompressed().empty());
|
int v = oi/cols * emptyImage.rows;
|
||||||
cv::Mat image;
|
UASSERT(u < textureSize-emptyImage.cols);
|
||||||
iter->sensorData().uncompressDataConst(&image, 0);
|
UASSERT(v < textureSize-emptyImage.rows);
|
||||||
UASSERT(!image.empty());
|
if(textures[t]>=0)
|
||||||
cv::Mat resizedImage;
|
|
||||||
cv::resize(image, resizedImage, emptyImage.size(), 0.0f, 0.0f, cv::INTER_AREA);
|
|
||||||
if(_ui->groupBox_gain->isChecked() && _compensator && _compensator->getIndex(textures[i]) >= 0)
|
|
||||||
{
|
{
|
||||||
_compensator->apply(textures[i], resizedImage);
|
QMap<int, Signature>::const_iterator iter = cachedSignatures.find(textures[t]);
|
||||||
|
UASSERT(iter!=cachedSignatures.end() && !iter->sensorData().imageCompressed().empty());
|
||||||
|
cv::Mat image;
|
||||||
|
iter->sensorData().uncompressDataConst(&image, 0);
|
||||||
|
UASSERT(!image.empty());
|
||||||
|
cv::Mat resizedImage;
|
||||||
|
cv::resize(image, resizedImage, emptyImage.size(), 0.0f, 0.0f, cv::INTER_AREA);
|
||||||
|
if(_ui->groupBox_gain->isChecked() && _compensator && _compensator->getIndex(textures[t]) >= 0)
|
||||||
|
{
|
||||||
|
_compensator->apply(textures[t], resizedImage);
|
||||||
|
}
|
||||||
|
UASSERT(resizedImage.type() == globalTexture.type());
|
||||||
|
resizedImage.copyTo(globalTexture(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
||||||
}
|
}
|
||||||
UASSERT(resizedImage.type() == globalTexture.type());
|
else
|
||||||
resizedImage.copyTo(globalTexture(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
{
|
||||||
}
|
emptyImage.copyTo(globalTexture(cv::Rect(u, v, emptyImage.cols, emptyImage.rows)));
|
||||||
else
|
}
|
||||||
{
|
++oi;
|
||||||
emptyImage.copyTo(globalTexture(cv::Rect(u, v, emptyImage.cols, emptyImage.rows)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>-1356</y>
|
<y>-1534</y>
|
||||||
<width>773</width>
|
<width>773</width>
|
||||||
<height>2832</height>
|
<height>2832</height>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -1118,7 +1118,7 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
|||||||
<item row="5" column="1">
|
<item row="5" column="1">
|
||||||
<widget class="QLabel" name="label_meshDecimation_2">
|
<widget class="QLabel" name="label_meshDecimation_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Radius used to transfer color from original cloud to resampled reconstructed surface (e.g., Poisson or mesh decimation). 0 means disabled.</string>
|
<string>Radius used to transfer color from original cloud to resampled reconstructed surface (e.g., Poisson or mesh decimation). Negative means disabled, 0 means take the nearest point.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@@ -1228,7 +1228,7 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
|
|||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>0.000000000000000</double>
|
<double>-1.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>10.000000000000000</double>
|
<double>10.000000000000000</double>
|
||||||
|
|||||||
Reference in New Issue
Block a user