Export: Added exposure fusion option

This commit is contained in:
matlabbe
2017-03-30 21:33:15 -04:00
parent f33b838204
commit accbe5a423
4 changed files with 130 additions and 51 deletions

View File

@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <rtabmap/core/Transform.h> #include <rtabmap/core/Transform.h>
#include <rtabmap/core/Parameters.h> #include <rtabmap/core/Parameters.h>
#include <vector>
namespace rtabmap namespace rtabmap
{ {
@@ -148,6 +149,9 @@ cv::Mat RTABMAP_EXP brightnessAndContrastAuto(
float clipLowHistPercent=0, float clipLowHistPercent=0,
float clipHighHistPercent=0); float clipHighHistPercent=0);
cv::Mat RTABMAP_EXP exposureFusion(
const std::vector<cv::Mat> & images);
} // namespace util3d } // namespace util3d
} // namespace rtabmap } // namespace rtabmap

View File

@@ -41,6 +41,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map> #include <map>
#include <Eigen/Core> #include <Eigen/Core>
#if CV_MAJOR_VERSION >= 3
#include <opencv2/photo/photo.hpp>
#endif
namespace rtabmap namespace rtabmap
{ {
@@ -1992,6 +1996,26 @@ cv::Mat brightnessAndContrastAuto(const cv::Mat &src, const cv::Mat & mask, floa
return dst; return dst;
} }
cv::Mat exposureFusion(const std::vector<cv::Mat> & images)
{
UASSERT(images.size());
cv::Mat fusion;
#if CV_MAJOR_VERSION >= 3
cv::createMergeMertens()->process(images, fusion);
cv::Mat rgb8;
UASSERT(fusion.channels() == 3);
fusion.convertTo(rgb8, CV_8UC3, 255.0);
fusion = rgb8;
#else
UWARN("Exposure fusion is only avaiable when rtabmap is built with OpenCV3.");
if (images.size())
{
fusion = images[0].clone();
}
#endif
return fusion;
}
} }
} }

View File

@@ -136,6 +136,7 @@ ExportCloudsDialog::ExportCloudsDialog(QWidget *parent) :
connect(_ui->checkBox_gainFull, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); connect(_ui->checkBox_gainFull, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->spinBox_textureBrightnessContrastRatioLow, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); connect(_ui->spinBox_textureBrightnessContrastRatioLow, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->spinBox_textureBrightnessContrastRatioHigh, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); connect(_ui->spinBox_textureBrightnessContrastRatioHigh, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_exposureFusion, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged())); connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SIGNAL(configChanged()));
connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor())); connect(_ui->checkBox_meshing, SIGNAL(stateChanged(int)), this, SLOT(updateReconstructionFlavor()));
@@ -281,6 +282,7 @@ void ExportCloudsDialog::saveSettings(QSettings & settings, const QString & grou
settings.setValue("mesh_textureCameraFilteringAngle", _ui->doubleSpinBox_cameraFilterAngle->value()); settings.setValue("mesh_textureCameraFilteringAngle", _ui->doubleSpinBox_cameraFilterAngle->value());
settings.setValue("mesh_textureBrightnessConstrastRatioLow", _ui->spinBox_textureBrightnessContrastRatioLow->value()); settings.setValue("mesh_textureBrightnessConstrastRatioLow", _ui->spinBox_textureBrightnessContrastRatioLow->value());
settings.setValue("mesh_textureBrightnessConstrastRatioHigh", _ui->spinBox_textureBrightnessContrastRatioHigh->value()); settings.setValue("mesh_textureBrightnessConstrastRatioHigh", _ui->spinBox_textureBrightnessContrastRatioHigh->value());
settings.setValue("mesh_textureExposureFusion", _ui->checkBox_exposureFusion->isChecked());
settings.setValue("mesh_angle_tolerance", _ui->doubleSpinBox_mesh_angleTolerance->value()); settings.setValue("mesh_angle_tolerance", _ui->doubleSpinBox_mesh_angleTolerance->value());
@@ -376,6 +378,7 @@ void ExportCloudsDialog::loadSettings(QSettings & settings, const QString & grou
_ui->doubleSpinBox_cameraFilterAngle->setValue(settings.value("mesh_textureCameraFilteringAngle", _ui->doubleSpinBox_cameraFilterAngle->value()).toDouble()); _ui->doubleSpinBox_cameraFilterAngle->setValue(settings.value("mesh_textureCameraFilteringAngle", _ui->doubleSpinBox_cameraFilterAngle->value()).toDouble());
_ui->spinBox_textureBrightnessContrastRatioLow->setValue(settings.value("mesh_textureBrightnessConstrastRatioLow", _ui->spinBox_textureBrightnessContrastRatioLow->value()).toDouble()); _ui->spinBox_textureBrightnessContrastRatioLow->setValue(settings.value("mesh_textureBrightnessConstrastRatioLow", _ui->spinBox_textureBrightnessContrastRatioLow->value()).toDouble());
_ui->spinBox_textureBrightnessContrastRatioHigh->setValue(settings.value("mesh_textureBrightnessConstrastRatioHigh", _ui->spinBox_textureBrightnessContrastRatioHigh->value()).toDouble()); _ui->spinBox_textureBrightnessContrastRatioHigh->setValue(settings.value("mesh_textureBrightnessConstrastRatioHigh", _ui->spinBox_textureBrightnessContrastRatioHigh->value()).toDouble());
_ui->checkBox_exposureFusion->setChecked(settings.value("mesh_textureExposureFusion", _ui->checkBox_exposureFusion->isChecked()).toBool());
_ui->doubleSpinBox_mesh_angleTolerance->setValue(settings.value("mesh_angle_tolerance", _ui->doubleSpinBox_mesh_angleTolerance->value()).toDouble()); _ui->doubleSpinBox_mesh_angleTolerance->setValue(settings.value("mesh_angle_tolerance", _ui->doubleSpinBox_mesh_angleTolerance->value()).toDouble());
_ui->checkBox_mesh_quad->setChecked(settings.value("mesh_quad", _ui->checkBox_mesh_quad->isChecked()).toBool()); _ui->checkBox_mesh_quad->setChecked(settings.value("mesh_quad", _ui->checkBox_mesh_quad->isChecked()).toBool());
@@ -468,6 +471,7 @@ void ExportCloudsDialog::restoreDefaults()
_ui->doubleSpinBox_cameraFilterAngle->setValue(30); _ui->doubleSpinBox_cameraFilterAngle->setValue(30);
_ui->spinBox_textureBrightnessContrastRatioLow->setValue(0); _ui->spinBox_textureBrightnessContrastRatioLow->setValue(0);
_ui->spinBox_textureBrightnessContrastRatioHigh->setValue(0); _ui->spinBox_textureBrightnessContrastRatioHigh->setValue(0);
_ui->checkBox_exposureFusion->setChecked(false);
_ui->doubleSpinBox_mesh_angleTolerance->setValue(15.0); _ui->doubleSpinBox_mesh_angleTolerance->setValue(15.0);
_ui->checkBox_mesh_quad->setChecked(false); _ui->checkBox_mesh_quad->setChecked(false);
@@ -2777,7 +2781,37 @@ cv::Mat ExportCloudsDialog::mergeTextures(pcl::TextureMesh & mesh, const QMap<in
} }
if(_ui->spinBox_textureBrightnessContrastRatioLow->value() > 0 || _ui->spinBox_textureBrightnessContrastRatioHigh->value() > 0) if(_ui->spinBox_textureBrightnessContrastRatioLow->value() > 0 || _ui->spinBox_textureBrightnessContrastRatioHigh->value() > 0)
{ {
globalTexture = util2d::brightnessAndContrastAuto(globalTexture, globalTextureMask, (float)_ui->spinBox_textureBrightnessContrastRatioLow->value(), (float)_ui->spinBox_textureBrightnessContrastRatioHigh->value()); if(_ui->checkBox_exposureFusion->isChecked())
{
std::vector<cv::Mat> images;
images.push_back(globalTexture);
if (_ui->spinBox_textureBrightnessContrastRatioLow->value() > 0)
{
images.push_back(util2d::brightnessAndContrastAuto(
globalTexture,
globalTextureMask,
(float)_ui->spinBox_textureBrightnessContrastRatioLow->value(),
0.0f));
}
if (_ui->spinBox_textureBrightnessContrastRatioHigh->value() > 0)
{
images.push_back(util2d::brightnessAndContrastAuto(
globalTexture,
globalTextureMask,
0.0f,
(float)_ui->spinBox_textureBrightnessContrastRatioHigh->value()));
}
globalTexture = util2d::exposureFusion(images);
}
else
{
globalTexture = util2d::brightnessAndContrastAuto(
globalTexture,
globalTextureMask,
(float)_ui->spinBox_textureBrightnessContrastRatioLow->value(),
(float)_ui->spinBox_textureBrightnessContrastRatioHigh->value());
}
} }
} }
} }

View File

@@ -23,9 +23,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>-1454</y> <y>-1293</y>
<width>773</width> <width>777</width>
<height>3289</height> <height>2373</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_13"> <layout class="QVBoxLayout" name="verticalLayout_13">
@@ -1407,6 +1407,23 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</item> </item>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QLabel" name="label_meshingTextureSize">
<property name="text">
<string>Output texture size. If not set or when clouds are not assembled, all textures are saved separately. Warning: values higher than 2048 may not be compatible with all GPUs.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_cameraFilter">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QComboBox" name="comboBox_meshingTextureSize"> <widget class="QComboBox" name="comboBox_meshingTextureSize">
<item> <item>
@@ -1456,23 +1473,26 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</item> </item>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="5" column="1">
<widget class="QLabel" name="label_meshingTextureSize"> <widget class="QLabel" name="label_meshingTextureSize_5">
<property name="text"> <property name="text">
<string>Output texture size. If not set or when clouds are not assembled, all textures are saved separately. Warning: values higher than 2048 may not be compatible with all GPUs.</string> <string>Brightness and contrast balance low ratio. Only used when textures are merged.</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="6" column="0">
<widget class="QLabel" name="label_meshingTextureSize_2"> <widget class="QSpinBox" name="spinBox_textureBrightnessContrastRatioHigh">
<property name="text"> <property name="suffix">
<string>Maximum distance from the camera for polygons to be textured by this camera (0 means infinite). Only used with dense reconstruction flavor.</string> <string> %</string>
</property> </property>
<property name="wordWrap"> <property name="minimum">
<bool>true</bool> <number>0</number>
</property>
<property name="maximum">
<number>49</number>
</property> </property>
</widget> </widget>
</item> </item>
@@ -1496,6 +1516,29 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QSpinBox" name="spinBox_textureBrightnessContrastRatioLow">
<property name="suffix">
<string> %</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>49</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_meshingTextureSize_2">
<property name="text">
<string>Maximum distance from the camera for polygons to be textured by this camera (0 means infinite). Only used with dense reconstruction flavor.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_meshingTextureMaxDistance"> <widget class="QDoubleSpinBox" name="doubleSpinBox_meshingTextureMaxDistance">
<property name="suffix"> <property name="suffix">
@@ -1518,36 +1561,6 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBox_cameraFilter">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_meshingTextureSize_5">
<property name="text">
<string>Brightness and contrast balance low ratio. Only used when textures are merged.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QSpinBox" name="spinBox_textureBrightnessContrastRatioLow">
<property name="suffix">
<string> %</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>49</number>
</property>
</widget>
</item>
<item row="6" column="1"> <item row="6" column="1">
<widget class="QLabel" name="label_meshingTextureSize_6"> <widget class="QLabel" name="label_meshingTextureSize_6">
<property name="text"> <property name="text">
@@ -1558,16 +1571,20 @@ Guidelines: 4 times the voxel size, 0.025 for voxel=0.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0"> <item row="7" column="1">
<widget class="QSpinBox" name="spinBox_textureBrightnessContrastRatioHigh"> <widget class="QLabel" name="label_meshingTextureSize_7">
<property name="suffix"> <property name="text">
<string> %</string> <string>Exposure fusion. Only used when textures are merged and brightness/contrast balance ratios are used (merging original texture + 1 for each ratios).</string>
</property> </property>
<property name="minimum"> <property name="wordWrap">
<number>0</number> <bool>true</bool>
</property> </property>
<property name="maximum"> </widget>
<number>49</number> </item>
<item row="7" column="0">
<widget class="QCheckBox" name="checkBox_exposureFusion">
<property name="text">
<string/>
</property> </property>
</widget> </widget>
</item> </item>