mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-19 19:14:42 +00:00
dellepiane: porting of arc3D filter to edit
This commit is contained in:
parent
3c6652dd2f
commit
810e38942f
376
src/plugins_experimental/edit_epoch/edit_epoch.cpp
Normal file
376
src/plugins_experimental/edit_epoch/edit_epoch.cpp
Normal file
@ -0,0 +1,376 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* A versatile mesh processing toolbox o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
$Log: meshedit.cpp,v $
|
||||
****************************************************************************/
|
||||
#include <Qt>
|
||||
#include <QtGui>
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtXml/QDomElement>
|
||||
#include <QtXml/QDomNode>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <meshlab/glarea.h>
|
||||
|
||||
#include "edit_epoch.h"
|
||||
#include <meshlab/stdpardialog.h>
|
||||
#include <vcg/complex/append.h>
|
||||
#include <vcg/math/histogram.h>
|
||||
#include <vcg/complex/algorithms/create/platonic.h>
|
||||
#include <vcg/complex/algorithms/clustering.h>
|
||||
#include <vcg/complex/algorithms/hole.h>
|
||||
#include <wrap/io_trimesh/export_ply.h>
|
||||
#include <meshlab/alnParser.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
FILE *logFP=0;
|
||||
|
||||
EditEpochPlugin::EditEpochPlugin() {
|
||||
epochDialog = new v3dImportDialog();
|
||||
epochDialog->hide();
|
||||
qFont.setFamily("Helvetica");
|
||||
qFont.setPixelSize(10);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
const QString EditEpochPlugin::Info()
|
||||
{
|
||||
return tr("Culo.");
|
||||
}
|
||||
|
||||
void EditEpochPlugin::Decorate(MeshModel &m, GLArea * gla)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool EditEpochPlugin::StartEdit(MeshDocument &_md, GLArea *_gla )
|
||||
{
|
||||
///////
|
||||
|
||||
MeshModel *m;// = md->mm();
|
||||
EpochReconstruction er;
|
||||
|
||||
QString fileName=epochDialog->fileName;
|
||||
|
||||
if (fileName.isEmpty()) return false;
|
||||
// initializing progress bar status
|
||||
//if (cb != NULL) (*cb)(0, "Loading...");
|
||||
|
||||
// this change of dir is needed for subsequent texture/material loading
|
||||
QString FileNameDir = fileName.left(fileName.lastIndexOf("/"));
|
||||
QDir::setCurrent(FileNameDir);
|
||||
|
||||
QString errorMsgFormat = "Error encountered while loading file %1:\n%2";
|
||||
string stdfilename = QFile::encodeName(fileName).constData ();
|
||||
//string filename = fileName.toUtf8().data();
|
||||
|
||||
QDomDocument doc;
|
||||
|
||||
|
||||
QFile file(fileName);
|
||||
if (file.open(QIODevice::ReadOnly) && doc.setContent(&file))
|
||||
{
|
||||
file.close();
|
||||
QDomElement root = doc.documentElement();
|
||||
if (root.nodeName() == tr("reconstruction"))
|
||||
{
|
||||
QDomNode nhead = root.firstChildElement("head");
|
||||
for(QDomNode n = nhead.firstChildElement("meta"); !n.isNull(); n = n.nextSiblingElement("meta"))
|
||||
{
|
||||
if(!n.hasAttributes()) return false;
|
||||
QDomNamedNodeMap attr= n.attributes();
|
||||
if(attr.contains("name")) er.name = (attr.namedItem("name")).nodeValue() ;
|
||||
if(attr.contains("author")) er.author = (attr.namedItem("author")).nodeValue() ;
|
||||
if(attr.contains("created")) er.created = (attr.namedItem("created")).nodeValue() ;
|
||||
}
|
||||
for(QDomNode n = root.firstChildElement("model"); !n.isNull(); n = n.nextSiblingElement("model"))
|
||||
{
|
||||
EpochModel em;
|
||||
em.Init(n);
|
||||
er.modelList.push_back(em);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
epochDialog->setEpochReconstruction( &er);
|
||||
|
||||
//connect(epochDialog, SIGNAL(closing()),gla,SLOT(endEdit()) );
|
||||
|
||||
int continueValue = epochDialog->exec();
|
||||
//// OK till here
|
||||
|
||||
epochDialog->exportToPLY=false;
|
||||
// do
|
||||
//{
|
||||
// epochDialog->exportToPLY=false;
|
||||
//
|
||||
// //Here we invoke the modal dialog and wait for its termination
|
||||
// int continueValue = epochDialog->exec();
|
||||
|
||||
// // The user has pressed the ok button: now start the real processing:
|
||||
//
|
||||
// if(epochDialog->exportToPLY == true) qDebug("Starting the ply exporting process");
|
||||
//
|
||||
// int t0=clock();
|
||||
// logFP=fopen("epoch.log","w");
|
||||
|
||||
// int subSampleVal = epochDialog->subsampleSpinBox->value();
|
||||
// int minCountVal= epochDialog->minCountSpinBox->value();
|
||||
// float maxCCDiagVal= epochDialog->maxCCDiagSpinBox->value();
|
||||
// int mergeResolution=epochDialog->mergeResolutionSpinBox->value();
|
||||
// int smoothSteps=epochDialog->smoothSpinBox->value();
|
||||
// bool closeHole = epochDialog->holeCheckBox->isChecked();
|
||||
// int maxHoleSize = epochDialog->holeSpinBox->value();
|
||||
// /*if (continueValue == QDialog::Rejected)
|
||||
// {
|
||||
// QMessageBox::warning(parent, "Open V3d format","Aborted");
|
||||
// return false;
|
||||
// }*/
|
||||
// CMeshO mm;
|
||||
// QTableWidget *qtw=epochDialog->imageTableWidget;
|
||||
// float MinAngleCos=cos(vcg::math::ToRad(epochDialog->qualitySpinBox->value()));
|
||||
// bool clustering=epochDialog->fastMergeCheckBox->isChecked();
|
||||
// bool removeSmallCC=epochDialog->removeSmallCCCheckBox->isChecked();
|
||||
// vcg::tri::Clustering<CMeshO, vcg::tri::AverageColorCell<CMeshO> > Grid;
|
||||
|
||||
// int selectedNum=0,selectedCount=0;
|
||||
// int i;
|
||||
// for(i=0;i<qtw->rowCount();++i) if(qtw->isItemSelected(qtw->item(i,0))) ++selectedNum;
|
||||
// /*if(selectedNum==0)
|
||||
// {
|
||||
// QMessageBox::warning(parent, "Open V3d format","No range map selected. Nothing loaded");
|
||||
// return false;
|
||||
// }*/
|
||||
|
||||
// bool dilationFlag = epochDialog->dilationCheckBox->isChecked();
|
||||
// int dilationN = epochDialog->dilationNumPassSpinBox->value();
|
||||
// int dilationSz = epochDialog->dilationSizeSlider->value() * 2 + 1;
|
||||
// bool erosionFlag = epochDialog->erosionCheckBox->isChecked();
|
||||
// int erosionN = epochDialog->erosionNumPassSpinBox->value();
|
||||
// int erosionSz = epochDialog->erosionSizeSlider->value() * 2 + 1;
|
||||
// float scalingFactor = epochDialog->scaleLineEdit->text().toFloat();
|
||||
// std::vector<string> savedMeshVector;
|
||||
|
||||
// bool firstTime=true;
|
||||
// QList<EpochModel>::iterator li;
|
||||
// for(li=er.modelList.begin(), i=0;li!=er.modelList.end();++li,++i)
|
||||
// {
|
||||
// if(qtw->isItemSelected(qtw->item(i,0)))
|
||||
// {
|
||||
// ++selectedCount;
|
||||
// mm.Clear();
|
||||
// int tt0=clock();
|
||||
// (*li).BuildMesh(mm,subSampleVal,minCountVal,MinAngleCos,smoothSteps,
|
||||
// dilationFlag, dilationN, dilationSz, erosionFlag, erosionN, erosionSz,scalingFactor);
|
||||
// int tt1=clock();
|
||||
// if(logFP) fprintf(logFP,"** Mesh %i : Build in %i\n",selectedCount,tt1-tt0);
|
||||
|
||||
// if(epochDialog->exportToPLY)
|
||||
// {
|
||||
// QString plyFilename =(*li).textureName.left((*li).textureName.length()-4);
|
||||
// plyFilename.append(".x.ply");
|
||||
// savedMeshVector.push_back(qPrintable(plyFilename));
|
||||
// int mask= tri::io::Mask::IOM_VERTCOORD + tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY;
|
||||
// tri::io::ExporterPLY<CMeshO>::Save(mm,qPrintable(plyFilename),mask);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if(clustering)
|
||||
// {
|
||||
// if (firstTime)
|
||||
// {
|
||||
// //Grid.Init(mm.bbox,100000);
|
||||
// vcg::tri::UpdateBounding<CMeshO>::Box(mm);
|
||||
// //Grid.Init(mm.bbox,1000.0*pow(10.0,mergeResolution),mm.bbox.Diag()/1000.0f);
|
||||
// Grid.Init(mm.bbox,100000.0*pow(10.0,mergeResolution));
|
||||
// firstTime=false;
|
||||
// }
|
||||
// Grid.AddMesh(mm);
|
||||
// }
|
||||
// else
|
||||
// tri::Append<CMeshO,CMeshO>::Mesh(m->cm,mm); // append mesh mr to ml
|
||||
// }
|
||||
// int tt2=clock();
|
||||
// if(logFP) fprintf(logFP,"** Mesh %i : Append in %i\n",selectedCount,tt2-tt1);
|
||||
|
||||
// }
|
||||
// //if (cb)(*cb)(selectedCount*90/selectedNum, "Building meshes");
|
||||
// }
|
||||
//
|
||||
// //if (cb != NULL) (*cb)(90, "Final Processing: clustering");
|
||||
// if(clustering)
|
||||
// {
|
||||
// Grid.ExtractPointSet(m->cm);
|
||||
// }
|
||||
//
|
||||
// if(epochDialog->exportToPLY)
|
||||
// {
|
||||
// QString ALNfilename = fileName.left(fileName.length()-4).append(".aln");
|
||||
// ALNParser::SaveALN(qPrintable(ALNfilename), savedMeshVector);
|
||||
// }
|
||||
// int t1=clock();
|
||||
// if(logFP) fprintf(logFP,"Extracted %i meshes in %i\n",selectedCount,t1-t0);
|
||||
|
||||
// //if (cb != NULL) (*cb)(95, "Final Processing: Removing Small Connected Components");
|
||||
// if(removeSmallCC)
|
||||
// {
|
||||
// vcg::tri::UpdateBounding<CMeshO>::Box(m->cm); // updates bounding box
|
||||
// m->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER | MeshModel::MM_FACEMARK);
|
||||
// tri::Clean<CMeshO>::RemoveSmallConnectedComponentsDiameter(m->cm,m->cm.bbox.Diag()*maxCCDiagVal/100.0);
|
||||
// }
|
||||
|
||||
// int t2=clock();
|
||||
// if(logFP) fprintf(logFP,"Topology and removed CC in %i\n",t2-t1);
|
||||
|
||||
// vcg::tri::UpdateBounding<CMeshO>::Box(m->cm); // updates bounding box
|
||||
//
|
||||
// //if (cb != NULL) (*cb)(97, "Final Processing: Closing Holes");
|
||||
// if(closeHole)
|
||||
// {
|
||||
// m->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER | MeshModel::MM_FACEMARK);
|
||||
// tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m->cm);
|
||||
// vcg::tri::Hole<CMeshO>::EarCuttingFill<vcg::tri::MinimumWeightEar< CMeshO> >(m->cm,maxHoleSize,false);
|
||||
// }
|
||||
|
||||
// //if (cb != NULL) (*cb)(100, "Done");
|
||||
// // vcg::tri::UpdateNormals<CMeshO>::PerVertex(m.cm); // updates normals
|
||||
//
|
||||
// m->updateDataMask(MeshModel::MM_VERTCOLOR);
|
||||
|
||||
// int t3=clock();
|
||||
// if(logFP) fprintf(logFP,"---------- Total Processing Time%i\n\n\n",t3-t0);
|
||||
// if(logFP) fclose(logFP);
|
||||
// logFP=0;
|
||||
|
||||
|
||||
////// Importing rasters
|
||||
|
||||
// //QList<EpochModel>::iterator li;
|
||||
// for(li=er.modelList.begin(), i=0;li!=er.modelList.end();++li,++i)
|
||||
// {
|
||||
// //RasterModel &pm =addNewRaster("","Poisson mesh");
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
//} while(epochDialog->exportToPLY);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditEpochPlugin::EndEdit(MeshModel &/*m*/, GLArea * /*parent*/)
|
||||
{
|
||||
assert(epochDialog);
|
||||
delete epochDialog;
|
||||
epochDialog=0;
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::hideRevealGluedMesh()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::setBaseMesh()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EditEpochPlugin::glueByPicking()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EditEpochPlugin::glueManual()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin:: alignParamCurrent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin:: alignParam()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::glueHere()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::glueHereAll()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::process()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::recalcCurrentArc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EditEpochPlugin::mousePressEvent(QMouseEvent *e, MeshModel &, GLArea * )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::mouseMoveEvent(QMouseEvent *e, MeshModel &, GLArea * )
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void EditEpochPlugin::mouseReleaseEvent(QMouseEvent * e, MeshModel &/*m*/, GLArea * gla)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// this function toggles on and off all the buttons (according to the "modal" states of the interface),
|
||||
// do not confuse it with the updatebuttons function of the epochDialog class.
|
||||
void EditEpochPlugin::toggleButtons()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
102
src/plugins_experimental/edit_epoch/edit_epoch.h
Normal file
102
src/plugins_experimental/edit_epoch/edit_epoch.h
Normal file
@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* A versatile mesh processing toolbox o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef EditEpochPLUGIN_H
|
||||
#define EditEpochPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <common/interfaces.h>
|
||||
#include "epoch_io.h"
|
||||
|
||||
|
||||
|
||||
class EditEpochPlugin : public QObject, public MeshEditInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MeshEditInterface)
|
||||
|
||||
enum
|
||||
{
|
||||
ALIGN_IDLE = 0x01,
|
||||
ALIGN_INSPECT_ARC = 0x02,
|
||||
ALIGN_MOVE = 0x03
|
||||
};
|
||||
|
||||
void Pick( MeshModel &m, GLArea * gla);
|
||||
|
||||
public:
|
||||
EditEpochPlugin();
|
||||
virtual ~EditEpochPlugin() {
|
||||
mode=ALIGN_IDLE;
|
||||
}
|
||||
|
||||
static const QString Info();
|
||||
|
||||
bool StartEdit(MeshDocument &/*m*/, GLArea * /*parent*/);
|
||||
void EndEdit(MeshModel &/*m*/, GLArea * /*parent*/);
|
||||
void Decorate(MeshModel &/*m*/, GLArea * /*parent*/);
|
||||
void mousePressEvent(QMouseEvent *, MeshModel &, GLArea * ) ;
|
||||
void mouseMoveEvent(QMouseEvent *, MeshModel &, GLArea * ) ;
|
||||
void mouseReleaseEvent(QMouseEvent *event, MeshModel &/*m*/, GLArea * );
|
||||
|
||||
QFont qFont;
|
||||
int mode;
|
||||
|
||||
v3dImportDialog *epochDialog; //the widget with the list of the meshes.
|
||||
|
||||
void toggleButtons();
|
||||
|
||||
|
||||
|
||||
MeshDocument *md;
|
||||
|
||||
GLArea * gla;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// this callback MUST be redefined because we are able to manage internally the layer change.
|
||||
virtual void LayerChanged(MeshDocument &/*md*/, MeshModel &/*oldMeshModel*/, GLArea */*parent*/)
|
||||
{
|
||||
// add code here to manage the external layer switching
|
||||
}
|
||||
|
||||
public slots:
|
||||
void process();
|
||||
void recalcCurrentArc();
|
||||
void glueHere();
|
||||
void glueHereAll();
|
||||
void glueManual();
|
||||
void glueByPicking();
|
||||
void alignParam();
|
||||
void alignParamCurrent();
|
||||
void setBaseMesh();
|
||||
void hideRevealGluedMesh();
|
||||
|
||||
|
||||
signals:
|
||||
void suspendEditToggle();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
50
src/plugins_experimental/edit_epoch/edit_epoch.pro
Normal file
50
src/plugins_experimental/edit_epoch/edit_epoch.pro
Normal file
@ -0,0 +1,50 @@
|
||||
include (../../shared.pri)
|
||||
|
||||
TEMPLATE = lib
|
||||
|
||||
FORMS = ui/v3dImportDialog.ui
|
||||
HEADERS += epoch_io.h \
|
||||
epoch_reconstruction.h \
|
||||
epoch_camera.h \
|
||||
radial_distortion.h\
|
||||
v3dImportDialog.h \
|
||||
scalar_image.h \
|
||||
maskRenderWidget.h \
|
||||
maskImageWidget.h \
|
||||
fillImage.h
|
||||
|
||||
SOURCES += epoch_io.cpp \
|
||||
epoch_camera.cpp \
|
||||
radial_distortion.cpp \
|
||||
scalar_image.cpp \
|
||||
v3dImportDialog.cpp \
|
||||
maskRenderWidget.cpp \
|
||||
maskImageWidget.cpp \
|
||||
fillImage.cpp \
|
||||
$$VCGDIR/wrap/ply/plylib.cpp
|
||||
|
||||
TARGET = edit_epoch
|
||||
QT += xml
|
||||
|
||||
win32-msvc2005:LIBS += ../../external/lib/win32-msvc2005/bz2.lib
|
||||
win32-msvc2008:LIBS += ../../external/lib/win32-msvc2008/bz2.lib
|
||||
win32-g++:LIBS += ../../external/lib/win32-gcc/libbz2.a
|
||||
linux-g++:LIBS += ../../external/lib/linux-g++/libbz2.a
|
||||
linux-g++-32:LIBS += ../../external/lib/linux-g++-32/libbz2.a
|
||||
linux-g++-64:LIBS += ../../external/lib/linux-g++-64/libbz2.a
|
||||
|
||||
win32-msvc2005:INCLUDEPATH += ../../external/bzip2-1.0.5
|
||||
win32-msvc2008:INCLUDEPATH += ../../external/bzip2-1.0.5
|
||||
win32-g++:INCLUDEPATH += ../../external/bzip2-1.0.5
|
||||
linux-g++:INCLUDEPATH += ../../external/bzip2-1.0.5
|
||||
linux-g++-32:INCLUDEPATH += ../../external/bzip2-1.0.5
|
||||
linux-g++-64:INCLUDEPATH += ../../external/bzip2-1.0.5
|
||||
|
||||
mac:LIBS += -lbz2
|
||||
|
||||
CONFIG(release, debug|release) {
|
||||
win32-g++:release:QMAKE_CXXFLAGS -= -O2
|
||||
win32-g++:release:QMAKE_CFLAGS -= -O2
|
||||
win32-g++:release:QMAKE_CXXFLAGS += -O3 -mtune=pentium3 -ffast-math
|
||||
}
|
||||
|
||||
8
src/plugins_experimental/edit_epoch/edit_epoch.qrc
Normal file
8
src/plugins_experimental/edit_epoch/edit_epoch.qrc
Normal file
@ -0,0 +1,8 @@
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>images/icon_arc3d.png</file>
|
||||
<file>images/cur_align.png</file>
|
||||
<file alias="layer_eye_open.png">../../meshlab/images/layer_eye_open.png</file>
|
||||
<file alias="layer_eye_close.png">../../meshlab/images/layer_eye_close.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
57
src/plugins_experimental/edit_epoch/edit_epoch_factory.cpp
Normal file
57
src/plugins_experimental/edit_epoch/edit_epoch_factory.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* A versatile mesh processing toolbox o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005-2008 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "edit_epoch_factory.h"
|
||||
#include "edit_epoch.h"
|
||||
|
||||
EditEpochFactory::EditEpochFactory()
|
||||
{
|
||||
editEpoch = new QAction(QIcon(":/images/icon_arc3d.png"), "Arc3D Importer", this);
|
||||
|
||||
actionList << editEpoch;
|
||||
|
||||
foreach(QAction *editAction, actionList)
|
||||
editAction->setCheckable(true);
|
||||
}
|
||||
|
||||
//gets a list of actions available from this plugin
|
||||
QList<QAction *> EditEpochFactory::actions() const
|
||||
{
|
||||
return actionList;
|
||||
}
|
||||
|
||||
//get the edit tool for the given action
|
||||
MeshEditInterface* EditEpochFactory::getMeshEditInterface(QAction *action)
|
||||
{
|
||||
if(action == editEpoch)
|
||||
{
|
||||
return new EditEpochPlugin();
|
||||
} else assert(0); //should never be asked for an action that isnt here
|
||||
}
|
||||
|
||||
QString EditEpochFactory::getEditToolDescription(QAction *)
|
||||
{
|
||||
return EditEpochPlugin::Info();
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN(EditEpochFactory)
|
||||
55
src/plugins_experimental/edit_epoch/edit_epoch_factory.h
Normal file
55
src/plugins_experimental/edit_epoch/edit_epoch_factory.h
Normal file
@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* A versatile mesh processing toolbox o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005-2008 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef EditEpochFactoryPLUGIN_H
|
||||
#define EditEpochFactoryPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <common/interfaces.h>
|
||||
|
||||
class EditEpochFactory : public QObject, public MeshEditInterfaceFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MeshEditInterfaceFactory)
|
||||
|
||||
public:
|
||||
EditEpochFactory();
|
||||
virtual ~EditEpochFactory() { delete editEpoch; }
|
||||
|
||||
//gets a list of actions available from this plugin
|
||||
virtual QList<QAction *> actions() const;
|
||||
|
||||
//get the edit tool for the given action
|
||||
virtual MeshEditInterface* getMeshEditInterface(QAction *);
|
||||
|
||||
//get the description for the given action
|
||||
virtual QString getEditToolDescription(QAction *);
|
||||
|
||||
private:
|
||||
QList <QAction *> actionList;
|
||||
|
||||
QAction *editEpoch;
|
||||
};
|
||||
|
||||
#endif
|
||||
111
src/plugins_experimental/edit_epoch/epoch_camera.cpp
Normal file
111
src/plugins_experimental/edit_epoch/epoch_camera.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include <vector>
|
||||
#include <vcg/math/matrix33.h>
|
||||
#include <vcg/math/matrix44.h>
|
||||
#include <vcg/space/point3.h>
|
||||
|
||||
using namespace vcg;
|
||||
using namespace std;
|
||||
|
||||
#include "radial_distortion.h"
|
||||
#include "epoch_camera.h"
|
||||
|
||||
|
||||
/*
|
||||
Epoch Camera
|
||||
|
||||
|
||||
*/
|
||||
// This function take in input a point in image space (e.g. with coords in range [0..1024]x[0..768]
|
||||
// a depth value and it returns the point in absolute 3D coords
|
||||
//
|
||||
void EpochCamera::DepthTo3DPoint(double x, double y, double depth, Point3d &M) const
|
||||
{
|
||||
Point3d m_temp = Kinv * Point3d(x,y,1);
|
||||
|
||||
double oldx, oldy;
|
||||
rd.ComputeOldXY(m_temp[0] / m_temp[2], m_temp[1] / m_temp[2], oldx, oldy);
|
||||
|
||||
m_temp=Point3d(oldx,oldy,1);
|
||||
Point3d fp=t;
|
||||
Point3d end = TRinv*m_temp;
|
||||
Point3d dir =fp-end;
|
||||
dir.Normalize();
|
||||
M = fp-dir*depth;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool EpochCamera::Open(const char *filename)
|
||||
{
|
||||
FILE *fp=fopen(filename,"rb");
|
||||
if(!fp) return false;
|
||||
|
||||
fscanf(fp,"%lf %lf %lf",&(K[0][0]),&(K[0][1]),&(K[0][2]));
|
||||
fscanf(fp,"%lf %lf %lf",&(K[1][0]),&(K[1][1]),&(K[1][2]));
|
||||
fscanf(fp,"%lf %lf %lf",&(K[2][0]),&(K[2][1]),&(K[2][2]));
|
||||
|
||||
k.resize(3);
|
||||
fscanf(fp,"%lf %lf %lf",&(k[0]),&(k[1]),&(k[2]));
|
||||
|
||||
fscanf(fp,"%lf %lf %lf",&(R[0][0]),&(R[0][1]),&(R[0][2]));
|
||||
fscanf(fp,"%lf %lf %lf",&(R[1][0]),&(R[1][1]),&(R[1][2]));
|
||||
fscanf(fp,"%lf %lf %lf",&(R[2][0]),&(R[2][1]),&(R[2][2]));
|
||||
|
||||
fscanf(fp,"%lf %lf %lf",&(t[0]),&(t[1]),&(t[2]));
|
||||
|
||||
fscanf(fp,"%i %i",&width,&height);
|
||||
|
||||
fclose(fp);
|
||||
Kinv=Inverse(K);
|
||||
|
||||
rd.SetParameters(k);
|
||||
|
||||
// TR = [R | -Rt] 4x4 matrix with upperleft a 3x3 rotation
|
||||
// on the right the rotated translation -Rt and 0001 in the
|
||||
// lower line.
|
||||
|
||||
R.transposeInPlace();
|
||||
#ifndef VCG_USE_EIGEN
|
||||
for(int i=0;i<3;++i)
|
||||
for(int j=0;j<3;++j)
|
||||
TR[i][j]= R[i][j];
|
||||
#else
|
||||
TR.corner<3,3>(Eigen::TopLeft) = R.transpose();
|
||||
#endif
|
||||
|
||||
Point3d rt= R*(-t);
|
||||
|
||||
for(int i=0;i<3;++i)
|
||||
TR[i][3]=rt[i];
|
||||
|
||||
for(int j=0;j<3;++j)
|
||||
TR[3][j]=0;
|
||||
|
||||
TR[3][3]=1;
|
||||
TRinv=Inverse(TR);
|
||||
return true;
|
||||
}
|
||||
46
src/plugins_experimental/edit_epoch/epoch_camera.h
Normal file
46
src/plugins_experimental/edit_epoch/epoch_camera.h
Normal file
@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
namespace vcg
|
||||
{
|
||||
class EpochCamera
|
||||
{
|
||||
public:
|
||||
Matrix33d K; // parametri intriseci camera
|
||||
Matrix33d Kinv;
|
||||
|
||||
std::vector<double> k;
|
||||
Matrix33d R;
|
||||
Matrix44d TR; // [R | -Rt] e.g. la matrice in cui
|
||||
Matrix44d TRinv;
|
||||
Point3d t;
|
||||
int width, height;
|
||||
|
||||
RadialDistortion rd;
|
||||
|
||||
void DepthTo3DPoint(double x, double y, double depth, Point3d &M) const;
|
||||
|
||||
bool Open(const char * filename);
|
||||
};
|
||||
|
||||
}
|
||||
739
src/plugins_experimental/edit_epoch/epoch_io.cpp
Normal file
739
src/plugins_experimental/edit_epoch/epoch_io.cpp
Normal file
@ -0,0 +1,739 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2006 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include <Qt>
|
||||
#include <QtGui>
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtXml/QDomElement>
|
||||
#include <QtXml/QDomNode>
|
||||
|
||||
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
|
||||
#include "epoch_reconstruction.h"
|
||||
#include <vcg/complex/append.h>
|
||||
#include <vcg/math/histogram.h>
|
||||
#include <vcg/complex/algorithms/create/platonic.h>
|
||||
#include <vcg/complex/algorithms/clustering.h>
|
||||
#include <vcg/complex/algorithms/hole.h>
|
||||
#include <wrap/io_trimesh/export_ply.h>
|
||||
#include <meshlab/alnParser.h>
|
||||
|
||||
FILE *logFP2=0;
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
|
||||
void EpochModel::depthFilter(FloatImage &depthImgf, FloatImage &countImgf, float depthJumpThr,
|
||||
bool dilation, int dilationNumPasses, int dilationWinsize,
|
||||
bool erosion, int erosionNumPasses, int erosionWinsize)
|
||||
{
|
||||
FloatImage depth;
|
||||
FloatImage depth2;
|
||||
int w = depthImgf.w;
|
||||
int h = depthImgf.h;
|
||||
|
||||
depth=depthImgf;
|
||||
|
||||
if (dilation)
|
||||
{
|
||||
for (int k = 0; k < dilationNumPasses; k++)
|
||||
{
|
||||
depth.Dilate(depth2, dilationWinsize / 2);
|
||||
depth=depth2;
|
||||
}
|
||||
}
|
||||
|
||||
if (erosion)
|
||||
{
|
||||
for (int k = 0; k < erosionNumPasses; k++)
|
||||
{
|
||||
depth.Erode(depth2, erosionWinsize / 2);
|
||||
depth=depth2;
|
||||
}
|
||||
}
|
||||
|
||||
Histogramf HH;
|
||||
HH.Clear();
|
||||
HH.SetRange(0,depthImgf.MaxVal()-depthImgf.MinVal(),10000);
|
||||
for(int i=1; i < static_cast<int>(depthImgf.v.size()); ++i)
|
||||
HH.Add(fabs(depthImgf.v[i]-depth.v[i-1]));
|
||||
|
||||
if(logFP2) fprintf(logFP2,"**** Depth histogram 2 Min %f Max %f Avg %f Percentiles ((10)%f (25)%f (50)%f (75)%f (90)%f)\n",HH.MinV(),HH.MaxV(),HH.Avg(),
|
||||
HH.Percentile(.1),HH.Percentile(.25),HH.Percentile(.5),HH.Percentile(.75),HH.Percentile(.9));
|
||||
|
||||
int deletedCnt=0;
|
||||
|
||||
depthJumpThr = static_cast<float>(HH.Percentile(0.8));
|
||||
for (int y = 0; y < h; y++)
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
if ((depthImgf.Val(x, y) - depth.Val(x, y)) / depthImgf.Val(x, y) > 0.6)
|
||||
{
|
||||
countImgf.Val(x, y) = 0.0f;
|
||||
++deletedCnt;
|
||||
}
|
||||
}
|
||||
|
||||
countImgf.convertToQImage().save("tmp_filteredcount.jpg","jpg");
|
||||
|
||||
if(logFP2) fprintf(logFP2,"**** depthFilter: deleted %i on %i\n",deletedCnt,w*h);
|
||||
|
||||
}
|
||||
|
||||
float EpochModel::ComputeDepthJumpThr(FloatImage &depthImgf, float percentile)
|
||||
{
|
||||
Histogramf HH;
|
||||
HH.Clear();
|
||||
HH.SetRange(0,depthImgf.MaxVal()-depthImgf.MinVal(),10000);
|
||||
for(unsigned int i=1; i < static_cast<unsigned int>(depthImgf.v.size()); ++i)
|
||||
HH.Add(fabs(depthImgf.v[i]-depthImgf.v[i-1]));
|
||||
|
||||
if(logFP2) fprintf(logFP2,"**** Depth histogram Min %f Max %f Avg %f Percentiles ((10)%f (25)%f (50)%f (75)%f (90)%f)\n",HH.MinV(),HH.MaxV(),HH.Avg(),
|
||||
HH.Percentile(.1),HH.Percentile(.25),HH.Percentile(.5),HH.Percentile(.75),HH.Percentile(.9));
|
||||
|
||||
return HH.Percentile(percentile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Apply the hand drawn mask image
|
||||
bool EpochModel::CombineHandMadeMaskAndCount(CharImage &CountImg, QString maskName )
|
||||
{
|
||||
QImage maskImg(maskName);
|
||||
qDebug("Trying to read maskname %s",qPrintable(maskName));
|
||||
if(maskImg.isNull())
|
||||
return false;
|
||||
|
||||
if( (maskImg.width()!= CountImg.w) || (maskImg.height()!= CountImg.h) )
|
||||
{
|
||||
qDebug("Warning mask and images does not match! %i %i vs %i %i",maskImg.width(),CountImg.w,maskImg.height(),CountImg.h);
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int j=0;j<maskImg.height();++j)
|
||||
for(int i=0;i<maskImg.width();++i)
|
||||
if(qRed(maskImg.pixel(i,j))>128)
|
||||
CountImg.Val(i,j)=0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void EpochModel::SmartSubSample(int factor, FloatImage &fli, CharImage &chi, FloatImage &subD, FloatImage &subQ, int minCount)
|
||||
{
|
||||
assert(fli.w==chi.w && fli.h==chi.h);
|
||||
int w=fli.w/factor;
|
||||
int h=fli.h/factor;
|
||||
subQ.resize(w,h);
|
||||
subD.resize(w,h);
|
||||
|
||||
for(int i=0;i<w;++i)
|
||||
for(int j=0;j<h;++j)
|
||||
{
|
||||
float maxcount=0;
|
||||
int cnt=0;
|
||||
float bestVal=0;
|
||||
for(int ki=0;ki<factor;++ki)
|
||||
for(int kj=0;kj<factor;++kj)
|
||||
{
|
||||
float q= chi.Val(i*factor+ki,j*factor+kj) - minCount+1 ;
|
||||
if(q>0)
|
||||
{
|
||||
maxcount+= q;
|
||||
bestVal +=q*fli.Val(i*factor+ki,j*factor+kj);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
if(cnt>0)
|
||||
{
|
||||
subD.Val(i,j)=float(bestVal)/maxcount;
|
||||
subQ.Val(i,j)=minCount-1 + float(maxcount)/cnt ;
|
||||
}
|
||||
else
|
||||
{
|
||||
subD.Val(i,j)=0;
|
||||
subQ.Val(i,j)=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This filter average apply a laplacian smoothing over a depth map averaging the samples with a weighting scheme that follows the Counting masks.
|
||||
The result of the laplacian is applied only on sample with low quality.
|
||||
*/
|
||||
|
||||
void EpochModel::Laplacian2(FloatImage &depthImg, FloatImage &countImg, int minCount, CharImage &featureMask, float depthThr)
|
||||
{
|
||||
FloatImage Sum;
|
||||
int w=depthImg.w,h=depthImg.h;
|
||||
Sum.resize(w,h);
|
||||
|
||||
for(int y=1;y<h-1;++y)
|
||||
for(int x=1;x<w-1;++x)
|
||||
{
|
||||
float curDepth=depthImg.Val(x,y);
|
||||
int cnt=0;
|
||||
for(int j=-1;j<=1;++j)
|
||||
for(int i=-1;i<=1;++i)
|
||||
{
|
||||
int q=countImg.Val(x+i,y+j)-minCount+1;
|
||||
if(q>0 && fabs(depthImg.Val(x+i,y+j)-curDepth) < depthThr) {
|
||||
Sum.Val(x,y)+=q*depthImg.Val(x+i,y+j);
|
||||
cnt+=q;
|
||||
}
|
||||
}
|
||||
if(cnt>0) {
|
||||
Sum.Val(x,y)/=cnt;
|
||||
}
|
||||
else Sum.Val(x,y)=depthImg.Val(x,y);
|
||||
}
|
||||
|
||||
for(int y=1;y<h-1;++y)
|
||||
for(int x=1;x<w-1;++x)
|
||||
{
|
||||
float q=(featureMask.Val(x,y)/255.0);
|
||||
depthImg.Val(x,y) = depthImg.Val(x,y)*q + Sum.Val(x,y)*(1-q);
|
||||
}
|
||||
}
|
||||
|
||||
// It generate a feature mask that mark the featureless area of the original photo.
|
||||
// Featureless areas are usually affected by noise and have to be smoothed more
|
||||
|
||||
void EpochModel::GenerateGradientSmoothingMask(int subsampleFactor, QImage &OriginalTexture, CharImage &mask)
|
||||
{
|
||||
CharImage gray(OriginalTexture);
|
||||
CharImage grad;
|
||||
grad.resize(gray.w,gray.h);
|
||||
int w=gray.w,h=gray.h;
|
||||
for(int x=1;x<w-1;++x)
|
||||
for(int y=1;y<h-1;++y)
|
||||
{
|
||||
int dx=abs(int(gray.Val(x,y))-int(gray.Val(x-1,y))) + abs(int(gray.Val(x,y))-int(gray.Val(x+1,y)));
|
||||
int dy=abs(int(gray.Val(x,y))-int(gray.Val(x,y-1))) + abs(int(gray.Val(x,y))-int(gray.Val(x,y+1)));
|
||||
grad.Val(x,y)=min(255,16*dx+dy);
|
||||
}
|
||||
|
||||
// create subsampled mask
|
||||
int ws=gray.w/subsampleFactor, hs=gray.h/subsampleFactor;
|
||||
mask.resize(ws,hs);
|
||||
|
||||
for(int x=0;x<ws;++x)
|
||||
for(int y=0;y<hs;++y)
|
||||
{
|
||||
unsigned char maxGrad=0;
|
||||
for(int si=0;si<subsampleFactor;++si)
|
||||
for(int sj=0;sj<subsampleFactor;++sj)
|
||||
maxGrad = max(maxGrad, grad.Val(x*subsampleFactor+sj,y*subsampleFactor+si));
|
||||
|
||||
mask.Val(x,y) = maxGrad;
|
||||
}
|
||||
|
||||
CharImage mask2;
|
||||
mask2.resize(ws, hs);
|
||||
|
||||
// average filter (11 x 11)
|
||||
int avg;
|
||||
int wsize = 5;
|
||||
for (int y = wsize; y < hs-wsize; y++)
|
||||
for (int x = wsize; x < ws-wsize; x++)
|
||||
{
|
||||
avg = 0;
|
||||
for (int yy = y - wsize; yy <= y + wsize; yy++)
|
||||
for (int xx = x - wsize; xx <= x + wsize; xx++)
|
||||
avg += mask.Val(xx, yy);
|
||||
|
||||
mask2.Val(x, y) = min(255, avg / ((2 * wsize + 1)* (2 * wsize +1)));
|
||||
}
|
||||
|
||||
mask.convertToQImage().save("tmp_testmask.jpg","jpg");
|
||||
mask2.convertToQImage().save("tmp_testmaskSmooth.jpg","jpg");
|
||||
|
||||
// erosion filter (7 x 7)
|
||||
int minimum;
|
||||
wsize = 3;
|
||||
for (int y = wsize; y < hs-wsize; y++)
|
||||
for (int x = wsize; x < ws-wsize; x++)
|
||||
{
|
||||
minimum = mask2.Val(x, y);
|
||||
for (int yy = y - wsize; yy <= y + wsize; yy++)
|
||||
for (int xx = x - wsize; xx <= x + wsize; xx++)
|
||||
if (mask2.Val(xx, yy) < minimum)
|
||||
minimum = mask2.Val(xx, yy);
|
||||
|
||||
mask.Val(x, y) = minimum;
|
||||
}
|
||||
|
||||
grad.convertToQImage().save("tmp_test.jpg","jpg");
|
||||
mask.convertToQImage().save("tmp_testmaskeroded.jpg","jpg");
|
||||
}
|
||||
|
||||
/*
|
||||
Main processing function;
|
||||
|
||||
it takes a depth map, a count map,
|
||||
- resample them to a (width/subsample,height/subsample) image
|
||||
- leave only the faces that are within a given orientation range
|
||||
- that have a count greater than minCount.
|
||||
- and smooth them with a count/quality aware laplacian filter
|
||||
*/
|
||||
|
||||
bool EpochModel::BuildMesh(CMeshO &m, int subsampleFactor, int minCount, float minAngleCos, int smoothSteps,
|
||||
bool dilation, int dilationPasses, int dilationSize,
|
||||
bool erosion, int erosionPasses, int erosionSize,float scalingFactor)
|
||||
{
|
||||
FloatImage depthImgf;
|
||||
CharImage countImgc;
|
||||
int ttt0=clock();
|
||||
depthImgf.Open(depthName.toAscii());
|
||||
countImgc.Open(countName.toAscii());
|
||||
|
||||
QImage TextureImg;
|
||||
TextureImg.load(textureName);
|
||||
int ttt1=clock();
|
||||
if(logFP2) fprintf(logFP2,"**** Buildmesh: Opening files %i\n",ttt1-ttt0);
|
||||
|
||||
CombineHandMadeMaskAndCount(countImgc,maskName); // set count to zero for all masked points
|
||||
|
||||
FloatImage depthSubf; // the subsampled depth image
|
||||
FloatImage countSubf; // the subsampled quality image (quality == count)
|
||||
|
||||
SmartSubSample(subsampleFactor,depthImgf,countImgc,depthSubf,countSubf,minCount);
|
||||
|
||||
CharImage FeatureMask; // the subsampled image with (quality == features)
|
||||
GenerateGradientSmoothingMask(subsampleFactor, TextureImg, FeatureMask);
|
||||
|
||||
depthSubf.convertToQImage().save("tmp_depth.jpg", "jpg");
|
||||
|
||||
int ttt2=clock();
|
||||
if(logFP2) fprintf(logFP2,"**** Buildmesh: SubSample and Gradient %i\n",ttt2-ttt1);
|
||||
|
||||
float depthThr = ComputeDepthJumpThr(depthSubf,0.8f);
|
||||
for(int ii=0;ii<smoothSteps;++ii)
|
||||
Laplacian2(depthSubf,countSubf,minCount,FeatureMask,depthThr);
|
||||
|
||||
int ttt3=clock();
|
||||
if(logFP2) fprintf(logFP2,"**** Buildmesh: Smoothing %i\n",ttt3-ttt2);
|
||||
|
||||
vcg::tri::Grid<CMeshO>(m,depthSubf.w,depthSubf.h,depthImgf.w,depthImgf.h,&*depthSubf.v.begin());
|
||||
|
||||
int ttt4=clock();
|
||||
if(logFP2) fprintf(logFP2,"**** Buildmesh: trimesh building %i\n",ttt4-ttt3);
|
||||
|
||||
|
||||
// The depth is filtered and the minimum count mask is update accordingly.
|
||||
// To be more specific the border of the depth map are identified by erosion
|
||||
// and the relative vertex removed (by setting mincount equal to 0).
|
||||
float depthThr2 = ComputeDepthJumpThr(depthSubf,0.95f);
|
||||
depthFilter(depthSubf, countSubf, depthThr2,
|
||||
dilation, dilationPasses, dilationSize,
|
||||
erosion, erosionPasses, erosionSize);
|
||||
|
||||
int vn = m.vn;
|
||||
for(int i=0;i<vn;++i)
|
||||
if(countSubf.v[i]<minCount)
|
||||
{
|
||||
m.vert[i].SetD();
|
||||
m.vn--;
|
||||
}
|
||||
|
||||
cam.Open(cameraName.toAscii());
|
||||
CMeshO::VertexIterator vi;
|
||||
Matrix33d Rinv= Inverse(cam.R);
|
||||
|
||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi)if(!(*vi).IsD())
|
||||
{
|
||||
Point3f in=(*vi).P();
|
||||
Point3d out;
|
||||
cam.DepthTo3DPoint(in[0], in[1], in[2], out);
|
||||
|
||||
(*vi).P().Import(out);
|
||||
QRgb c = TextureImg.pixel(int(in[0]), int(in[1]));
|
||||
(*vi).C().SetRGB(qRed(c),qGreen(c),qBlue(c));
|
||||
//(*vi).Q()=chi.Val(in[0], in[1]);
|
||||
//(*vi).Q()=flisubQ.Val(in[0]/subsample, in[1]/subsample);
|
||||
if(FeatureMask.Val(int(in[0]/subsampleFactor), int(in[1]/subsampleFactor))<200) (*vi).Q()=0;
|
||||
else (*vi).Q()=1;
|
||||
(*vi).Q()=float(FeatureMask.Val(in[0]/subsampleFactor, in[1]/subsampleFactor))/255.0;
|
||||
}
|
||||
|
||||
int ttt5=clock();
|
||||
if(logFP2) fprintf(logFP2,"**** Buildmesh: Projecting and Coloring %i\n",ttt5-ttt4);
|
||||
|
||||
CMeshO::FaceIterator fi;
|
||||
Point3f CameraPos=Point3f::Construct(cam.t);
|
||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
||||
{
|
||||
|
||||
if((*fi).V(0)->IsD() ||(*fi).V(1)->IsD() ||(*fi).V(2)->IsD() )
|
||||
{
|
||||
(*fi).SetD();
|
||||
--m.fn;
|
||||
}
|
||||
else
|
||||
{
|
||||
Point3f n=vcg::Normal(*fi);
|
||||
n.Normalize();
|
||||
Point3f dir=CameraPos-vcg::Barycenter(*fi);
|
||||
dir.Normalize();
|
||||
if(dir.dot(n) < minAngleCos)
|
||||
{
|
||||
(*fi).SetD();
|
||||
--m.fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tri::Clean<CMeshO>::RemoveUnreferencedVertex(m);
|
||||
int ttt6=clock();
|
||||
if(logFP2) fprintf(logFP2,"**** Buildmesh: Deleting skewed %i\n",ttt6-ttt5);
|
||||
|
||||
// Matrix44d Rot;
|
||||
// Rot.SetRotate(M_PI,Point3d(1,0,0));
|
||||
// vcg::tri::UpdatePosition<CMeshO>::Matrix(m, Rot);
|
||||
|
||||
Matrix44f scaleMat;
|
||||
scaleMat.SetScale(scalingFactor,scalingFactor,scalingFactor);
|
||||
vcg::tri::UpdatePosition<CMeshO>::Matrix(m, scaleMat);
|
||||
|
||||
return true;
|
||||
}
|
||||
void EpochModel::AddCameraIcon(CMeshO &m)
|
||||
{
|
||||
tri::Allocator<CMeshO>::AddVertices(m,3);
|
||||
m.vert[m.vert.size()-3].P()=Point3f::Construct(cam.t+Point3d(0,0,0));
|
||||
m.vert[m.vert.size()-3].C()=Color4b::Green;
|
||||
m.vert[m.vert.size()-2].P()=Point3f::Construct(cam.t+Point3d(0,1,0));
|
||||
m.vert[m.vert.size()-2].C()=Color4b::Green;
|
||||
m.vert[m.vert.size()-1].P()=Point3f::Construct(cam.t+Point3d(1,0,0));
|
||||
m.vert[m.vert.size()-1].C()=Color4b::Green;
|
||||
|
||||
tri::Allocator<CMeshO>::AddFaces(m,1);
|
||||
m.face[m.face.size()-1].V(0)= &m.vert[m.vert.size()-3];
|
||||
m.face[m.face.size()-1].V(1)= &m.vert[m.vert.size()-2];
|
||||
m.face[m.face.size()-1].V(2)= &m.vert[m.vert.size()-1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool EpochModel::Init(QDomNode &node)
|
||||
{
|
||||
if(!node.hasAttributes()) return false;
|
||||
QDomNamedNodeMap attr= node.attributes();
|
||||
QString indexString = (attr.namedItem("index")).nodeValue() ;
|
||||
qDebug("reading Model with index %i ",indexString.toInt());
|
||||
for(QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling())
|
||||
{
|
||||
if(n.nodeName() == QString("camera")) cameraName = n.attributes().namedItem("filename").nodeValue();
|
||||
if(n.nodeName() == QString("texture")) textureName= n.attributes().namedItem("filename").nodeValue();
|
||||
if(n.nodeName() == QString("depth")) depthName = n.attributes().namedItem("filename").nodeValue();
|
||||
if(n.nodeName() == QString("count")) countName = n.attributes().namedItem("filename").nodeValue();
|
||||
|
||||
// import leuven camera
|
||||
{
|
||||
double cam[9];
|
||||
float focus,scale;
|
||||
|
||||
FILE* lvcam;
|
||||
|
||||
lvcam = fopen(cameraName.toAscii(),"rb");
|
||||
|
||||
// focus + image centers
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[0]),&(cam[1]),&(cam[2]));
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[3]),&(cam[4]),&(cam[5]));
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[6]),&(cam[7]),&(cam[8]));
|
||||
|
||||
shot.Intrinsics.CenterPx[0] = cam[2];
|
||||
shot.Intrinsics.CenterPx[1] = cam[5];
|
||||
focus = cam[0];
|
||||
scale = 1.0f;
|
||||
while(focus>10.0f)
|
||||
{
|
||||
focus /= 10.0f;
|
||||
scale /= 10.0f;
|
||||
}
|
||||
shot.Intrinsics.FocalMm = focus;
|
||||
shot.Intrinsics.PixelSizeMm[0] = scale;
|
||||
shot.Intrinsics.PixelSizeMm[1] = scale;
|
||||
|
||||
// distortion
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[0]),&(cam[1]),&(cam[2]));
|
||||
shot.Intrinsics.k[0] = cam[0];
|
||||
shot.Intrinsics.k[1] = cam[1];
|
||||
|
||||
// orientation axis
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[0]),&(cam[1]),&(cam[2]));
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[3]),&(cam[4]),&(cam[5]));
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[6]),&(cam[7]),&(cam[8]));
|
||||
|
||||
Matrix44f myrot;
|
||||
|
||||
myrot[0][0] = cam[0]; myrot[0][1] = cam[3]; myrot[0][2] = cam[6]; myrot[0][3] = 0.0f;
|
||||
myrot[1][0] = -cam[1]; myrot[1][1] = -cam[4]; myrot[1][2] = -cam[7]; myrot[1][3] = 0.0f;
|
||||
myrot[2][0] = -cam[2]; myrot[2][1] = -cam[5]; myrot[2][2] = -cam[8]; myrot[2][3] = 0.0f;
|
||||
myrot[3][0] = 0.0f; myrot[3][1] = 0.0f; myrot[3][2] = 0.0f; myrot[3][3] = 1.0;
|
||||
|
||||
shot.Extrinsics.SetRot(myrot);
|
||||
|
||||
// camera position
|
||||
fscanf(lvcam,"%lf %lf %lf",&(cam[0]),&(cam[1]),&(cam[2]));
|
||||
shot.Extrinsics.SetTra(Point3f(-cam[0], -cam[1], -cam[2]));
|
||||
// shot.Extrinsics.sca = 1.0f;
|
||||
|
||||
|
||||
// image size
|
||||
fscanf(lvcam,"%lf %lf",&(cam[0]),&(cam[1]));
|
||||
shot.Intrinsics.ViewportPx.X() = (int)(cam[0]);
|
||||
shot.Intrinsics.ViewportPx.Y() = (int)(cam[1]);
|
||||
|
||||
fclose(lvcam);
|
||||
}
|
||||
}
|
||||
|
||||
QString tmpName=textureName.left(textureName.length()-4);
|
||||
maskName = tmpName.append(".mask.png");
|
||||
return true;
|
||||
}
|
||||
|
||||
QString EpochModel::ThumbName(QString &_imageName)
|
||||
{
|
||||
QString tmpName=_imageName.left(_imageName.length()-4);
|
||||
return tmpName.append(".thumb.jpg");
|
||||
}
|
||||
|
||||
//bool EpochIO::open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask,const RichParameterSet & /*par*/, CallBackPos *cb, QWidget *parent)
|
||||
//{
|
||||
// EpochReconstruction er;
|
||||
//
|
||||
// mask = vcg::tri::io::Mask::IOM_VERTCOLOR | vcg::tri::io::Mask::IOM_VERTQUALITY;
|
||||
//// just to be sure...
|
||||
//
|
||||
// if (fileName.isEmpty()) return false;
|
||||
// // initializing progress bar status
|
||||
// if (cb != NULL) (*cb)(0, "Loading...");
|
||||
//
|
||||
// // this change of dir is needed for subsequent texture/material loading
|
||||
// QString FileNameDir = fileName.left(fileName.lastIndexOf("/"));
|
||||
// QDir::setCurrent(FileNameDir);
|
||||
//
|
||||
// QString errorMsgFormat = "Error encountered while loading file %1:\n%2";
|
||||
// string stdfilename = QFile::encodeName(fileName).constData ();
|
||||
// //string filename = fileName.toUtf8().data();
|
||||
//
|
||||
// QDomDocument doc;
|
||||
//
|
||||
// if(formatName.toUpper() == tr("V3D") && fileName.endsWith(".v3d"))
|
||||
// {
|
||||
// QFile file(fileName);
|
||||
// if (file.open(QIODevice::ReadOnly) && doc.setContent(&file))
|
||||
// {
|
||||
// file.close();
|
||||
// QDomElement root = doc.documentElement();
|
||||
// if (root.nodeName() == tr("reconstruction"))
|
||||
// {
|
||||
// QDomNode nhead = root.firstChildElement("head");
|
||||
// for(QDomNode n = nhead.firstChildElement("meta"); !n.isNull(); n = n.nextSiblingElement("meta"))
|
||||
// {
|
||||
// if(!n.hasAttributes()) return false;
|
||||
// QDomNamedNodeMap attr= n.attributes();
|
||||
// if(attr.contains("name")) er.name = (attr.namedItem("name")).nodeValue() ;
|
||||
// if(attr.contains("author")) er.author = (attr.namedItem("author")).nodeValue() ;
|
||||
// if(attr.contains("created")) er.created = (attr.namedItem("created")).nodeValue() ;
|
||||
// }
|
||||
// for(QDomNode n = root.firstChildElement("model"); !n.isNull(); n = n.nextSiblingElement("model"))
|
||||
// {
|
||||
// EpochModel em;
|
||||
// em.Init(n);
|
||||
// er.modelList.push_back(em);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// epochDialog->setEpochReconstruction( &er, cb);
|
||||
// do
|
||||
// {
|
||||
// epochDialog->exportToPLY=false;
|
||||
//
|
||||
// //Here we invoke the modal dialog and wait for its termination
|
||||
// int continueValue = epochDialog->exec();
|
||||
//
|
||||
// // The user has pressed the ok button: now start the real processing:
|
||||
//
|
||||
// if(epochDialog->exportToPLY == true) qDebug("Starting the ply exporting process");
|
||||
//
|
||||
// int t0=clock();
|
||||
// logFP2=fopen("epoch.log","w");
|
||||
//
|
||||
// int subSampleVal = epochDialog->subsampleSpinBox->value();
|
||||
// int minCountVal= epochDialog->minCountSpinBox->value();
|
||||
// float maxCCDiagVal= epochDialog->maxCCDiagSpinBox->value();
|
||||
// int mergeResolution=epochDialog->mergeResolutionSpinBox->value();
|
||||
// int smoothSteps=epochDialog->smoothSpinBox->value();
|
||||
// bool closeHole = epochDialog->holeCheckBox->isChecked();
|
||||
// int maxHoleSize = epochDialog->holeSpinBox->value();
|
||||
// if (continueValue == QDialog::Rejected)
|
||||
// {
|
||||
// QMessageBox::warning(parent, "Open V3d format","Aborted");
|
||||
// return false;
|
||||
// }
|
||||
// CMeshO mm;
|
||||
// QTableWidget *qtw=epochDialog->imageTableWidget;
|
||||
// float MinAngleCos=cos(vcg::math::ToRad(epochDialog->qualitySpinBox->value()));
|
||||
// bool clustering=epochDialog->fastMergeCheckBox->isChecked();
|
||||
// bool removeSmallCC=epochDialog->removeSmallCCCheckBox->isChecked();
|
||||
// vcg::tri::Clustering<CMeshO, vcg::tri::AverageColorCell<CMeshO> > Grid;
|
||||
//
|
||||
// int selectedNum=0,selectedCount=0;
|
||||
// int i;
|
||||
// for(i=0;i<qtw->rowCount();++i) if(qtw->isItemSelected(qtw->item(i,0))) ++selectedNum;
|
||||
// if(selectedNum==0)
|
||||
// {
|
||||
// QMessageBox::warning(parent, "Open V3d format","No range map selected. Nothing loaded");
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// bool dilationFlag = epochDialog->dilationCheckBox->isChecked();
|
||||
// int dilationN = epochDialog->dilationNumPassSpinBox->value();
|
||||
// int dilationSz = epochDialog->dilationSizeSlider->value() * 2 + 1;
|
||||
// bool erosionFlag = epochDialog->erosionCheckBox->isChecked();
|
||||
// int erosionN = epochDialog->erosionNumPassSpinBox->value();
|
||||
// int erosionSz = epochDialog->erosionSizeSlider->value() * 2 + 1;
|
||||
// float scalingFactor = epochDialog->scaleLineEdit->text().toFloat();
|
||||
// std::vector<string> savedMeshVector;
|
||||
//
|
||||
// bool firstTime=true;
|
||||
// QList<EpochModel>::iterator li;
|
||||
// for(li=er.modelList.begin(), i=0;li!=er.modelList.end();++li,++i)
|
||||
// {
|
||||
// if(qtw->isItemSelected(qtw->item(i,0)))
|
||||
// {
|
||||
// ++selectedCount;
|
||||
// mm.Clear();
|
||||
// int tt0=clock();
|
||||
// (*li).BuildMesh(mm,subSampleVal,minCountVal,MinAngleCos,smoothSteps,
|
||||
// dilationFlag, dilationN, dilationSz, erosionFlag, erosionN, erosionSz,scalingFactor);
|
||||
// int tt1=clock();
|
||||
// if(logFP2) fprintf(logFP2,"** Mesh %i : Build in %i\n",selectedCount,tt1-tt0);
|
||||
//
|
||||
// if(epochDialog->exportToPLY)
|
||||
// {
|
||||
// QString plyFilename =(*li).textureName.left((*li).textureName.length()-4);
|
||||
// plyFilename.append(".x.ply");
|
||||
// savedMeshVector.push_back(qPrintable(plyFilename));
|
||||
// int mask= tri::io::Mask::IOM_VERTCOORD + tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY;
|
||||
// tri::io::ExporterPLY<CMeshO>::Save(mm,qPrintable(plyFilename),mask);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if(clustering)
|
||||
// {
|
||||
// if (firstTime)
|
||||
// {
|
||||
// //Grid.Init(mm.bbox,100000);
|
||||
// vcg::tri::UpdateBounding<CMeshO>::Box(mm);
|
||||
// //Grid.Init(mm.bbox,1000.0*pow(10.0,mergeResolution),mm.bbox.Diag()/1000.0f);
|
||||
// Grid.Init(mm.bbox,100000.0*pow(10.0,mergeResolution));
|
||||
// firstTime=false;
|
||||
// }
|
||||
// Grid.AddMesh(mm);
|
||||
// }
|
||||
// else
|
||||
// tri::Append<CMeshO,CMeshO>::Mesh(m.cm,mm); // append mesh mr to ml
|
||||
// }
|
||||
// int tt2=clock();
|
||||
// if(logFP2) fprintf(logFP2,"** Mesh %i : Append in %i\n",selectedCount,tt2-tt1);
|
||||
//
|
||||
// }
|
||||
// if (cb)(*cb)(selectedCount*90/selectedNum, "Building meshes");
|
||||
// }
|
||||
//
|
||||
// if (cb != NULL) (*cb)(90, "Final Processing: clustering");
|
||||
// if(clustering)
|
||||
// {
|
||||
// Grid.ExtractPointSet(m.cm);
|
||||
// }
|
||||
//
|
||||
// if(epochDialog->exportToPLY)
|
||||
// {
|
||||
// QString ALNfilename = fileName.left(fileName.length()-4).append(".aln");
|
||||
// ALNParser::SaveALN(qPrintable(ALNfilename), savedMeshVector);
|
||||
// }
|
||||
// int t1=clock();
|
||||
// if(logFP2) fprintf(logFP2,"Extracted %i meshes in %i\n",selectedCount,t1-t0);
|
||||
//
|
||||
// if (cb != NULL) (*cb)(95, "Final Processing: Removing Small Connected Components");
|
||||
// if(removeSmallCC)
|
||||
// {
|
||||
// vcg::tri::UpdateBounding<CMeshO>::Box(m.cm); // updates bounding box
|
||||
// m.updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER | MeshModel::MM_FACEMARK);
|
||||
// tri::Clean<CMeshO>::RemoveSmallConnectedComponentsDiameter(m.cm,m.cm.bbox.Diag()*maxCCDiagVal/100.0);
|
||||
// }
|
||||
//
|
||||
// int t2=clock();
|
||||
// if(logFP2) fprintf(logFP2,"Topology and removed CC in %i\n",t2-t1);
|
||||
//
|
||||
// vcg::tri::UpdateBounding<CMeshO>::Box(m.cm); // updates bounding box
|
||||
//
|
||||
// if (cb != NULL) (*cb)(97, "Final Processing: Closing Holes");
|
||||
// if(closeHole)
|
||||
// {
|
||||
// m.updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER | MeshModel::MM_FACEMARK);
|
||||
// tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);
|
||||
// vcg::tri::Hole<CMeshO>::EarCuttingFill<vcg::tri::MinimumWeightEar< CMeshO> >(m.cm,maxHoleSize,false);
|
||||
// }
|
||||
//
|
||||
// if (cb != NULL) (*cb)(100, "Done");
|
||||
// // vcg::tri::UpdateNormals<CMeshO>::PerVertex(m.cm); // updates normals
|
||||
//
|
||||
// m.updateDataMask(MeshModel::MM_VERTCOLOR);
|
||||
//
|
||||
// int t3=clock();
|
||||
// if(logFP2) fprintf(logFP2,"---------- Total Processing Time%i\n\n\n",t3-t0);
|
||||
// if(logFP2) fclose(logFP2);
|
||||
// logFP2=0;
|
||||
//
|
||||
//
|
||||
// //// Importing rasters
|
||||
//
|
||||
// //QList<EpochModel>::iterator li;
|
||||
// for(li=er.modelList.begin(), i=0;li!=er.modelList.end();++li,++i)
|
||||
// {
|
||||
// //RasterModel &pm =addNewRaster("","Poisson mesh");
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// } while(epochDialog->exportToPLY);
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
69
src/plugins_experimental/edit_epoch/epoch_io.h
Normal file
69
src/plugins_experimental/edit_epoch/epoch_io.h
Normal file
@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* A versatile mesh processing toolbox o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
History
|
||||
|
||||
$Log$
|
||||
Revision 1.4 2007/11/26 07:35:26 cignoni
|
||||
Yet another small cosmetic change to the interface of the io filters.
|
||||
|
||||
Revision 1.3 2007/11/25 09:48:39 cignoni
|
||||
Changed the interface of the io filters. Now also a default bit set for the capabilities has to specified
|
||||
|
||||
Revision 1.2 2006/11/29 00:59:16 cignoni
|
||||
Cleaned plugins interface; changed useless help class into a plain string
|
||||
|
||||
Revision 1.1 2006/11/07 18:14:21 cignoni
|
||||
Moved from the epoch svn repository
|
||||
|
||||
Revision 1.1 2006/01/20 13:03:27 cignoni
|
||||
*** empty log message ***
|
||||
|
||||
*****************************************************************************/
|
||||
#ifndef EXTRAIOPLUGINV3D_H
|
||||
#define EXTRAIOPLUGINV3D_H
|
||||
|
||||
#include <QObject>
|
||||
#include <common/interfaces.h>
|
||||
#include "v3dImportDialog.h"
|
||||
|
||||
class EpochIO : public QObject, public MeshIOInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MeshIOInterface)
|
||||
|
||||
public:
|
||||
QList<Format> importFormats() const;
|
||||
QList<Format> exportFormats() const {return QList<Format>();};
|
||||
|
||||
EpochIO();
|
||||
~EpochIO();
|
||||
QString lastFileName;
|
||||
void GetExportMaskCapability(QString &, int &, int &) const {assert(0); return ;}
|
||||
|
||||
bool open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask,const RichParameterSet & par, vcg::CallBackPos *cb=0, QWidget *parent=0);
|
||||
bool save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask, const RichParameterSet &, vcg::CallBackPos *cb=0, QWidget *parent= 0);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
72
src/plugins_experimental/edit_epoch/epoch_reconstruction.h
Normal file
72
src/plugins_experimental/edit_epoch/epoch_reconstruction.h
Normal file
@ -0,0 +1,72 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _EPOCH_RECONSTRUCTION_H
|
||||
#define _EPOCH_RECONSTRUCTION_H
|
||||
|
||||
#include <QtXml>
|
||||
|
||||
#include <common/meshmodel.h>
|
||||
|
||||
#include "radial_distortion.h"
|
||||
#include "epoch_camera.h"
|
||||
#include "scalar_image.h"
|
||||
|
||||
|
||||
class EpochModel
|
||||
{
|
||||
public:
|
||||
int index;
|
||||
QString cameraName;
|
||||
QString maskName;
|
||||
QString depthName;
|
||||
QString textureName;
|
||||
QString countName;
|
||||
vcg::EpochCamera cam;
|
||||
vcg::Shotf shot;
|
||||
bool Init(QDomNode &node);
|
||||
static QString ThumbName(QString &imageName);
|
||||
|
||||
bool BuildMesh(CMeshO &m, int subsampleFactor, int minCount, float minAngleCos, int smoothSteps,
|
||||
bool dilation, int dilationPasses, int dilationSize, bool erosion, int erosionPasses, int erosionSize,float scalingFactor);
|
||||
void SmartSubSample(int subsampleFactor, FloatImage &fli, CharImage &chi, FloatImage &subD,FloatImage &subQ, int minCount);
|
||||
void AddCameraIcon(CMeshO &m);
|
||||
bool CombineHandMadeMaskAndCount(CharImage &qualityImg, QString maskName );
|
||||
void GenerateCountImage();
|
||||
void GenerateGradientSmoothingMask(int subsampleFactor, QImage &OriginalTexture, CharImage &mask);
|
||||
void Laplacian2(FloatImage &depth, FloatImage &Q, int minCount, CharImage &mask, float depthThr);
|
||||
float ComputeDepthJumpThr(FloatImage &depthImgf, float percentile);
|
||||
void depthFilter(FloatImage &depthImgf, FloatImage &countImgf, float depthJumpThr,
|
||||
bool dilation, int dilationNumPasses, int dilationWinsize, bool erosion, int erosionNumPasses, int erosionWinsize);
|
||||
|
||||
QIcon *getIcon();
|
||||
};
|
||||
|
||||
class EpochReconstruction
|
||||
{
|
||||
public:
|
||||
QString name, author, created;
|
||||
QList<EpochModel> modelList;
|
||||
};
|
||||
|
||||
#endif
|
||||
127
src/plugins_experimental/edit_epoch/fillImage.cpp
Normal file
127
src/plugins_experimental/edit_epoch/fillImage.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "fillImage.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace ui
|
||||
{
|
||||
|
||||
fillImage::fillImage()
|
||||
{
|
||||
}
|
||||
|
||||
fillImage::~fillImage()
|
||||
{
|
||||
}
|
||||
|
||||
void fillImage::Compute(const QImage& input, int x, int y, int threshold_gradient, int threshold_fixed, QImage& output)
|
||||
{
|
||||
threshold_gradient_ = threshold_gradient;
|
||||
threshold_fixed_ = threshold_fixed;
|
||||
input_ = input;
|
||||
W = input.width();
|
||||
H = input.height();
|
||||
xo = x;
|
||||
yo = y;
|
||||
|
||||
output = QImage(W, H, QImage::Format_Mono);
|
||||
computed_ = QImage(W, H, QImage::Format_Mono);
|
||||
output.fill(0);
|
||||
computed_.fill(0);
|
||||
|
||||
ComputeGradient(input, gradient_);
|
||||
|
||||
pixels_to_do_.push_back(std::make_pair(x,y));
|
||||
while(!pixels_to_do_.empty())
|
||||
{
|
||||
DealWithPixel(pixels_to_do_.front(),output);
|
||||
pixels_to_do_.pop_front();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool fillImage::ShouldWeCompute(int x, int y)
|
||||
{
|
||||
if (input_.isGrayscale())
|
||||
return (gradient_.get(x,y) < threshold_gradient_ && computed_.pixelIndex(x,y) == 0 && std::abs(qGray(input_.pixel(x,y)) - qGray(input_.pixel(xo,yo))) < threshold_fixed_);
|
||||
else
|
||||
return (gradient_.get(x,y) < threshold_gradient_ && computed_.pixelIndex(x,y) == 0 && std::abs(qRed(input_.pixel(x,y)) - qRed(input_.pixel(xo,yo))) < threshold_fixed_ && std::abs(qGreen(input_.pixel(x,y)) - qGreen(input_.pixel(xo,yo))) < threshold_fixed_ && std::abs(qBlue(input_.pixel(x,y)) - qBlue(input_.pixel(xo,yo))) < threshold_fixed_);
|
||||
}
|
||||
|
||||
void fillImage::DealWithPixel(const std::pair<int,int>& xy, QImage& output)
|
||||
{
|
||||
int x = xy.first;
|
||||
int y = xy.second;
|
||||
if (computed_.pixelIndex(x,y) == 1)
|
||||
return;
|
||||
output.setPixel(x,y,1);
|
||||
computed_.setPixel(x,y,1);
|
||||
|
||||
if (x>0 && ShouldWeCompute(x-1,y))
|
||||
pixels_to_do_.push_back(std::make_pair(x-1,y));
|
||||
if (x<W-1 && ShouldWeCompute(x+1, y))
|
||||
pixels_to_do_.push_back(std::make_pair(x+1,y));
|
||||
if (y>0 && ShouldWeCompute(x, y-1))
|
||||
pixels_to_do_.push_back(std::make_pair(x,y-1));
|
||||
if (y<H-1 && ShouldWeCompute(x, y+1))
|
||||
pixels_to_do_.push_back(std::make_pair(x,y+1));
|
||||
}
|
||||
|
||||
void fillImage::ComputeGradient(const QImage& input, myGSImage& output)
|
||||
{
|
||||
input.save("input.jpg", "jpg");
|
||||
size_t W = input.width();
|
||||
size_t H = input.height();
|
||||
|
||||
float* temp = new float[W*H];
|
||||
for (size_t i=0; i<W*H; ++i)
|
||||
temp[i] = 0.0;
|
||||
|
||||
float dx, dy;
|
||||
float min = std::numeric_limits<float>::max();
|
||||
float max = -std::numeric_limits<float>::max();
|
||||
|
||||
for (size_t i=1; i<W; ++i)
|
||||
for (size_t j=1; j<H; ++j)
|
||||
{
|
||||
dx = qGray(input.pixel(i,j)) - qGray(input.pixel(i-1,j));
|
||||
dy = qGray(input.pixel(i,j)) - qGray(input.pixel(i,j-1));
|
||||
|
||||
dx = std::sqrt(dx*dx + dy*dy);
|
||||
temp[j*W+i] = dx;
|
||||
|
||||
if (dx > max)
|
||||
max = dx;
|
||||
if (dx < min)
|
||||
min = dx;
|
||||
}
|
||||
output = myGSImage(W, H);
|
||||
|
||||
float range = 255./(max-min);
|
||||
for (size_t i=0; i<W; ++i)
|
||||
for (size_t j=0; j<H; ++j)
|
||||
output.put(i, j, (unsigned char)((temp[j*W+i]-min)*range));
|
||||
}
|
||||
}
|
||||
117
src/plugins_experimental/edit_epoch/fillImage.h
Normal file
117
src/plugins_experimental/edit_epoch/fillImage.h
Normal file
@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __IO_FILL_AREA_INC_
|
||||
#define __IO_FILL_AREA_INC_
|
||||
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
namespace ui
|
||||
{
|
||||
struct myGSImage
|
||||
{
|
||||
unsigned char* data;
|
||||
size_t w, h;
|
||||
|
||||
myGSImage()
|
||||
{
|
||||
data = 0;
|
||||
}
|
||||
|
||||
myGSImage(const myGSImage& image)
|
||||
{
|
||||
w = image.w;
|
||||
h = image.h;
|
||||
if (data)
|
||||
delete [] data;
|
||||
data = new unsigned char[w*h];
|
||||
memcpy(data, image.data, w*h);
|
||||
}
|
||||
|
||||
myGSImage & operator = (const myGSImage& image)
|
||||
{
|
||||
w = image.w;
|
||||
h = image.h;
|
||||
if (data)
|
||||
delete [] data;
|
||||
data = new unsigned char[w*h];
|
||||
memcpy(data, image.data, w*h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
myGSImage(size_t width, size_t height): w(width), h(height)
|
||||
{
|
||||
data = new unsigned char[width*height];
|
||||
};
|
||||
|
||||
~myGSImage()
|
||||
{
|
||||
if (data)
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
unsigned char get(size_t i, size_t j) const
|
||||
{
|
||||
return data[j*w + i];
|
||||
}
|
||||
|
||||
void put(size_t i, size_t j, unsigned char a)
|
||||
{
|
||||
data[j*w + i] = a;
|
||||
}
|
||||
|
||||
void fill(unsigned char a)
|
||||
{
|
||||
for (size_t i=0; i<w; ++i)
|
||||
for (size_t j=0; j<h; ++j)
|
||||
put(i,j,a);
|
||||
}
|
||||
};
|
||||
|
||||
class fillImage
|
||||
{
|
||||
public:
|
||||
fillImage();
|
||||
virtual ~fillImage();
|
||||
void Compute(const QImage& input, int x, int y, int threshold_gradient,
|
||||
int threshold_fixed, QImage& output);
|
||||
|
||||
protected:
|
||||
|
||||
bool ShouldWeCompute(int x, int y);
|
||||
|
||||
void ComputeGradient(const QImage&, myGSImage& output);
|
||||
|
||||
void DealWithPixel(const std::pair<int,int>&, QImage& output);
|
||||
QImage input_, computed_;
|
||||
myGSImage gradient_;
|
||||
int threshold_gradient_, threshold_fixed_;
|
||||
int W,H;
|
||||
int xo, yo;
|
||||
std::deque<std::pair<int,int> > pixels_to_do_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
BIN
src/plugins_experimental/edit_epoch/images/cur_align.png
Normal file
BIN
src/plugins_experimental/edit_epoch/images/cur_align.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 291 B |
BIN
src/plugins_experimental/edit_epoch/images/icon_align.png
Normal file
BIN
src/plugins_experimental/edit_epoch/images/icon_align.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
85
src/plugins_experimental/edit_epoch/images/icon_align.svg
Normal file
85
src/plugins_experimental/edit_epoch/images/icon_align.svg
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.44.1"
|
||||
sodipodi:docbase="/Users/cignoni/Documents/devel/meshlab/src/meshlabplugins/editalign/images"
|
||||
sodipodi:docname="icon_align.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.90587"
|
||||
inkscape:cx="400.85687"
|
||||
inkscape:cy="661.09126"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:window-width="1027"
|
||||
inkscape:window-height="776"
|
||||
inkscape:window-x="45"
|
||||
inkscape:window-y="22" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:yellow;stroke:black;stroke-width:0.46049017;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Times;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10.4538814;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
|
||||
id="path1876"
|
||||
sodipodi:cx="399.54025"
|
||||
sodipodi:cy="395.05637"
|
||||
sodipodi:rx="5.0892239"
|
||||
sodipodi:ry="5.0892239"
|
||||
d="M 404.62948 395.05637 A 5.0892239 5.0892239 0 1 1 394.45103,395.05637 A 5.0892239 5.0892239 0 1 1 404.62948 395.05637 z"
|
||||
transform="matrix(2.295798,0,0,2.295798,-514.5326,-515.6987)"
|
||||
inkscape:export-xdpi="471.64999"
|
||||
inkscape:export-ydpi="471.64999"
|
||||
inkscape:export-filename="/Users/cignoni/Documents/devel/meshlab/src/meshlabplugins/editalign/images/icon_align.png" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times"
|
||||
x="395.52896"
|
||||
y="398.0043"
|
||||
id="text1966"
|
||||
sodipodi:linespacing="125%"
|
||||
inkscape:transform-center-x="-2.2011998"
|
||||
inkscape:transform-center-y="4.0400391"
|
||||
inkscape:export-filename="/Users/cignoni/Documents/devel/meshlab/src/meshlabplugins/editalign/images/icon_align.png"
|
||||
inkscape:export-xdpi="471.64999"
|
||||
inkscape:export-ydpi="471.64999"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1968"
|
||||
x="395.52896"
|
||||
y="398.0043"
|
||||
style="font-size:20px;font-weight:bold">A</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
BIN
src/plugins_experimental/edit_epoch/images/icon_arc3d.png
Normal file
BIN
src/plugins_experimental/edit_epoch/images/icon_arc3d.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
333
src/plugins_experimental/edit_epoch/maskImageWidget.cpp
Normal file
333
src/plugins_experimental/edit_epoch/maskImageWidget.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "maskImageWidget.h"
|
||||
#include "maskRenderWidget.h"
|
||||
#include "fillImage.h"
|
||||
#include <QtGui/QPen>
|
||||
#include <QtGui/QBrush>
|
||||
#include <QtGui/QPolygon>
|
||||
#include <QtGui/QPixmap>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QPalette>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QPaintEvent>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QToolBar>
|
||||
#include <QtGui/QSpinBox>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QDesktopWidget>
|
||||
|
||||
#include <stack>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef WIN32
|
||||
#undef min
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
|
||||
namespace ui
|
||||
{
|
||||
|
||||
struct maskImageWidget::Impl
|
||||
{
|
||||
enum DrawMode { Pen, Eraser } mode_;
|
||||
|
||||
maskRenderWidget *render_area_;
|
||||
int threshold_gradient_, threshold_fixed_;
|
||||
int realwidth_, realheight_;
|
||||
Impl();
|
||||
};
|
||||
|
||||
|
||||
maskImageWidget::Impl::Impl()
|
||||
{
|
||||
mode_ = Pen;
|
||||
threshold_gradient_ = 100;
|
||||
threshold_fixed_ = 30;
|
||||
}
|
||||
|
||||
|
||||
maskImageWidget::maskImageWidget(const QImage& image, QWidget *parent) : QDialog(parent), pimpl_(new Impl)
|
||||
{
|
||||
init(image);
|
||||
}
|
||||
|
||||
|
||||
maskImageWidget::~maskImageWidget() throw()
|
||||
{
|
||||
delete pimpl_;
|
||||
}
|
||||
|
||||
QImage maskImageWidget::getMask() const
|
||||
{
|
||||
return pimpl_->render_area_->getMask(pimpl_->realwidth_, pimpl_->realheight_);
|
||||
}
|
||||
|
||||
void maskImageWidget::loadMask(const QString& filename)
|
||||
{
|
||||
pimpl_->render_area_->load(filename);
|
||||
}
|
||||
|
||||
void maskImageWidget::init(const QImage& image)
|
||||
{
|
||||
setWindowTitle(tr("Mask Editor"));
|
||||
|
||||
QPixmap load("coral_open32x32.png");
|
||||
QPixmap save("coral_save32x32.png");
|
||||
QPixmap undo("coral_undo32x32.png");
|
||||
QPixmap redo("coral_redo32x32.png");
|
||||
QPixmap pen("coral_pencil32x32.png");
|
||||
QPixmap eraser("coral_eraser32x32.png");
|
||||
|
||||
QAction *canvasloadmask = new QAction(this);
|
||||
canvasloadmask->setIcon(load);
|
||||
canvasloadmask->setText(tr("&Load Mask"));
|
||||
QAction *canvassavemask = new QAction(this);
|
||||
canvassavemask->setIcon(QIcon(save));
|
||||
canvassavemask->setText(tr("&Save Mask"));
|
||||
QAction *canvasundo = new QAction(this);
|
||||
canvasundo->setIcon(QIcon(undo));
|
||||
canvasundo->setText(tr("&Undo"));
|
||||
canvasundo->setShortcut(QKeySequence("Ctrl+Z"));
|
||||
QAction *canvasredo = new QAction(this);
|
||||
canvasredo->setIcon(QIcon(redo));
|
||||
canvasredo->setText(tr("&Redo"));
|
||||
canvasredo->setShortcut(QKeySequence("Ctrl+Shift+Z"));
|
||||
QAction *canvasclear = new QAction(tr("&Clear"), this);
|
||||
canvasclear->setShortcut(QKeySequence("Ctrl+C"));
|
||||
|
||||
QAction *canvaspen = new QAction(this);
|
||||
canvaspen->setIcon(QIcon(pen));
|
||||
canvaspen->setText(tr("&Pen"));
|
||||
QAction *canvaseraser = new QAction(this);
|
||||
canvaseraser->setIcon(QIcon(eraser));
|
||||
canvaseraser->setText(tr("&Eraser"));
|
||||
|
||||
QActionGroup *actions(new QActionGroup(this));
|
||||
actions->addAction(canvaspen);
|
||||
actions->addAction(canvaseraser);
|
||||
canvaspen->setCheckable(true);
|
||||
canvaseraser->setCheckable(true);
|
||||
canvaspen->setChecked(true);
|
||||
actions->setExclusive(true);
|
||||
|
||||
QAction *canvasOK = new QAction(this);
|
||||
canvasOK->setText("OK");
|
||||
QAction *canvasCancel = new QAction(this);
|
||||
canvasCancel->setText("Cancel");
|
||||
|
||||
QBoxLayout *layout(new QVBoxLayout(this));
|
||||
|
||||
// We don't want a real-size image. We will downscale it!
|
||||
QImage image_to_use = image;
|
||||
pimpl_->realwidth_ = image.width();
|
||||
pimpl_->realheight_ = image.height();
|
||||
qDebug("maskImageWidget::Init real wxh %i x%i",pimpl_->realwidth_,pimpl_->realheight_);
|
||||
QDesktopWidget *desktop(QApplication::desktop());
|
||||
if (image.width() > (desktop->width() * .8) ||
|
||||
image.height() > (desktop->height() * .8))
|
||||
{
|
||||
int width(desktop->width()), height(desktop->height());
|
||||
image_to_use = image.scaled((int)std::floor(width * .75),
|
||||
(int)std::floor(height * .75), Qt::KeepAspectRatio);
|
||||
}
|
||||
pimpl_->render_area_ = new maskRenderWidget(image_to_use, this);
|
||||
|
||||
QToolBar *canvas_toolbar(new QToolBar(this));
|
||||
canvas_toolbar->addSeparator();
|
||||
canvas_toolbar->addAction(canvasloadmask);
|
||||
canvas_toolbar->addAction(canvassavemask);
|
||||
canvas_toolbar->addSeparator();
|
||||
|
||||
canvas_toolbar->addAction(canvasundo);
|
||||
canvas_toolbar->addAction(canvasredo);
|
||||
canvas_toolbar->addSeparator();
|
||||
|
||||
QSpinBox *pen_width(new QSpinBox(canvas_toolbar));
|
||||
pen_width->setToolTip(tr("Pen Width"));
|
||||
pen_width->setRange(0, 80);
|
||||
pen_width->setSingleStep(2);
|
||||
pen_width->setValue(16);
|
||||
connect(pen_width, SIGNAL(valueChanged(int)), SLOT(setCanvasPenWidth(int)));
|
||||
canvas_toolbar->addWidget(pen_width);
|
||||
canvas_toolbar->addAction(canvaspen);
|
||||
canvas_toolbar->addAction(canvaseraser);
|
||||
canvas_toolbar->addSeparator();
|
||||
|
||||
QSpinBox *gradient(new QSpinBox(canvas_toolbar));
|
||||
gradient->setToolTip("Gradient Threshold");
|
||||
gradient->setRange(0, 255);
|
||||
gradient->setValue(pimpl_->threshold_gradient_);
|
||||
connect(gradient, SIGNAL(valueChanged(int)), SLOT(setGradientThreshold(int)));
|
||||
|
||||
QSpinBox *fixed(new QSpinBox(canvas_toolbar));
|
||||
fixed->setToolTip("Fixed Threshold");
|
||||
fixed->setRange(0, 255);
|
||||
fixed->setValue(pimpl_->threshold_fixed_);
|
||||
connect(fixed, SIGNAL(valueChanged(int)), SLOT(setFixedThreshold(int)));
|
||||
|
||||
canvas_toolbar->addWidget(gradient);
|
||||
canvas_toolbar->addWidget(fixed);
|
||||
canvas_toolbar->addSeparator();
|
||||
|
||||
canvas_toolbar->addAction(canvasOK);
|
||||
canvas_toolbar->addAction(canvasCancel);
|
||||
|
||||
layout->addWidget(canvas_toolbar);
|
||||
layout->addWidget(pimpl_->render_area_);
|
||||
layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
connect(canvasloadmask, SIGNAL(activated()), SLOT(loadMask()));
|
||||
connect(canvassavemask, SIGNAL(activated()), SLOT(saveMask()));
|
||||
connect(canvasundo, SIGNAL(activated()), pimpl_->render_area_, SLOT(undo()));
|
||||
connect(canvasredo, SIGNAL(activated()), pimpl_->render_area_, SLOT(redo()));
|
||||
connect(canvasclear, SIGNAL(activated()), pimpl_->render_area_, SLOT(clear()));
|
||||
connect(canvaspen, SIGNAL(activated()), SLOT(setCanvasPen()));
|
||||
connect(canvaseraser, SIGNAL(activated()), SLOT(setCanvasEraser()));
|
||||
|
||||
connect(pimpl_->render_area_, SIGNAL(pointSelected(const QPoint &)), SLOT(automaticMask(const QPoint &)));
|
||||
|
||||
connect(canvasOK, SIGNAL(activated()), SLOT(accept()));
|
||||
connect(canvasCancel, SIGNAL(activated()), SLOT(reject()));
|
||||
}
|
||||
|
||||
void maskImageWidget::setCanvasPenWidth(int width)
|
||||
{
|
||||
QPen pen(pimpl_->render_area_->pen());
|
||||
pen.setWidth(width);
|
||||
pimpl_->render_area_->setPen(pen);
|
||||
}
|
||||
|
||||
|
||||
void maskImageWidget::setCanvasPen()
|
||||
{
|
||||
QPen pen(pimpl_->render_area_->pen());
|
||||
pen.setColor(QColor(Qt::black));
|
||||
pen.setJoinStyle(Qt::RoundJoin);
|
||||
pimpl_->render_area_->setPen(pen);
|
||||
}
|
||||
|
||||
|
||||
void maskImageWidget::setCanvasEraser()
|
||||
{
|
||||
QPen pen(pimpl_->render_area_->pen());
|
||||
pen.setColor(QColor(Qt::transparent));
|
||||
pen.setJoinStyle(Qt::RoundJoin);
|
||||
pimpl_->render_area_->setPen(pen);
|
||||
}
|
||||
|
||||
|
||||
void maskImageWidget::setGradientThreshold(int threshold_gradient)
|
||||
{
|
||||
pimpl_->threshold_gradient_ = threshold_gradient;
|
||||
}
|
||||
|
||||
|
||||
void maskImageWidget::setFixedThreshold(int threshold_fixed)
|
||||
{
|
||||
pimpl_->threshold_fixed_ = threshold_fixed;
|
||||
}
|
||||
|
||||
void maskImageWidget::loadMask()
|
||||
{
|
||||
try
|
||||
{
|
||||
QString filename(QFileDialog::getOpenFileName(this, QString("Open mask file"), QString(), QString("*.png")));
|
||||
if (QString::null != filename)
|
||||
pimpl_->render_area_->load(filename);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Problem"), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool check_extension(QString &filename, const QString &ext)
|
||||
{
|
||||
bool ret(false);
|
||||
if (ext != filename.section('.', -1))
|
||||
{
|
||||
int index(filename.lastIndexOf('.'));
|
||||
if (-1 == index)
|
||||
{
|
||||
filename += '.';
|
||||
index += filename.size();
|
||||
}
|
||||
filename.replace(index + 1, ext.size(), ext);
|
||||
filename.resize(index + 1 + ext.size());
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
void maskImageWidget::saveMask()
|
||||
{
|
||||
try
|
||||
{
|
||||
QString filename(QFileDialog::getSaveFileName(this, QString("Save mask file"), QString(), QString("*.png")));
|
||||
if (QString::null != filename)
|
||||
{
|
||||
check_extension(filename, QString("png"));
|
||||
pimpl_->render_area_->save(filename, pimpl_->realwidth_, pimpl_->realheight_);
|
||||
}
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Epoch 3D Webservice"), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maskImageWidget::automaticMask(const QPoint &p)
|
||||
{
|
||||
QImage image = (pimpl_->render_area_->palette().base().texture()).toImage();
|
||||
QImage out;
|
||||
fillImage fi;
|
||||
fi.Compute(image, p.x(), p.y(), pimpl_->threshold_gradient_, pimpl_->threshold_fixed_, out);
|
||||
|
||||
const size_t width(image.width()), height(image.height());
|
||||
QImage temp(pimpl_->render_area_->alphaMask());
|
||||
for (size_t i = 0; i < width; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < height; ++j)
|
||||
{
|
||||
if (out.pixelIndex(i, j) > 0)
|
||||
temp.setPixel(i, j, QColor(Qt::black).rgba());
|
||||
}
|
||||
}
|
||||
//temp.save("temp.jpg","jpg");
|
||||
pimpl_->render_area_->setAlphaMask(temp);
|
||||
}
|
||||
};
|
||||
76
src/plugins_experimental/edit_epoch/maskImageWidget.h
Normal file
76
src/plugins_experimental/edit_epoch/maskImageWidget.h
Normal file
@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __IO_MASK_IMAGE_WIDGET_INC__
|
||||
#define __IO_MASK_IMAGE_WIDGET_INC__
|
||||
|
||||
|
||||
#include <QtGui/QDialog>
|
||||
|
||||
|
||||
namespace ui
|
||||
{
|
||||
/*! \class maskImageWidget
|
||||
\brief A brief description
|
||||
\author Maarten Vergauwen
|
||||
*/
|
||||
class maskImageWidget : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct Impl;
|
||||
Impl* pimpl_;
|
||||
|
||||
void init (const QImage &);
|
||||
|
||||
public:
|
||||
/*! \brief Constructor
|
||||
\param The image.
|
||||
*/
|
||||
explicit maskImageWidget(const QImage &, QWidget *parent = 0);
|
||||
;
|
||||
/*! \brief Destructor
|
||||
*/
|
||||
virtual ~maskImageWidget() throw();
|
||||
|
||||
QImage getMask() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void loadMask(const QString& filename);
|
||||
|
||||
private slots:
|
||||
|
||||
void setCanvasPenWidth(int);
|
||||
void setCanvasPen();
|
||||
void setCanvasEraser();
|
||||
void setGradientThreshold(int);
|
||||
void setFixedThreshold(int);
|
||||
void automaticMask(const QPoint &);
|
||||
void loadMask();
|
||||
void saveMask();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
385
src/plugins_experimental/edit_epoch/maskRenderWidget.cpp
Normal file
385
src/plugins_experimental/edit_epoch/maskRenderWidget.cpp
Normal file
@ -0,0 +1,385 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "maskRenderWidget.h"
|
||||
#include <QtGui/QPen>
|
||||
#include <QtGui/QBrush>
|
||||
#include <QtGui/QPolygon>
|
||||
#include <QtGui/QPixmap>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QPalette>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QPaintEvent>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
#include <stack>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef WIN32
|
||||
#undef min
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
|
||||
namespace ui
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
template <class T>
|
||||
inline void unwind(std::stack<T> &stack)
|
||||
{
|
||||
while (!stack.empty())
|
||||
stack.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct maskRenderWidget::Impl
|
||||
{
|
||||
enum Shape { Nothing, Polyline, Rect, Rubber, Point } shape_;
|
||||
|
||||
QPen pen_;
|
||||
QPolygon polygon_;
|
||||
|
||||
QPoint start_point_, last_point_, end_point_;
|
||||
QRect rubber_band_;
|
||||
|
||||
QImage foreground_, band_buffer_;
|
||||
std::stack<QImage> undo_, redo_;
|
||||
|
||||
Impl();
|
||||
|
||||
void paintOnDevice(QPaintDevice *);
|
||||
};
|
||||
|
||||
|
||||
maskRenderWidget::Impl::Impl() : pen_(Qt::black)
|
||||
{
|
||||
shape_ = Nothing;
|
||||
pen_.setWidth(16);
|
||||
pen_.setCapStyle(Qt::RoundCap);
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::Impl::paintOnDevice(QPaintDevice *device)
|
||||
{
|
||||
assert(device);
|
||||
QPainter painter(device);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
switch (shape_)
|
||||
{
|
||||
case Impl::Polyline:
|
||||
{
|
||||
painter.setPen(pen_);
|
||||
painter.drawPolyline(polygon_);
|
||||
}
|
||||
break;
|
||||
case Impl::Point:
|
||||
{
|
||||
painter.setPen(pen_);
|
||||
QPoint p2(end_point_.x() + 1, end_point_.y() + 1);
|
||||
painter.drawLine(end_point_, p2);
|
||||
}
|
||||
break;
|
||||
case Impl::Rect:
|
||||
{
|
||||
QPen pen;
|
||||
pen.setColor(pen_.color());
|
||||
painter.setPen(pen);
|
||||
const int x(rubber_band_.x()), y(rubber_band_.y());
|
||||
const int w(rubber_band_.width()), h(rubber_band_.height());
|
||||
for (int i = 0; i < w; ++i)
|
||||
for (int j = 0; j < h; ++j)
|
||||
painter.drawPoint(QPoint(x + i, y + j));
|
||||
rubber_band_ = QRect(0, 0, 0, 0);
|
||||
}
|
||||
break;
|
||||
case Impl::Rubber:
|
||||
{
|
||||
QPen pen(Qt::gray);
|
||||
pen.setWidth(1);
|
||||
painter.setPen(pen);
|
||||
painter.drawRect(rubber_band_);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
maskRenderWidget::maskRenderWidget(QWidget *parent) : QWidget(parent), pimpl_(new Impl)
|
||||
{
|
||||
setAttribute(Qt::WA_StaticContents);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
QImage image(640, 480, QImage::Format_ARGB32);
|
||||
image.fill(Qt::white);
|
||||
setImage(image);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
maskRenderWidget::maskRenderWidget(const QImage& image, QWidget *parent) : QWidget(parent), pimpl_(new Impl)
|
||||
{
|
||||
qDebug("MaskRenderWidget started with an image %i x %i",image.width(),image.height());
|
||||
setAttribute(Qt::WA_StaticContents);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
setImage(image);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
maskRenderWidget::~maskRenderWidget() throw()
|
||||
{
|
||||
delete pimpl_;
|
||||
}
|
||||
|
||||
void maskRenderWidget::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Z && (e->modifiers() & Qt::ControlModifier))
|
||||
{
|
||||
undo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if (e->button() == Qt::LeftButton)
|
||||
{
|
||||
if (e->modifiers() & Qt::ShiftModifier)
|
||||
{
|
||||
emit pointSelected(e->pos());
|
||||
}
|
||||
else
|
||||
{
|
||||
pimpl_->undo_.push(pimpl_->foreground_);
|
||||
pimpl_->end_point_ = e->pos();
|
||||
pimpl_->polygon_ = QPolygon();
|
||||
pimpl_->polygon_ << e->pos();
|
||||
priv::unwind(pimpl_->redo_);
|
||||
pimpl_->shape_ = Impl::Point;
|
||||
update();
|
||||
}
|
||||
}
|
||||
else if (e->button() == Qt::RightButton)
|
||||
{
|
||||
pimpl_->undo_.push(pimpl_->foreground_);
|
||||
QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
|
||||
pimpl_->start_point_ = e->pos();
|
||||
pimpl_->shape_ = Impl::Rubber;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
if (Impl::Rubber == pimpl_->shape_)
|
||||
{
|
||||
pimpl_->band_buffer_ = pimpl_->foreground_;
|
||||
int x(std::min(e->pos().x(), pimpl_->start_point_.x()));
|
||||
int y(std::min(e->pos().y(), pimpl_->start_point_.y()));
|
||||
int w(std::abs((float)e->pos().x() - pimpl_->start_point_.x()));
|
||||
int h(std::abs((float)e->pos().y() - pimpl_->start_point_.y()));
|
||||
|
||||
pimpl_->rubber_band_ = QRect(x, y, w, h);
|
||||
update();
|
||||
}
|
||||
else if (Impl::Point == pimpl_->shape_)
|
||||
{
|
||||
pimpl_->shape_ = Impl::Polyline;
|
||||
}
|
||||
else if (Impl::Polyline == pimpl_->shape_)
|
||||
{
|
||||
pimpl_->last_point_ = pimpl_->end_point_;
|
||||
pimpl_->end_point_ = e->pos();
|
||||
pimpl_->polygon_ << e->pos();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
if (Impl::Rubber == pimpl_->shape_)
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
pimpl_->shape_ = Impl::Rect;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
else if (Impl::Polyline == pimpl_->shape_)
|
||||
{
|
||||
pimpl_->last_point_ = pimpl_->end_point_;
|
||||
pimpl_->end_point_ = e->pos();
|
||||
update();
|
||||
}
|
||||
pimpl_->shape_ = Impl::Nothing;
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QImage * device = &pimpl_->foreground_;
|
||||
|
||||
if (Impl::Rubber == pimpl_->shape_)
|
||||
device = &pimpl_->band_buffer_;
|
||||
|
||||
pimpl_->paintOnDevice(device);
|
||||
|
||||
QPainter painter(this);
|
||||
QVector<QRect> rects(e->region().rects());
|
||||
for (int i = 0; i < rects.count(); ++i)
|
||||
{
|
||||
QRect r = rects[i];
|
||||
painter.drawImage(r, *device, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QSize maskRenderWidget::sizeHint() const
|
||||
{
|
||||
return minimumSizeHint();
|
||||
}
|
||||
|
||||
|
||||
QSize maskRenderWidget::minimumSizeHint() const
|
||||
{
|
||||
return pimpl_->foreground_.isNull()? QSize(400, 400) : pimpl_->foreground_.size();
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::setPen(const QPen &pen)
|
||||
{
|
||||
pimpl_->pen_ = pen;
|
||||
}
|
||||
|
||||
|
||||
QPen maskRenderWidget::pen() const
|
||||
{
|
||||
return pimpl_->pen_;
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::setImage(const QImage &image)
|
||||
{
|
||||
QPalette palette;
|
||||
#if (QT_VERSION >= 0x040100)
|
||||
setAutoFillBackground(true);
|
||||
#endif
|
||||
palette.setBrush(backgroundRole(), QBrush(QPixmap::fromImage(image)));
|
||||
setPalette(palette);
|
||||
pimpl_->foreground_ = image;
|
||||
QImage alpha(image.width(), image.height(),QImage::Format_Mono);
|
||||
alpha.fill(0);
|
||||
|
||||
pimpl_->foreground_.setAlphaChannel(alpha);
|
||||
|
||||
priv::unwind(pimpl_->undo_);
|
||||
priv::unwind(pimpl_->redo_);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::load(const QString &filename)
|
||||
{
|
||||
QImage alpha(filename);
|
||||
// I would have liked to use KeepAspectRatio but if someone loads a
|
||||
// bogus mask with a different ratio, the rest will crash. The output
|
||||
// is now undefined but it won't crash.
|
||||
alpha = alpha.scaled(pimpl_->foreground_.width(), pimpl_->foreground_.height(), Qt::IgnoreAspectRatio);
|
||||
QImage temp(pimpl_->foreground_);
|
||||
const int width(temp.width()), height(temp.height());
|
||||
for (int i = 0; i < width; ++i)
|
||||
for (int j = 0; j < height; ++j)
|
||||
{
|
||||
QRgb rgb = temp.pixel(i, j);
|
||||
temp.setPixel(i, j, QColor(qRed(rgb), qGreen(rgb), qBlue(rgb), qGray(alpha.pixel(i, j))).rgba());
|
||||
}
|
||||
setAlphaMask(temp);
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::save(const QString &filename, int w, int h)
|
||||
{
|
||||
pimpl_->foreground_.alphaChannel().scaled(w, h, Qt::KeepAspectRatio).save(filename, "PGM");
|
||||
}
|
||||
|
||||
QImage maskRenderWidget::getMask(int w, int h) const
|
||||
{
|
||||
// return pimpl_->foreground_.alphaChannel().scaled(w, h, Qt::KeepAspectRatio);
|
||||
return pimpl_->foreground_.alphaChannel().scaled(w, h); // changed to this becouse sometimes for rounding error did not create the original size.
|
||||
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::setAlphaMask(const QImage &image)
|
||||
{
|
||||
pimpl_->undo_.push(pimpl_->foreground_);
|
||||
pimpl_->foreground_ = image;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
QImage maskRenderWidget::alphaMask() const
|
||||
{
|
||||
return pimpl_->foreground_;
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::undo()
|
||||
{
|
||||
if (!pimpl_->undo_.empty())
|
||||
{
|
||||
pimpl_->redo_.push(pimpl_->foreground_);
|
||||
pimpl_->foreground_ = pimpl_->undo_.top();
|
||||
pimpl_->undo_.pop();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::redo()
|
||||
{
|
||||
if (!pimpl_->redo_.empty())
|
||||
{
|
||||
pimpl_->undo_.push(pimpl_->foreground_);
|
||||
pimpl_->foreground_ = pimpl_->redo_.top();
|
||||
pimpl_->redo_.pop();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maskRenderWidget::clear()
|
||||
{
|
||||
pimpl_->undo_.push(pimpl_->foreground_);
|
||||
priv::unwind(pimpl_->redo_);
|
||||
pimpl_->foreground_.fill(QColor(Qt::transparent).rgba());
|
||||
update();
|
||||
}
|
||||
};
|
||||
125
src/plugins_experimental/edit_epoch/maskRenderWidget.h
Normal file
125
src/plugins_experimental/edit_epoch/maskRenderWidget.h
Normal file
@ -0,0 +1,125 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __IO_MASK_RENDER_WIDGET_INC__
|
||||
#define __IO_MASK_RENDER_WIDGET_INC__
|
||||
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
|
||||
namespace ui
|
||||
{
|
||||
/*! \class maskRenderWidget
|
||||
\brief A brief description
|
||||
\author gmatthew
|
||||
*/
|
||||
class maskRenderWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct Impl;
|
||||
Impl* pimpl_;
|
||||
|
||||
virtual void keyPressEvent(QKeyEvent *);
|
||||
virtual void mousePressEvent(QMouseEvent *);
|
||||
virtual void mouseMoveEvent(QMouseEvent *);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *);
|
||||
virtual void paintEvent(QPaintEvent *);
|
||||
|
||||
public:
|
||||
/*! \brief Constructor
|
||||
*/
|
||||
explicit maskRenderWidget(QWidget *parent = 0);
|
||||
/*! \brief Constructor
|
||||
*/
|
||||
explicit maskRenderWidget(const QImage &, QWidget *parent = 0);
|
||||
/*! \brief Destructor
|
||||
*/
|
||||
virtual ~maskRenderWidget() throw();
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
virtual QSize sizeHint() const;
|
||||
virtual QSize minimumSizeHint() const;
|
||||
#endif
|
||||
|
||||
/*! \brief Set the drawable pen.
|
||||
\param The pen object.
|
||||
*/
|
||||
void setPen(const QPen &pen);
|
||||
/*! \brief Returns the drawable pen.
|
||||
\return pen The pen object.
|
||||
*/
|
||||
QPen pen() const;
|
||||
/*! \brief Set the background Image.
|
||||
\param image The image to be set as the background.
|
||||
*/
|
||||
void setImage(const QImage &);
|
||||
/*! \brief Load the alpha mask.
|
||||
\param filename The path to the image to be used as the mask.
|
||||
*/
|
||||
void load(const QString &filename);
|
||||
/*! \brief Save the alpha mask.
|
||||
\param filename The path to the image to be used as the mask.
|
||||
\param w The width of the image to save to.
|
||||
\param h The height of the image to save to.
|
||||
*/
|
||||
void save(const QString &filename, int w, int h);
|
||||
/*! \brief Get the alpha mask.
|
||||
\param w The width of the image to return.
|
||||
\param h The height of the image to return.
|
||||
*/
|
||||
QImage getMask(int w, int h) const;
|
||||
/*! \brief Set the alpha mask.
|
||||
\param image The image to be set as the mask.
|
||||
*/
|
||||
void setAlphaMask(const QImage &image);
|
||||
/*! \brief Returns the alpha mask.
|
||||
\return An qimage object.
|
||||
*/
|
||||
QImage alphaMask() const;
|
||||
|
||||
public slots:
|
||||
/*! \brief Undoes the last action and adds the current action to the redo stack and updates the display. If no more actions could be undone, does nothing.
|
||||
|
||||
The number of times this can be done is limited only by the resources available.
|
||||
*/
|
||||
void undo();
|
||||
/*! \brief Redoes the last action and adds the current action to the undo stack and updates the display. If no more actions could be redone, does nothing.
|
||||
|
||||
The number of times this can be done is limited only by the resources available.
|
||||
*/
|
||||
void redo();
|
||||
/*! \brief Clears the display.
|
||||
|
||||
This action is also added to the undo actions.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
signals:
|
||||
void pointSelected(const QPoint &);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
109
src/plugins_experimental/edit_epoch/radial_distortion.cpp
Normal file
109
src/plugins_experimental/edit_epoch/radial_distortion.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "radial_distortion.h"
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
void RadialDistortion::SetParameters(vector<double>& k, double max, int resolution)
|
||||
{
|
||||
k_ = k;
|
||||
max_ = max;
|
||||
resolution_ = resolution;
|
||||
|
||||
SetupLookupTable(max_, resolution_);
|
||||
}
|
||||
|
||||
void RadialDistortion::forward_map(double x1, double y1, double* x2, double* y2) const
|
||||
{
|
||||
ComputeNewXY(x1-ocx_, y1-ocy_, *x2, *y2);
|
||||
*x2 += ncx_;
|
||||
*y2 += ncy_;
|
||||
}
|
||||
|
||||
|
||||
void RadialDistortion::inverse_map(double x2, double y2, double* x1, double* y1) const
|
||||
{
|
||||
ComputeOldXY(x2-ncx_, y2-ncy_, *x1, *y1);
|
||||
*x1 += ocx_;
|
||||
*y1 += ocy_;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Relative w.r.t. center !
|
||||
void RadialDistortion::ComputeNewXY(double xo, double yo, double& xn, double& yn) const
|
||||
{
|
||||
double r = (xo*xo) + (yo*yo); // r is r squared
|
||||
double f = 1.0;
|
||||
for (int i = 0; i < static_cast<int>(k_.size()); i++) f += (k_[i] * pow(r, i+1));
|
||||
xn = f*xo;
|
||||
yn = f*yo;
|
||||
}
|
||||
|
||||
|
||||
void RadialDistortion::ComputeOldXY(double xn, double yn, double& xo, double& yo) const
|
||||
{
|
||||
double rn = sqrt((xn*xn) + (yn*yn)); //// r is r squared
|
||||
map<double, double>::const_iterator next = lookup_.upper_bound(rn);
|
||||
map<double, double>::const_iterator prev = next; prev--;
|
||||
|
||||
// The compiler will optimise this.
|
||||
double a = (*prev).first;
|
||||
double b = (*next).first;
|
||||
double c = rn;
|
||||
double d = (*prev).second;
|
||||
double e = (*next).second;
|
||||
double f = ((e-d)/(b-a))*(c-a) + d;
|
||||
|
||||
xo = f*xn;
|
||||
yo = f*yn;
|
||||
}
|
||||
|
||||
|
||||
void RadialDistortion::SetupLookupTable(double max, int resolution)
|
||||
{
|
||||
lookup_.clear();
|
||||
double incr = max/(double)resolution;
|
||||
double value = 0.0;
|
||||
double old=-1.0;
|
||||
while (value < max)
|
||||
{
|
||||
double f = 1.0;
|
||||
for (int i = 0; i < static_cast<int>(k_.size()); i++)
|
||||
f += (k_[i] * pow(value*value, i+1));
|
||||
if ((f*value)>old)
|
||||
{
|
||||
//cout << "R = " << value << " ,Rd = " << f*value << " ,f = " << f << endl;
|
||||
lookup_[f*value] = 1.0/f;
|
||||
old=f*value;
|
||||
value += incr;
|
||||
}
|
||||
else {
|
||||
//vstDebug(100)<<"vstUndoRadialDistortion::SetupLookupTable:warning RADIAL DISTORTION FOLDING BACK at "<<value<<endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
60
src/plugins_experimental/edit_epoch/radial_distortion.h
Normal file
60
src/plugins_experimental/edit_epoch/radial_distortion.h
Normal file
@ -0,0 +1,60 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
// using namespace std;
|
||||
//#include <vil/vil_warp.h>
|
||||
|
||||
class RadialDistortion // : public vil_warp_mapping
|
||||
{
|
||||
public:
|
||||
RadialDistortion() { }
|
||||
RadialDistortion(const RadialDistortion &obj):
|
||||
k_(obj.k_), ocx_(obj.ocx_), ocy_(obj.ocy_), ncx_(obj.ncx_), ncy_(obj.ncy_), lookup_(obj.lookup_), max_(obj.max_), resolution_(obj.resolution_) {}
|
||||
|
||||
void SetParameters(std::vector<double>& k, double max = 2000, int resolution = 10000);
|
||||
|
||||
std::vector<double> GetParameters() { return k_; };
|
||||
|
||||
void ComputeNewXY(double xo, double yo, double& xn, double& yn) const;
|
||||
void ComputeOldXY(double xn, double yn, double& xo, double& yo) const;
|
||||
|
||||
// for vil_warp, which doesn't work
|
||||
void forward_map(double x1, double y1, double* x2, double* y2) const;
|
||||
void inverse_map(double x2, double y2, double* x1, double* y1) const;
|
||||
|
||||
protected:
|
||||
std::vector<double> k_;
|
||||
double ocx_;
|
||||
double ocy_;
|
||||
double ncx_;
|
||||
double ncy_;
|
||||
|
||||
void SetupLookupTable(double max, int resolution);
|
||||
|
||||
std::map<double, double> lookup_;
|
||||
|
||||
double max_;
|
||||
int resolution_;
|
||||
};
|
||||
195
src/plugins_experimental/edit_epoch/reconstruction.cpp
Normal file
195
src/plugins_experimental/edit_epoch/reconstruction.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
// A camera consists of K, R, t and the radial distortion parameters.
|
||||
// We have an UndoRadialDistortion member (undoraddist_) which is
|
||||
// initialized with the distortion parameters.
|
||||
|
||||
// Furthermore we have an SVD with the P-matrix (R,t, no K). This is used
|
||||
// to compute the point at infinity (direction of a line) from a point in
|
||||
// the image.
|
||||
|
||||
// We use vnl (of VXL: www.vxl.org) for the math but any other library will
|
||||
// do.
|
||||
|
||||
void vstRadialEuclideanCamera::RecomputeSvd()
|
||||
{
|
||||
vnl_matrix_fixed<double, 3, 4> P;
|
||||
P.update(R_.transpose(), 0, 0);
|
||||
P.set_column(3, -R_.transpose() * T_);
|
||||
Psvd_ = vstSvd<double>(P);
|
||||
}
|
||||
|
||||
// from depth and 2D point to a 3D point:
|
||||
|
||||
void vstRadialEuclideanCamera::DepthTo3DPoint(const vstPoint2D &m, double depth, vstPoint3D &M) const
|
||||
{
|
||||
vnl_vector_fixed<double, 3> m_temp = Kinv_ * m.GetVector();
|
||||
|
||||
double x, y;
|
||||
undoraddist_.ComputeOldXY(m_temp(0) / m_temp(2), m_temp(1) / m_temp(2), x, y);
|
||||
m_temp(0) = x;
|
||||
m_temp(1) = y;
|
||||
m_temp(2) = 1;
|
||||
|
||||
vstPoint3D fp(T_);
|
||||
vnl_vector_fixed<double, 4> end(Psvd_.solve(m_temp));
|
||||
vstLine3D l(fp, vstPoint3D(end));
|
||||
vnl_vector_fixed<double, 4> dir(l.GetPointInfinite().GetVector());
|
||||
dir.normalize();
|
||||
|
||||
M.SetVector(fp.GetVector() + depth * dir);
|
||||
if (IsBehindCamera(M))
|
||||
M.SetVector(fp.GetVector() - depth * dir);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Undo Radial Distortion: This class has two maps to map undistorted to
|
||||
// distorted coordinates and vice versa.
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
// using namespace std;
|
||||
//#include <vil/vil_warp.h>
|
||||
|
||||
class vstUndoRadialDistortion // : public vil_warp_mapping
|
||||
{
|
||||
public:
|
||||
vstUndoRadialDistortion() { }
|
||||
vstUndoRadialDistortion(const vstUndoRadialDistortion &obj):
|
||||
k_(obj.k_), ocx_(obj.ocx_), ocy_(obj.ocy_), ncx_(obj.ncx_), ncy_(obj.ncy_), lookup_(obj.lookup_), max_(obj.max_), resolution_(obj.resolution_) {}
|
||||
|
||||
void SetParameters(std::vector<double>& k, double max = 2000, int resolution = 10000);
|
||||
|
||||
std::vector<double> GetParameters() { return k_; };
|
||||
|
||||
void ComputeNewXY(double xo, double yo, double& xn, double& yn) const;
|
||||
void ComputeOldXY(double xn, double yn, double& xo, double& yo) const;
|
||||
|
||||
// for vil_warp, which doesn't work
|
||||
void forward_map(double x1, double y1, double* x2, double* y2) const;
|
||||
void inverse_map(double x2, double y2, double* x1, double* y1) const;
|
||||
|
||||
protected:
|
||||
std::vector<double> k_;
|
||||
double ocx_;
|
||||
double ocy_;
|
||||
double ncx_;
|
||||
double ncy_;
|
||||
|
||||
void SetupLookupTable(double max, int resolution);
|
||||
|
||||
std::map<double, double> lookup_;
|
||||
|
||||
double max_;
|
||||
int resolution_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
void vstUndoRadialDistortion::SetParameters(vector<double>& k, double max, int resolution)
|
||||
{
|
||||
k_ = k;
|
||||
max_ = max;
|
||||
resolution_ = resolution;
|
||||
|
||||
SetupLookupTable(max_, resolution_);
|
||||
}
|
||||
|
||||
void vstUndoRadialDistortion::forward_map(double x1, double y1, double* x2, double* y2) const
|
||||
{
|
||||
ComputeNewXY(x1-ocx_, y1-ocy_, *x2, *y2);
|
||||
*x2 += ncx_;
|
||||
*y2 += ncy_;
|
||||
}
|
||||
|
||||
|
||||
void vstUndoRadialDistortion::inverse_map(double x2, double y2, double* x1, double* y1) const
|
||||
{
|
||||
ComputeOldXY(x2-ncx_, y2-ncy_, *x1, *y1);
|
||||
*x1 += ocx_;
|
||||
*y1 += ocy_;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Relative w.r.t. center !
|
||||
void vstUndoRadialDistortion::ComputeNewXY(double xo, double yo, double& xn, double& yn) const
|
||||
{
|
||||
double r = (xo*xo) + (yo*yo); // r is r squared
|
||||
double f = 1.0;
|
||||
for (int i = 0; i < k_.size(); i++) f += (k_[i] * pow(r, i+1));
|
||||
xn = f*xo;
|
||||
yn = f*yo;
|
||||
}
|
||||
|
||||
|
||||
void vstUndoRadialDistortion::ComputeOldXY(double xn, double yn, double& xo, double& yo) const
|
||||
{
|
||||
double rn = sqrt((xn*xn) + (yn*yn)); //// r is r squared
|
||||
map<double, double>::const_iterator next = lookup_.upper_bound(rn);
|
||||
map<double, double>::const_iterator prev = next; prev--;
|
||||
|
||||
// The compiler will optimise this.
|
||||
double a = (*prev).first;
|
||||
double b = (*next).first;
|
||||
double c = rn;
|
||||
double d = (*prev).second;
|
||||
double e = (*next).second;
|
||||
double f = ((e-d)/(b-a))*(c-a) + d;
|
||||
|
||||
xo = f*xn;
|
||||
yo = f*yn;
|
||||
}
|
||||
|
||||
|
||||
void vstUndoRadialDistortion::SetupLookupTable(double max, int resolution)
|
||||
{
|
||||
lookup_.clear();
|
||||
double incr = max/(double)resolution;
|
||||
double value = 0.0;
|
||||
double old=-1.0;
|
||||
while (value < max)
|
||||
{
|
||||
double f = 1.0;
|
||||
for (int i = 0; i < k_.size(); i++)
|
||||
f += (k_[i] * pow(value*value, i+1));
|
||||
if ((f*value)>old)
|
||||
{
|
||||
//cout << "R = " << value << " ,Rd = " << f*value << " ,f = " << f << endl;
|
||||
lookup_[f*value] = 1.0/f;
|
||||
old=f*value;
|
||||
value += incr;
|
||||
}
|
||||
else {
|
||||
//vstDebug(100)<<"vstUndoRadialDistortion::SetupLookupTable:warning RADIAL DISTORTION FOLDING BACK at "<<value<<endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
src/plugins_experimental/edit_epoch/resource.h
Normal file
16
src/plugins_experimental/edit_epoch/resource.h
Normal file
@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by edit_epoch.rc
|
||||
//
|
||||
#define IDI_ICON1 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
16
src/plugins_experimental/edit_epoch/resource1.h
Normal file
16
src/plugins_experimental/edit_epoch/resource1.h
Normal file
@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by edit_epoch1.rc
|
||||
//
|
||||
#define IDB_PNG1 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
195
src/plugins_experimental/edit_epoch/scalar_image.cpp
Normal file
195
src/plugins_experimental/edit_epoch/scalar_image.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include <Qt>
|
||||
#include <QPixmap>
|
||||
#include <bzlib.h>
|
||||
#include <vector>
|
||||
#include "scalar_image.h"
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
/*
|
||||
|
||||
Images with bit-depths greater than 8bpp and up to 31bpp are supported by the JJ2000 codec if they are stored in PGX files
|
||||
(one file per component). PGX is a custom monochrome file format invented specifically to simplify the use of JPEG 2000
|
||||
with images of different bit-depths in the range of 1 to 31 bits per pixel.
|
||||
|
||||
The file consists of a one line text header followed by the (raw) data.
|
||||
|
||||
Header: "PG"+ ws +<endianess>+ ws +[sign]+ws + <bit-depth>+" "+<width>+" "+<height>+[compressed_size]'\n'
|
||||
|
||||
where:
|
||||
|
||||
* ws (white-spaces) is any combination of characters ' ' and '\t'.
|
||||
* endianess equals "LM" or "ML"(resp. little-endian or big-endian)
|
||||
* sign equals "+" or "-" (resp. unsigned or signed). If omited, values are supposed to be unsigned.
|
||||
* bit-depth that can be any number between 1 and 31. This number must take into account the eventual sign bit.
|
||||
* width and height are the image dimensions (in pixels).
|
||||
|
||||
Data: The image binary values appear one after the other (in raster order) immediately after the last header character ('\n')
|
||||
and are byte-aligned (they are packed into 1,2 or 4 bytes per sample, depending upon the bit-depth value).
|
||||
*/
|
||||
template <>
|
||||
bool ScalarImage<float>::Open(const char *filename)
|
||||
{
|
||||
FILE *fp=fopen(filename,"rb");
|
||||
if(!fp) return false;
|
||||
char buf[256];
|
||||
fgets(buf,255,fp);
|
||||
qDebug("Header of %s is '%s'",filename,buf);
|
||||
float ll,lh;
|
||||
int depth;
|
||||
char mode;
|
||||
int compressed_size=0;
|
||||
sscanf(buf,"PG LM %i %i %i %c %f %f %i",&depth,&w,&h,&mode,&ll,&lh,&compressed_size);
|
||||
qDebug("image should be of %i x %i %i depth and with range in %f -- %f in mode %c",w,h,depth,ll,lh,mode);
|
||||
if(depth!=16)
|
||||
{
|
||||
qDebug("Wrong depth of image 16 bit expected");
|
||||
return false;
|
||||
}
|
||||
if (mode != 'l' && mode != 'L')
|
||||
{
|
||||
qDebug("Wrong mode, expected l or L");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == 'l')
|
||||
{
|
||||
vector<unsigned short> bb(w*h);
|
||||
fread(&*bb.begin(),w*h,sizeof(short),fp);
|
||||
v.resize(w*h);
|
||||
for(int i =0; i<w*h;++i)
|
||||
v[i]=ll+(lh-ll)*(float(bb[i])/65536.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* compressed_buffer = new char[compressed_size];
|
||||
fread(compressed_buffer,compressed_size,1,fp);
|
||||
// decompress!
|
||||
size_t size = w*h*sizeof(short);
|
||||
unsigned char * uncompressed_buffer = new unsigned char[size];
|
||||
unsigned int mysize = size;
|
||||
BZ2_bzBuffToBuffDecompress((char*)uncompressed_buffer, &mysize, compressed_buffer, compressed_size, 0, 0);
|
||||
if (mysize != size)
|
||||
{
|
||||
qDebug("This is very wrong. The uncompressed size is not the expected size");
|
||||
return false;
|
||||
}
|
||||
int imagesize = w*h;
|
||||
unsigned char *correct_buffer = new unsigned char[size];
|
||||
|
||||
for (int i=0; i<imagesize; ++i)
|
||||
{
|
||||
for (size_t j=0; j<sizeof(short); ++j)
|
||||
{
|
||||
correct_buffer[sizeof(short)*i +j] = uncompressed_buffer[imagesize*j + i];
|
||||
}
|
||||
}
|
||||
v.resize(w*h);
|
||||
for (int i=0; i<imagesize; ++i)
|
||||
{
|
||||
float a = *((unsigned short*)&correct_buffer[i*sizeof(short)]);
|
||||
v[i] = ll+(lh-ll)*(a/65536.0f);
|
||||
}
|
||||
|
||||
delete [] uncompressed_buffer;
|
||||
delete [] compressed_buffer;
|
||||
delete [] correct_buffer;
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool ScalarImage<unsigned char>::Open(const char *filename)
|
||||
{
|
||||
FILE *fp=fopen(filename,"rb");
|
||||
if(!fp) return false;
|
||||
char buf[256];
|
||||
fgets(buf,255,fp);
|
||||
qDebug("Header of %s is '%s'",filename,buf);
|
||||
int depth;
|
||||
char mode = ' ';
|
||||
int compressed_size=0;
|
||||
int nrscan = sscanf(buf,"PG LM %i %i %i %c %i",&depth,&w,&h,&mode,&compressed_size);
|
||||
if (nrscan == 3)
|
||||
qDebug("image should be of %i x %i %i depth ",w,h,depth);
|
||||
else
|
||||
qDebug("compressed image of %i x %i %i depth ",w,h,depth);
|
||||
if(depth!=8)
|
||||
{
|
||||
qDebug("Wrong depth of image: 8 bit expected");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode != 'C')
|
||||
{
|
||||
v.resize(w*h);
|
||||
fread(&*v.begin(),w*h,sizeof(unsigned char),fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* compressed_buffer = new char[compressed_size];
|
||||
fread(compressed_buffer,compressed_size,1,fp);
|
||||
// decompress!
|
||||
unsigned int mysize = w*h;
|
||||
v.resize(w*h);
|
||||
BZ2_bzBuffToBuffDecompress((char*)&*v.begin(), &mysize, compressed_buffer, compressed_size, 0, 0);
|
||||
if (mysize != (unsigned int)(w*h))
|
||||
{
|
||||
qDebug("This is very wrong. The uncompressed size is not the expected size");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
ScalarImage<unsigned char>::ScalarImage(QImage img)
|
||||
{
|
||||
resize(img.width(),img.height());
|
||||
|
||||
for(int y=0;y<h;++y)
|
||||
for(int x=0;x<w;++x)
|
||||
Val(x,y)=qGray(img.pixel(x,y));
|
||||
|
||||
}
|
||||
|
||||
template <class ScalarType>
|
||||
bool ScalarImage<ScalarType>::Subsample(const int factor, ScalarImage<ScalarType> &fli)
|
||||
{
|
||||
resize(fli.w/factor,fli.h/factor);
|
||||
|
||||
for(int i=0;i<h;++i)
|
||||
for(int j=0;j<w;++j)
|
||||
Val(i,j)=fli.Val(i*factor,j*factor);
|
||||
return true;
|
||||
};
|
||||
|
||||
150
src/plugins_experimental/edit_epoch/scalar_image.h
Normal file
150
src/plugins_experimental/edit_epoch/scalar_image.h
Normal file
@ -0,0 +1,150 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef VCG_SCALARIMAGE_H
|
||||
#define VCG_SCALARIMAGE_H
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <vcg/space/color4.h>
|
||||
/*
|
||||
Very simple class to store a bitmap of floating point values.
|
||||
*/
|
||||
template <class ScalarType>
|
||||
class ScalarImage
|
||||
{
|
||||
public:
|
||||
std::vector<ScalarType> v;
|
||||
int w,h;
|
||||
void resize(int _w, int _h) { w=_w; h=_h; v.resize(w*h);}
|
||||
bool Open(const char *filename);
|
||||
ScalarType &Val(int x,int y) {
|
||||
assert(x>=0 && x<w);
|
||||
assert(y>=0 && y<h);
|
||||
return v[y*w+x];
|
||||
};
|
||||
|
||||
ScalarType Val(int x,int y) const {
|
||||
assert(x>=0 && x<w);
|
||||
assert(y>=0 && y<h);
|
||||
return v[y*w+x];
|
||||
};
|
||||
|
||||
void operator = ( const ScalarImage & img )
|
||||
{
|
||||
w=img.w;
|
||||
h=img.h;
|
||||
v=img.v;
|
||||
}
|
||||
|
||||
ScalarType MinVal() { return *std::min_element(v.begin(),v.end()); }
|
||||
ScalarType MaxVal() { return *std::max_element(v.begin(),v.end()); }
|
||||
|
||||
inline QImage convertToQImage()
|
||||
{
|
||||
QImage img(w,h,QImage::Format_RGB32);
|
||||
|
||||
float maxV = MaxVal();
|
||||
float minV = MinVal();
|
||||
|
||||
float scale = 1.0f / (maxV-minV);
|
||||
for (int y = 0; y < h; y++)
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
float value = (Val(x, y) - minV) * scale;
|
||||
value *= 255.0f;
|
||||
img.setPixel(x,y,qRgb(value,value,value));
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
void Erode(ScalarImage &Eroded, const int wsize=1) const
|
||||
{
|
||||
Eroded.resize(w,h);
|
||||
// erosion filter (3 x 3)
|
||||
float minimum;
|
||||
for (int y = wsize; y < h-wsize; y++)
|
||||
for (int x = wsize; x < w-wsize; x++)
|
||||
{
|
||||
minimum = Val(x, y);
|
||||
for (int yy = y - wsize; yy <= y + wsize; yy++)
|
||||
for (int xx = x - wsize; xx <= x + wsize; xx++)
|
||||
if (Val(xx, yy) < minimum)
|
||||
minimum = Val(xx, yy);
|
||||
|
||||
Eroded.Val(x, y) = minimum;
|
||||
}
|
||||
}
|
||||
|
||||
void Dilate(ScalarImage &Dilated, int wsize=1)
|
||||
{
|
||||
Dilated.resize(w,h);
|
||||
// dilation filter (3 x 3)
|
||||
float maximum;
|
||||
for (int y = wsize; y < h-wsize; y++)
|
||||
for (int x = wsize; x < w-wsize; x++)
|
||||
{
|
||||
maximum = Val(x, y);
|
||||
for (int yy = y - wsize; yy <= y + wsize; yy++)
|
||||
for (int xx = x - wsize; xx <= x + wsize; xx++)
|
||||
if (Val(xx, yy) > maximum)
|
||||
maximum = Val(xx, yy);
|
||||
|
||||
Dilated.Val(x, y) = maximum;
|
||||
}
|
||||
}
|
||||
|
||||
ScalarImage(QImage img);
|
||||
ScalarImage(){};
|
||||
bool Subsample(const int factor, ScalarImage<ScalarType> &fli);
|
||||
static QPixmap colorizedScaledToHeight(const int desiredH, ScalarImage<ScalarType> &fli, float colormax=10)
|
||||
{
|
||||
assert(fli.h>desiredH);
|
||||
int factor = fli.h / desiredH;
|
||||
|
||||
int newW=fli.w/factor -1;
|
||||
int newH=fli.h/factor -1;
|
||||
QImage newImage(newW,newH,QImage::Format_RGB32);
|
||||
|
||||
for(int i=0;i<newImage.height();++i)
|
||||
for(int j=0;j<newImage.width();++j)
|
||||
{
|
||||
float sum=0;
|
||||
for(int si=0;si<factor;++si)
|
||||
for(int sj=0;sj<factor;++sj)
|
||||
sum+= fli.Val(j*factor+sj,i*factor+si);
|
||||
sum/=factor*factor;
|
||||
sum=std::min(sum,colormax);
|
||||
vcg::Color4b avgcolor; avgcolor.ColorRamp(0,colormax,sum);
|
||||
newImage.setPixel(j,i,qRgb(avgcolor.V(0),avgcolor.V(1),avgcolor.V(2)));
|
||||
}
|
||||
return QPixmap::fromImage(newImage);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
typedef ScalarImage<float> FloatImage;
|
||||
typedef ScalarImage<unsigned char> CharImage;
|
||||
|
||||
|
||||
#endif
|
||||
678
src/plugins_experimental/edit_epoch/ui/v3dImportDialog.ui
Normal file
678
src/plugins_experimental/edit_epoch/ui/v3dImportDialog.ui
Normal file
@ -0,0 +1,678 @@
|
||||
<ui version="4.0" >
|
||||
<class>v3dImportDialog</class>
|
||||
<widget class="QDialog" name="v3dImportDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>792</width>
|
||||
<height>606</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>V3D Import Settings</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="infoLabel" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="previewLabel" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>SubSample</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="imgSizeLabel" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="subsampleSpinBox" >
|
||||
<property name="toolTip" >
|
||||
<string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set the subsample factor:</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 1 the image is not resized</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 2 image is halved <span style=" font-style:italic;">(one point every 4)</span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 3 image is reduced to one third <span style=" font-style:italic;">(one point every 9)</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Minimum Count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>91</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="minCountSpinBox" >
|
||||
<property name="toolTip" >
|
||||
<string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set the minimum number of match for a sample to be accepted</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3 means that only samples that had been found a correspondence with other 2 images or more are considered</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="minCountSlider" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rangeLabel" >
|
||||
<property name="text" >
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Minimum Angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="qualitySpinBox" >
|
||||
<property name="decimals" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<double>90.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep" >
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<double>75.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="text" >
|
||||
<string>Feature Aware Smoothing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="smoothSpinBox" >
|
||||
<property name="decimals" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<double>20.000000000000000</double>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<double>3.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QCheckBox" name="removeSmallCCCheckBox" >
|
||||
<property name="layoutDirection" >
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Remove pieces less than</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="maxCCDiagSpinBox" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip" >
|
||||
<string>When enabled, all the floating pieces smaller than the indicated percentage are deleted. Unit is the diagonal of the bounding box of the object</string>
|
||||
</property>
|
||||
<property name="decimals" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<double>25.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep" >
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="holeCheckBox" >
|
||||
<property name="enabled" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="layoutDirection" >
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Close Holes less than</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="holeSpinBox" >
|
||||
<property name="singleStep" >
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<item row="0" column="5" >
|
||||
<widget class="QSlider" name="dilationSizeSlider" >
|
||||
<property name="minimum" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep" >
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" >
|
||||
<widget class="QSpinBox" name="erosionNumPassSpinBox" >
|
||||
<property name="minimum" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" >
|
||||
<widget class="QLabel" name="lblDilationSize" >
|
||||
<property name="text" >
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6" >
|
||||
<widget class="QLabel" name="lblErosionSizeValue" >
|
||||
<property name="text" >
|
||||
<string>5 x 5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" >
|
||||
<widget class="QSpinBox" name="dilationNumPassSpinBox" >
|
||||
<property name="minimum" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QLabel" name="lblDilationSteps" >
|
||||
<property name="text" >
|
||||
<string>Num. passes:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5" >
|
||||
<widget class="QSlider" name="erosionSizeSlider" >
|
||||
<property name="minimum" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="singleStep" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep" >
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6" >
|
||||
<widget class="QLabel" name="lblDilationSizeValue" >
|
||||
<property name="text" >
|
||||
<string>5 x 5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<widget class="QLabel" name="lblErosionSteps" >
|
||||
<property name="text" >
|
||||
<string>Num. passes:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_8" >
|
||||
<property name="text" >
|
||||
<string>Depth Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4" >
|
||||
<widget class="QLabel" name="lblErosionSize" >
|
||||
<property name="text" >
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QCheckBox" name="dilationCheckBox" >
|
||||
<property name="text" >
|
||||
<string>Dilation</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QCheckBox" name="erosionCheckBox" >
|
||||
<property name="text" >
|
||||
<string>Erosion</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="fastMergeCheckBox" >
|
||||
<property name="toolTip" >
|
||||
<string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Perform a fast, fixed resolution merging of all the range maps. If unchecked all the rangemaps are simply put in the same space without merging them.</p></body></html></string>
|
||||
</property>
|
||||
<property name="layoutDirection" >
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Fast merge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>Resolution: Min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="mergeResolutionSpinBox" >
|
||||
<property name="minimum" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7" >
|
||||
<property name="text" >
|
||||
<string>Max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectButton" >
|
||||
<property name="text" >
|
||||
<string>Select</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="subsampleSequenceSpinBox" >
|
||||
<property name="value" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10" >
|
||||
<property name="text" >
|
||||
<string>Scaling Factor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="scaleLineEdit" >
|
||||
<property name="inputMask" >
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>1.0</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>131</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="okButton" >
|
||||
<property name="text" >
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="plyButton" >
|
||||
<property name="toolTip" >
|
||||
<string>Process all selected range maps and save them as separated ply</string>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Export as PLY</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancelButton" >
|
||||
<property name="text" >
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="imageTableWidget" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="MinimumExpanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="columnCount" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>okButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>v3dImportDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>554</x>
|
||||
<y>682</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>342</x>
|
||||
<y>405</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>cancelButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>v3dImportDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>637</x>
|
||||
<y>682</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>425</x>
|
||||
<y>433</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>removeSmallCCCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>maxCCDiagSpinBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>348</x>
|
||||
<y>584</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>637</x>
|
||||
<y>584</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
555
src/plugins_experimental/edit_epoch/ui_v3dImportDialog.h
Normal file
555
src/plugins_experimental/edit_epoch/ui_v3dImportDialog.h
Normal file
@ -0,0 +1,555 @@
|
||||
/********************************************************************************
|
||||
** Form generated from reading UI file 'v3dImportDialog.ui'
|
||||
**
|
||||
** Created: Tue 31. Jan 16:30:15 2012
|
||||
** by: Qt User Interface Compiler version 4.7.2
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef UI_V3DIMPORTDIALOG_H
|
||||
#define UI_V3DIMPORTDIALOG_H
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QButtonGroup>
|
||||
#include <QtGui/QCheckBox>
|
||||
#include <QtGui/QDialog>
|
||||
#include <QtGui/QDoubleSpinBox>
|
||||
#include <QtGui/QGridLayout>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QSlider>
|
||||
#include <QtGui/QSpacerItem>
|
||||
#include <QtGui/QSpinBox>
|
||||
#include <QtGui/QTableWidget>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Ui_v3dImportDialog
|
||||
{
|
||||
public:
|
||||
QHBoxLayout *hboxLayout;
|
||||
QVBoxLayout *vboxLayout;
|
||||
QLabel *infoLabel;
|
||||
QLabel *previewLabel;
|
||||
QHBoxLayout *hboxLayout1;
|
||||
QLabel *label;
|
||||
QSpacerItem *spacerItem;
|
||||
QLabel *imgSizeLabel;
|
||||
QSpinBox *subsampleSpinBox;
|
||||
QHBoxLayout *hboxLayout2;
|
||||
QLabel *label_2;
|
||||
QSpacerItem *spacerItem1;
|
||||
QSpinBox *minCountSpinBox;
|
||||
QVBoxLayout *vboxLayout1;
|
||||
QSlider *minCountSlider;
|
||||
QLabel *rangeLabel;
|
||||
QHBoxLayout *hboxLayout3;
|
||||
QLabel *label_3;
|
||||
QSpacerItem *spacerItem2;
|
||||
QDoubleSpinBox *qualitySpinBox;
|
||||
QHBoxLayout *hboxLayout4;
|
||||
QLabel *label_5;
|
||||
QSpacerItem *spacerItem3;
|
||||
QDoubleSpinBox *smoothSpinBox;
|
||||
QHBoxLayout *hboxLayout5;
|
||||
QCheckBox *removeSmallCCCheckBox;
|
||||
QDoubleSpinBox *maxCCDiagSpinBox;
|
||||
QSpacerItem *spacerItem4;
|
||||
QCheckBox *holeCheckBox;
|
||||
QSpinBox *holeSpinBox;
|
||||
QGridLayout *gridLayout;
|
||||
QSlider *dilationSizeSlider;
|
||||
QSpinBox *erosionNumPassSpinBox;
|
||||
QLabel *lblDilationSize;
|
||||
QLabel *lblErosionSizeValue;
|
||||
QSpinBox *dilationNumPassSpinBox;
|
||||
QLabel *lblDilationSteps;
|
||||
QSlider *erosionSizeSlider;
|
||||
QLabel *lblDilationSizeValue;
|
||||
QLabel *lblErosionSteps;
|
||||
QLabel *label_8;
|
||||
QLabel *lblErosionSize;
|
||||
QCheckBox *dilationCheckBox;
|
||||
QCheckBox *erosionCheckBox;
|
||||
QHBoxLayout *hboxLayout6;
|
||||
QSpacerItem *spacerItem5;
|
||||
QCheckBox *fastMergeCheckBox;
|
||||
QLabel *label_6;
|
||||
QSlider *mergeResolutionSpinBox;
|
||||
QLabel *label_7;
|
||||
QHBoxLayout *hboxLayout7;
|
||||
QPushButton *selectButton;
|
||||
QSpacerItem *spacerItem6;
|
||||
QSpinBox *subsampleSequenceSpinBox;
|
||||
QHBoxLayout *hboxLayout8;
|
||||
QLabel *label_10;
|
||||
QSpacerItem *spacerItem7;
|
||||
QLineEdit *scaleLineEdit;
|
||||
QHBoxLayout *hboxLayout9;
|
||||
QSpacerItem *spacerItem8;
|
||||
QPushButton *okButton;
|
||||
QPushButton *plyButton;
|
||||
QPushButton *cancelButton;
|
||||
QTableWidget *imageTableWidget;
|
||||
|
||||
void setupUi(QDialog *v3dImportDialog)
|
||||
{
|
||||
if (v3dImportDialog->objectName().isEmpty())
|
||||
v3dImportDialog->setObjectName(QString::fromUtf8("v3dImportDialog"));
|
||||
v3dImportDialog->resize(792, 606);
|
||||
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
sizePolicy.setHorizontalStretch(0);
|
||||
sizePolicy.setVerticalStretch(0);
|
||||
sizePolicy.setHeightForWidth(v3dImportDialog->sizePolicy().hasHeightForWidth());
|
||||
v3dImportDialog->setSizePolicy(sizePolicy);
|
||||
hboxLayout = new QHBoxLayout(v3dImportDialog);
|
||||
hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
|
||||
vboxLayout = new QVBoxLayout();
|
||||
vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
|
||||
infoLabel = new QLabel(v3dImportDialog);
|
||||
infoLabel->setObjectName(QString::fromUtf8("infoLabel"));
|
||||
|
||||
vboxLayout->addWidget(infoLabel);
|
||||
|
||||
previewLabel = new QLabel(v3dImportDialog);
|
||||
previewLabel->setObjectName(QString::fromUtf8("previewLabel"));
|
||||
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
sizePolicy1.setHorizontalStretch(0);
|
||||
sizePolicy1.setVerticalStretch(0);
|
||||
sizePolicy1.setHeightForWidth(previewLabel->sizePolicy().hasHeightForWidth());
|
||||
previewLabel->setSizePolicy(sizePolicy1);
|
||||
|
||||
vboxLayout->addWidget(previewLabel);
|
||||
|
||||
hboxLayout1 = new QHBoxLayout();
|
||||
hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
|
||||
label = new QLabel(v3dImportDialog);
|
||||
label->setObjectName(QString::fromUtf8("label"));
|
||||
|
||||
hboxLayout1->addWidget(label);
|
||||
|
||||
spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout1->addItem(spacerItem);
|
||||
|
||||
imgSizeLabel = new QLabel(v3dImportDialog);
|
||||
imgSizeLabel->setObjectName(QString::fromUtf8("imgSizeLabel"));
|
||||
|
||||
hboxLayout1->addWidget(imgSizeLabel);
|
||||
|
||||
subsampleSpinBox = new QSpinBox(v3dImportDialog);
|
||||
subsampleSpinBox->setObjectName(QString::fromUtf8("subsampleSpinBox"));
|
||||
|
||||
hboxLayout1->addWidget(subsampleSpinBox);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout1);
|
||||
|
||||
hboxLayout2 = new QHBoxLayout();
|
||||
hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
|
||||
label_2 = new QLabel(v3dImportDialog);
|
||||
label_2->setObjectName(QString::fromUtf8("label_2"));
|
||||
|
||||
hboxLayout2->addWidget(label_2);
|
||||
|
||||
spacerItem1 = new QSpacerItem(91, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout2->addItem(spacerItem1);
|
||||
|
||||
minCountSpinBox = new QSpinBox(v3dImportDialog);
|
||||
minCountSpinBox->setObjectName(QString::fromUtf8("minCountSpinBox"));
|
||||
|
||||
hboxLayout2->addWidget(minCountSpinBox);
|
||||
|
||||
vboxLayout1 = new QVBoxLayout();
|
||||
vboxLayout1->setSpacing(0);
|
||||
vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
|
||||
minCountSlider = new QSlider(v3dImportDialog);
|
||||
minCountSlider->setObjectName(QString::fromUtf8("minCountSlider"));
|
||||
QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
sizePolicy2.setHorizontalStretch(0);
|
||||
sizePolicy2.setVerticalStretch(0);
|
||||
sizePolicy2.setHeightForWidth(minCountSlider->sizePolicy().hasHeightForWidth());
|
||||
minCountSlider->setSizePolicy(sizePolicy2);
|
||||
minCountSlider->setMaximum(10);
|
||||
minCountSlider->setOrientation(Qt::Horizontal);
|
||||
|
||||
vboxLayout1->addWidget(minCountSlider);
|
||||
|
||||
rangeLabel = new QLabel(v3dImportDialog);
|
||||
rangeLabel->setObjectName(QString::fromUtf8("rangeLabel"));
|
||||
|
||||
vboxLayout1->addWidget(rangeLabel);
|
||||
|
||||
|
||||
hboxLayout2->addLayout(vboxLayout1);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout2);
|
||||
|
||||
hboxLayout3 = new QHBoxLayout();
|
||||
hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
|
||||
label_3 = new QLabel(v3dImportDialog);
|
||||
label_3->setObjectName(QString::fromUtf8("label_3"));
|
||||
|
||||
hboxLayout3->addWidget(label_3);
|
||||
|
||||
spacerItem2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout3->addItem(spacerItem2);
|
||||
|
||||
qualitySpinBox = new QDoubleSpinBox(v3dImportDialog);
|
||||
qualitySpinBox->setObjectName(QString::fromUtf8("qualitySpinBox"));
|
||||
qualitySpinBox->setDecimals(1);
|
||||
qualitySpinBox->setMaximum(90);
|
||||
qualitySpinBox->setSingleStep(5);
|
||||
qualitySpinBox->setValue(75);
|
||||
|
||||
hboxLayout3->addWidget(qualitySpinBox);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout3);
|
||||
|
||||
hboxLayout4 = new QHBoxLayout();
|
||||
hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
|
||||
label_5 = new QLabel(v3dImportDialog);
|
||||
label_5->setObjectName(QString::fromUtf8("label_5"));
|
||||
|
||||
hboxLayout4->addWidget(label_5);
|
||||
|
||||
spacerItem3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout4->addItem(spacerItem3);
|
||||
|
||||
smoothSpinBox = new QDoubleSpinBox(v3dImportDialog);
|
||||
smoothSpinBox->setObjectName(QString::fromUtf8("smoothSpinBox"));
|
||||
smoothSpinBox->setDecimals(0);
|
||||
smoothSpinBox->setMaximum(20);
|
||||
smoothSpinBox->setValue(3);
|
||||
|
||||
hboxLayout4->addWidget(smoothSpinBox);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout4);
|
||||
|
||||
hboxLayout5 = new QHBoxLayout();
|
||||
hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5"));
|
||||
removeSmallCCCheckBox = new QCheckBox(v3dImportDialog);
|
||||
removeSmallCCCheckBox->setObjectName(QString::fromUtf8("removeSmallCCCheckBox"));
|
||||
removeSmallCCCheckBox->setLayoutDirection(Qt::RightToLeft);
|
||||
removeSmallCCCheckBox->setChecked(true);
|
||||
|
||||
hboxLayout5->addWidget(removeSmallCCCheckBox);
|
||||
|
||||
maxCCDiagSpinBox = new QDoubleSpinBox(v3dImportDialog);
|
||||
maxCCDiagSpinBox->setObjectName(QString::fromUtf8("maxCCDiagSpinBox"));
|
||||
QSizePolicy sizePolicy3(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
sizePolicy3.setHorizontalStretch(0);
|
||||
sizePolicy3.setVerticalStretch(0);
|
||||
sizePolicy3.setHeightForWidth(maxCCDiagSpinBox->sizePolicy().hasHeightForWidth());
|
||||
maxCCDiagSpinBox->setSizePolicy(sizePolicy3);
|
||||
maxCCDiagSpinBox->setDecimals(0);
|
||||
maxCCDiagSpinBox->setMaximum(25);
|
||||
maxCCDiagSpinBox->setSingleStep(5);
|
||||
maxCCDiagSpinBox->setValue(5);
|
||||
|
||||
hboxLayout5->addWidget(maxCCDiagSpinBox);
|
||||
|
||||
spacerItem4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout5->addItem(spacerItem4);
|
||||
|
||||
holeCheckBox = new QCheckBox(v3dImportDialog);
|
||||
holeCheckBox->setObjectName(QString::fromUtf8("holeCheckBox"));
|
||||
holeCheckBox->setEnabled(true);
|
||||
holeCheckBox->setLayoutDirection(Qt::RightToLeft);
|
||||
|
||||
hboxLayout5->addWidget(holeCheckBox);
|
||||
|
||||
holeSpinBox = new QSpinBox(v3dImportDialog);
|
||||
holeSpinBox->setObjectName(QString::fromUtf8("holeSpinBox"));
|
||||
holeSpinBox->setSingleStep(5);
|
||||
holeSpinBox->setValue(10);
|
||||
|
||||
hboxLayout5->addWidget(holeSpinBox);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout5);
|
||||
|
||||
gridLayout = new QGridLayout();
|
||||
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
|
||||
dilationSizeSlider = new QSlider(v3dImportDialog);
|
||||
dilationSizeSlider->setObjectName(QString::fromUtf8("dilationSizeSlider"));
|
||||
dilationSizeSlider->setMinimum(1);
|
||||
dilationSizeSlider->setMaximum(6);
|
||||
dilationSizeSlider->setSingleStep(1);
|
||||
dilationSizeSlider->setPageStep(5);
|
||||
dilationSizeSlider->setValue(2);
|
||||
dilationSizeSlider->setOrientation(Qt::Horizontal);
|
||||
|
||||
gridLayout->addWidget(dilationSizeSlider, 0, 5, 1, 1);
|
||||
|
||||
erosionNumPassSpinBox = new QSpinBox(v3dImportDialog);
|
||||
erosionNumPassSpinBox->setObjectName(QString::fromUtf8("erosionNumPassSpinBox"));
|
||||
erosionNumPassSpinBox->setMinimum(1);
|
||||
erosionNumPassSpinBox->setMaximum(10);
|
||||
erosionNumPassSpinBox->setValue(3);
|
||||
|
||||
gridLayout->addWidget(erosionNumPassSpinBox, 1, 3, 1, 1);
|
||||
|
||||
lblDilationSize = new QLabel(v3dImportDialog);
|
||||
lblDilationSize->setObjectName(QString::fromUtf8("lblDilationSize"));
|
||||
|
||||
gridLayout->addWidget(lblDilationSize, 0, 4, 1, 1);
|
||||
|
||||
lblErosionSizeValue = new QLabel(v3dImportDialog);
|
||||
lblErosionSizeValue->setObjectName(QString::fromUtf8("lblErosionSizeValue"));
|
||||
|
||||
gridLayout->addWidget(lblErosionSizeValue, 1, 6, 1, 1);
|
||||
|
||||
dilationNumPassSpinBox = new QSpinBox(v3dImportDialog);
|
||||
dilationNumPassSpinBox->setObjectName(QString::fromUtf8("dilationNumPassSpinBox"));
|
||||
dilationNumPassSpinBox->setMinimum(1);
|
||||
dilationNumPassSpinBox->setMaximum(5);
|
||||
|
||||
gridLayout->addWidget(dilationNumPassSpinBox, 0, 3, 1, 1);
|
||||
|
||||
lblDilationSteps = new QLabel(v3dImportDialog);
|
||||
lblDilationSteps->setObjectName(QString::fromUtf8("lblDilationSteps"));
|
||||
|
||||
gridLayout->addWidget(lblDilationSteps, 0, 2, 1, 1);
|
||||
|
||||
erosionSizeSlider = new QSlider(v3dImportDialog);
|
||||
erosionSizeSlider->setObjectName(QString::fromUtf8("erosionSizeSlider"));
|
||||
erosionSizeSlider->setMinimum(1);
|
||||
erosionSizeSlider->setMaximum(6);
|
||||
erosionSizeSlider->setSingleStep(1);
|
||||
erosionSizeSlider->setPageStep(5);
|
||||
erosionSizeSlider->setValue(2);
|
||||
erosionSizeSlider->setOrientation(Qt::Horizontal);
|
||||
|
||||
gridLayout->addWidget(erosionSizeSlider, 1, 5, 1, 1);
|
||||
|
||||
lblDilationSizeValue = new QLabel(v3dImportDialog);
|
||||
lblDilationSizeValue->setObjectName(QString::fromUtf8("lblDilationSizeValue"));
|
||||
|
||||
gridLayout->addWidget(lblDilationSizeValue, 0, 6, 1, 1);
|
||||
|
||||
lblErosionSteps = new QLabel(v3dImportDialog);
|
||||
lblErosionSteps->setObjectName(QString::fromUtf8("lblErosionSteps"));
|
||||
|
||||
gridLayout->addWidget(lblErosionSteps, 1, 2, 1, 1);
|
||||
|
||||
label_8 = new QLabel(v3dImportDialog);
|
||||
label_8->setObjectName(QString::fromUtf8("label_8"));
|
||||
|
||||
gridLayout->addWidget(label_8, 0, 0, 1, 1);
|
||||
|
||||
lblErosionSize = new QLabel(v3dImportDialog);
|
||||
lblErosionSize->setObjectName(QString::fromUtf8("lblErosionSize"));
|
||||
|
||||
gridLayout->addWidget(lblErosionSize, 1, 4, 1, 1);
|
||||
|
||||
dilationCheckBox = new QCheckBox(v3dImportDialog);
|
||||
dilationCheckBox->setObjectName(QString::fromUtf8("dilationCheckBox"));
|
||||
dilationCheckBox->setChecked(true);
|
||||
|
||||
gridLayout->addWidget(dilationCheckBox, 0, 1, 1, 1);
|
||||
|
||||
erosionCheckBox = new QCheckBox(v3dImportDialog);
|
||||
erosionCheckBox->setObjectName(QString::fromUtf8("erosionCheckBox"));
|
||||
erosionCheckBox->setChecked(true);
|
||||
|
||||
gridLayout->addWidget(erosionCheckBox, 1, 1, 1, 1);
|
||||
|
||||
|
||||
vboxLayout->addLayout(gridLayout);
|
||||
|
||||
hboxLayout6 = new QHBoxLayout();
|
||||
hboxLayout6->setObjectName(QString::fromUtf8("hboxLayout6"));
|
||||
spacerItem5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout6->addItem(spacerItem5);
|
||||
|
||||
fastMergeCheckBox = new QCheckBox(v3dImportDialog);
|
||||
fastMergeCheckBox->setObjectName(QString::fromUtf8("fastMergeCheckBox"));
|
||||
fastMergeCheckBox->setLayoutDirection(Qt::RightToLeft);
|
||||
|
||||
hboxLayout6->addWidget(fastMergeCheckBox);
|
||||
|
||||
label_6 = new QLabel(v3dImportDialog);
|
||||
label_6->setObjectName(QString::fromUtf8("label_6"));
|
||||
|
||||
hboxLayout6->addWidget(label_6);
|
||||
|
||||
mergeResolutionSpinBox = new QSlider(v3dImportDialog);
|
||||
mergeResolutionSpinBox->setObjectName(QString::fromUtf8("mergeResolutionSpinBox"));
|
||||
mergeResolutionSpinBox->setMinimum(1);
|
||||
mergeResolutionSpinBox->setMaximum(5);
|
||||
mergeResolutionSpinBox->setValue(3);
|
||||
mergeResolutionSpinBox->setOrientation(Qt::Horizontal);
|
||||
|
||||
hboxLayout6->addWidget(mergeResolutionSpinBox);
|
||||
|
||||
label_7 = new QLabel(v3dImportDialog);
|
||||
label_7->setObjectName(QString::fromUtf8("label_7"));
|
||||
|
||||
hboxLayout6->addWidget(label_7);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout6);
|
||||
|
||||
hboxLayout7 = new QHBoxLayout();
|
||||
hboxLayout7->setObjectName(QString::fromUtf8("hboxLayout7"));
|
||||
selectButton = new QPushButton(v3dImportDialog);
|
||||
selectButton->setObjectName(QString::fromUtf8("selectButton"));
|
||||
|
||||
hboxLayout7->addWidget(selectButton);
|
||||
|
||||
spacerItem6 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout7->addItem(spacerItem6);
|
||||
|
||||
subsampleSequenceSpinBox = new QSpinBox(v3dImportDialog);
|
||||
subsampleSequenceSpinBox->setObjectName(QString::fromUtf8("subsampleSequenceSpinBox"));
|
||||
subsampleSequenceSpinBox->setValue(3);
|
||||
|
||||
hboxLayout7->addWidget(subsampleSequenceSpinBox);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout7);
|
||||
|
||||
hboxLayout8 = new QHBoxLayout();
|
||||
hboxLayout8->setObjectName(QString::fromUtf8("hboxLayout8"));
|
||||
label_10 = new QLabel(v3dImportDialog);
|
||||
label_10->setObjectName(QString::fromUtf8("label_10"));
|
||||
|
||||
hboxLayout8->addWidget(label_10);
|
||||
|
||||
spacerItem7 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout8->addItem(spacerItem7);
|
||||
|
||||
scaleLineEdit = new QLineEdit(v3dImportDialog);
|
||||
scaleLineEdit->setObjectName(QString::fromUtf8("scaleLineEdit"));
|
||||
scaleLineEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
|
||||
hboxLayout8->addWidget(scaleLineEdit);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout8);
|
||||
|
||||
hboxLayout9 = new QHBoxLayout();
|
||||
hboxLayout9->setObjectName(QString::fromUtf8("hboxLayout9"));
|
||||
spacerItem8 = new QSpacerItem(131, 31, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
|
||||
hboxLayout9->addItem(spacerItem8);
|
||||
|
||||
okButton = new QPushButton(v3dImportDialog);
|
||||
okButton->setObjectName(QString::fromUtf8("okButton"));
|
||||
|
||||
hboxLayout9->addWidget(okButton);
|
||||
|
||||
plyButton = new QPushButton(v3dImportDialog);
|
||||
plyButton->setObjectName(QString::fromUtf8("plyButton"));
|
||||
|
||||
hboxLayout9->addWidget(plyButton);
|
||||
|
||||
cancelButton = new QPushButton(v3dImportDialog);
|
||||
cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
|
||||
|
||||
hboxLayout9->addWidget(cancelButton);
|
||||
|
||||
|
||||
vboxLayout->addLayout(hboxLayout9);
|
||||
|
||||
|
||||
hboxLayout->addLayout(vboxLayout);
|
||||
|
||||
imageTableWidget = new QTableWidget(v3dImportDialog);
|
||||
if (imageTableWidget->columnCount() < 3)
|
||||
imageTableWidget->setColumnCount(3);
|
||||
imageTableWidget->setObjectName(QString::fromUtf8("imageTableWidget"));
|
||||
QSizePolicy sizePolicy4(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
|
||||
sizePolicy4.setHorizontalStretch(0);
|
||||
sizePolicy4.setVerticalStretch(0);
|
||||
sizePolicy4.setHeightForWidth(imageTableWidget->sizePolicy().hasHeightForWidth());
|
||||
imageTableWidget->setSizePolicy(sizePolicy4);
|
||||
imageTableWidget->setColumnCount(3);
|
||||
|
||||
hboxLayout->addWidget(imageTableWidget);
|
||||
|
||||
|
||||
retranslateUi(v3dImportDialog);
|
||||
QObject::connect(okButton, SIGNAL(clicked()), v3dImportDialog, SLOT(accept()));
|
||||
QObject::connect(cancelButton, SIGNAL(clicked()), v3dImportDialog, SLOT(reject()));
|
||||
QObject::connect(removeSmallCCCheckBox, SIGNAL(toggled(bool)), maxCCDiagSpinBox, SLOT(setEnabled(bool)));
|
||||
|
||||
QMetaObject::connectSlotsByName(v3dImportDialog);
|
||||
} // setupUi
|
||||
|
||||
void retranslateUi(QDialog *v3dImportDialog)
|
||||
{
|
||||
v3dImportDialog->setWindowTitle(QApplication::translate("v3dImportDialog", "V3D Import Settings", 0, QApplication::UnicodeUTF8));
|
||||
infoLabel->setText(QApplication::translate("v3dImportDialog", "TextLabel", 0, QApplication::UnicodeUTF8));
|
||||
previewLabel->setText(QApplication::translate("v3dImportDialog", "TextLabel", 0, QApplication::UnicodeUTF8));
|
||||
label->setText(QApplication::translate("v3dImportDialog", "SubSample", 0, QApplication::UnicodeUTF8));
|
||||
imgSizeLabel->setText(QApplication::translate("v3dImportDialog", "TextLabel", 0, QApplication::UnicodeUTF8));
|
||||
#ifndef QT_NO_TOOLTIP
|
||||
subsampleSpinBox->setToolTip(QApplication::translate("v3dImportDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\" white-space: pre-wrap; font-style:normal; text-decoration:none;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Set the subsample factor:</p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 1 the image is not resized</p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 2 image is halved <span style=\" font-style:italic;\">(one point every 4)</span></p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> 3 image is reduced to one third <span style=\" font-style:italic;\">(one point every 9)</span></p></body></html>", 0, QApplication::UnicodeUTF8));
|
||||
#endif // QT_NO_TOOLTIP
|
||||
label_2->setText(QApplication::translate("v3dImportDialog", "Minimum Count", 0, QApplication::UnicodeUTF8));
|
||||
#ifndef QT_NO_TOOLTIP
|
||||
minCountSpinBox->setToolTip(QApplication::translate("v3dImportDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\" white-space: pre-wrap; font-style:normal; text-decoration:none;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Set the minimum number of match for a sample to be accepted</p><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">3 means that only samples that had been found a correspondence with other 2 images or more are considered</p></body></html>", 0, QApplication::UnicodeUTF8));
|
||||
#endif // QT_NO_TOOLTIP
|
||||
rangeLabel->setText(QApplication::translate("v3dImportDialog", "TextLabel", 0, QApplication::UnicodeUTF8));
|
||||
label_3->setText(QApplication::translate("v3dImportDialog", "Minimum Angle", 0, QApplication::UnicodeUTF8));
|
||||
label_5->setText(QApplication::translate("v3dImportDialog", "Feature Aware Smoothing", 0, QApplication::UnicodeUTF8));
|
||||
removeSmallCCCheckBox->setText(QApplication::translate("v3dImportDialog", "Remove pieces less than", 0, QApplication::UnicodeUTF8));
|
||||
#ifndef QT_NO_TOOLTIP
|
||||
maxCCDiagSpinBox->setToolTip(QApplication::translate("v3dImportDialog", "When enabled, all the floating pieces smaller than the indicated percentage are deleted. Unit is the diagonal of the bounding box of the object", 0, QApplication::UnicodeUTF8));
|
||||
#endif // QT_NO_TOOLTIP
|
||||
holeCheckBox->setText(QApplication::translate("v3dImportDialog", "Close Holes less than", 0, QApplication::UnicodeUTF8));
|
||||
lblDilationSize->setText(QApplication::translate("v3dImportDialog", "Size:", 0, QApplication::UnicodeUTF8));
|
||||
lblErosionSizeValue->setText(QApplication::translate("v3dImportDialog", "5 x 5", 0, QApplication::UnicodeUTF8));
|
||||
lblDilationSteps->setText(QApplication::translate("v3dImportDialog", "Num. passes:", 0, QApplication::UnicodeUTF8));
|
||||
lblDilationSizeValue->setText(QApplication::translate("v3dImportDialog", "5 x 5", 0, QApplication::UnicodeUTF8));
|
||||
lblErosionSteps->setText(QApplication::translate("v3dImportDialog", "Num. passes:", 0, QApplication::UnicodeUTF8));
|
||||
label_8->setText(QApplication::translate("v3dImportDialog", "Depth Filter", 0, QApplication::UnicodeUTF8));
|
||||
lblErosionSize->setText(QApplication::translate("v3dImportDialog", "Size:", 0, QApplication::UnicodeUTF8));
|
||||
dilationCheckBox->setText(QApplication::translate("v3dImportDialog", "Dilation", 0, QApplication::UnicodeUTF8));
|
||||
erosionCheckBox->setText(QApplication::translate("v3dImportDialog", "Erosion", 0, QApplication::UnicodeUTF8));
|
||||
#ifndef QT_NO_TOOLTIP
|
||||
fastMergeCheckBox->setToolTip(QApplication::translate("v3dImportDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\" white-space: pre-wrap; font-style:normal; text-decoration:none;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Perform a fast, fixed resolution merging of all the range maps. If unchecked all the rangemaps are simply put in the same space without merging them.</p></body></html>", 0, QApplication::UnicodeUTF8));
|
||||
#endif // QT_NO_TOOLTIP
|
||||
fastMergeCheckBox->setText(QApplication::translate("v3dImportDialog", "Fast merge", 0, QApplication::UnicodeUTF8));
|
||||
label_6->setText(QApplication::translate("v3dImportDialog", "Resolution: Min", 0, QApplication::UnicodeUTF8));
|
||||
label_7->setText(QApplication::translate("v3dImportDialog", "Max", 0, QApplication::UnicodeUTF8));
|
||||
selectButton->setText(QApplication::translate("v3dImportDialog", "Select", 0, QApplication::UnicodeUTF8));
|
||||
label_10->setText(QApplication::translate("v3dImportDialog", "Scaling Factor", 0, QApplication::UnicodeUTF8));
|
||||
scaleLineEdit->setInputMask(QString());
|
||||
scaleLineEdit->setText(QApplication::translate("v3dImportDialog", "1.0", 0, QApplication::UnicodeUTF8));
|
||||
okButton->setText(QApplication::translate("v3dImportDialog", "OK", 0, QApplication::UnicodeUTF8));
|
||||
#ifndef QT_NO_TOOLTIP
|
||||
plyButton->setToolTip(QApplication::translate("v3dImportDialog", "Process all selected range maps and save them as separated ply", 0, QApplication::UnicodeUTF8));
|
||||
#endif // QT_NO_TOOLTIP
|
||||
plyButton->setText(QApplication::translate("v3dImportDialog", "Export as PLY", 0, QApplication::UnicodeUTF8));
|
||||
cancelButton->setText(QApplication::translate("v3dImportDialog", "Cancel", 0, QApplication::UnicodeUTF8));
|
||||
} // retranslateUi
|
||||
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class v3dImportDialog: public Ui_v3dImportDialog {};
|
||||
} // namespace Ui
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // UI_V3DIMPORTDIALOG_H
|
||||
246
src/plugins_experimental/edit_epoch/v3dImportDialog.cpp
Normal file
246
src/plugins_experimental/edit_epoch/v3dImportDialog.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#include <Qt>
|
||||
#include <QtGui>
|
||||
#include <QDialog>
|
||||
|
||||
#include "v3dImportDialog.h"
|
||||
#include "maskImageWidget.h"
|
||||
using namespace vcg;
|
||||
|
||||
// small helper function for generating a color ramp pixmap to be used in the import dialog.
|
||||
|
||||
QPixmap generateColorRamp()
|
||||
{
|
||||
const int width=100;
|
||||
const int height=15;
|
||||
Color4b ramp;
|
||||
QImage newImage(width,height,QImage::Format_RGB32);
|
||||
|
||||
for(int x=0;x<width;++x)
|
||||
for(int y=0;y<height;++y)
|
||||
{
|
||||
ramp.ColorRamp(0,width,x);
|
||||
newImage.setPixel(x,y,qRgb(ramp.V(0),ramp.V(1),ramp.V(2)));
|
||||
}
|
||||
|
||||
return QPixmap::fromImage(newImage);
|
||||
}
|
||||
/*
|
||||
Main function that populate the dialog, loading all the images and eventually creating the thumbs.
|
||||
called directly by the open before invoking this dialog.
|
||||
*/
|
||||
void v3dImportDialog::setEpochReconstruction(EpochReconstruction *_er)
|
||||
{
|
||||
// if the epoch reconstruction has not changed do nothing
|
||||
if(erCreated == _er->created)
|
||||
{
|
||||
er=_er;
|
||||
return;
|
||||
}
|
||||
|
||||
er=_er;
|
||||
erCreated=er->created;
|
||||
infoLabel->setText(er->name + " - " + er->author + " - " + er->created);
|
||||
|
||||
imageTableWidget->clear();
|
||||
imageTableWidget->setRowCount(er->modelList.size());
|
||||
imageTableWidget->setColumnCount(4);
|
||||
//imageTableWidget->setColumnWidth (1,64);
|
||||
imageTableWidget->setSelectionBehavior (QAbstractItemView::SelectRows);
|
||||
imageTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
imageTableWidget->setMinimumWidth(64*8);
|
||||
|
||||
rangeLabel->setPixmap(generateColorRamp());
|
||||
rangeLabel->setMaximumHeight(10);
|
||||
rangeLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
rangeLabel->setScaledContents(true);
|
||||
|
||||
minCountSlider->setMaximumHeight(12);
|
||||
|
||||
int i;
|
||||
for(i=0; i<er->modelList.size() ;++i)
|
||||
{
|
||||
//cb(i*100/er->modelList.size(),"Reading images");
|
||||
|
||||
QString ThumbImgName=EpochModel::ThumbName(er->modelList[i].textureName);
|
||||
QString ThumbCntName=EpochModel::ThumbName(er->modelList[i].countName);
|
||||
|
||||
imageTableWidget->setRowHeight (i,64);
|
||||
QTableWidgetItem *emptyHeaderItem = new QTableWidgetItem(i*2);
|
||||
QTableWidgetItem *texNameHeaderItem = new QTableWidgetItem(er->modelList[i].textureName,i);
|
||||
imageTableWidget->setItem(i, 0, texNameHeaderItem);
|
||||
imageTableWidget->setItem(i, 1, emptyHeaderItem);
|
||||
QLabel *imageLabel = new QLabel(imageTableWidget);
|
||||
if(!QFile::exists(ThumbImgName))
|
||||
{
|
||||
QPixmap(er->modelList[i].textureName).scaledToHeight(64).save(ThumbImgName,"jpg");
|
||||
if(!QFile::exists(ThumbImgName))
|
||||
QMessageBox::warning(this,"Error in Thumb creation",
|
||||
QString("Unable to create '%1' from '%2'").arg(ThumbImgName),er->modelList[i].textureName);
|
||||
}
|
||||
|
||||
imageLabel->setPixmap(QPixmap(EpochModel::ThumbName(er->modelList[i].textureName)));
|
||||
imageTableWidget->setCellWidget(i,1,imageLabel);
|
||||
if(QFile::exists(er->modelList[i].maskName))
|
||||
{
|
||||
QTableWidgetItem *emptyHeaderItem = new QTableWidgetItem(i*4);
|
||||
imageTableWidget->setItem(i, 2, emptyHeaderItem);
|
||||
QLabel *maskLabel = new QLabel(imageTableWidget);
|
||||
maskLabel->setPixmap(QPixmap(er->modelList[i].maskName).scaledToHeight(64));
|
||||
imageTableWidget->setCellWidget(i,2,maskLabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTableWidgetItem *maskHeaderItem = new QTableWidgetItem(QString("double click for\nediting the mask"),i*3);
|
||||
imageTableWidget->setItem(i, 2, maskHeaderItem);
|
||||
}
|
||||
|
||||
if(!QFile::exists(ThumbCntName))
|
||||
{
|
||||
CharImage chi;
|
||||
bool ret=chi.Open(er->modelList[i].countName.toAscii());
|
||||
if(!ret) QMessageBox::warning(this,"Error in Thumb creation",QString("Unable to create '%1' from '%2'").arg(ThumbCntName,er->modelList[i].textureName));
|
||||
|
||||
CharImage::colorizedScaledToHeight(64,chi).save(ThumbCntName,"jpg");
|
||||
if(!QFile::exists(ThumbCntName))
|
||||
QMessageBox::warning(this,"Error in Thumb creation",QString("Unable to create '%1' from '%2'").arg(ThumbCntName,er->modelList[i].textureName));
|
||||
}
|
||||
QLabel *countLabel = new QLabel(imageTableWidget);
|
||||
countLabel->setPixmap(QPixmap(ThumbCntName));
|
||||
QPixmap tmp(ThumbCntName);
|
||||
if(tmp.isNull())
|
||||
QMessageBox::warning(this,"Error in Thumb creation",QString("Null Pixmap '%1'").arg(ThumbCntName));
|
||||
imageTableWidget->setCellWidget(i,3,countLabel);
|
||||
}
|
||||
|
||||
//cb(100,"Completed Image Reading.");
|
||||
|
||||
show(); // necessary to make the size of the image preview correct.
|
||||
imageTableWidget->setItemSelected(imageTableWidget->item(0,0),true);
|
||||
imageTableWidget->setItemSelected(imageTableWidget->item(0,1),true);
|
||||
imageTableWidget->setItemSelected(imageTableWidget->item(0,2),true);
|
||||
//on_imageTableWidget_itemSelectionChanged();
|
||||
|
||||
}
|
||||
|
||||
void v3dImportDialog::on_imageTableWidget_itemSelectionChanged()
|
||||
{
|
||||
if(imageTableWidget->selectedItems().size()==3)
|
||||
{
|
||||
int row= imageTableWidget->row(imageTableWidget->selectedItems().first());
|
||||
QPixmap tmp(er->modelList[row].textureName);
|
||||
imgSize=tmp.size();
|
||||
previewLabel->setPixmap(tmp.scaled(previewLabel->size(),Qt::KeepAspectRatio) );
|
||||
on_subsampleSpinBox_valueChanged(subsampleSpinBox->value());
|
||||
}
|
||||
}
|
||||
void v3dImportDialog::on_plyButton_clicked()
|
||||
{
|
||||
exportToPLY = true;
|
||||
accept();
|
||||
}
|
||||
void v3dImportDialog::on_selectButton_clicked()
|
||||
{
|
||||
int itemNum=imageTableWidget->rowCount();
|
||||
int modVal=subsampleSequenceSpinBox->value();
|
||||
if(modVal==0) return;
|
||||
|
||||
for(int i=0;i<itemNum;i+=modVal)
|
||||
imageTableWidget->setRangeSelected(QTableWidgetSelectionRange(i,0,i,2),true);
|
||||
}
|
||||
|
||||
void v3dImportDialog::on_imageTableWidget_itemClicked(QTableWidgetItem * item )
|
||||
{
|
||||
int row= imageTableWidget->row(item);
|
||||
previewLabel->setPixmap(
|
||||
QPixmap(er->modelList[row].textureName).scaled(previewLabel->size(),Qt::KeepAspectRatio) );
|
||||
|
||||
}
|
||||
|
||||
void v3dImportDialog::on_imageTableWidget_itemDoubleClicked(QTableWidgetItem * item )
|
||||
{
|
||||
int row= imageTableWidget->row(item);
|
||||
int col= imageTableWidget->column(item);
|
||||
if(col!=2) return;
|
||||
qDebug("DoubleClicked on image %s",qPrintable(er->modelList[row].textureName));
|
||||
QImage ttt(er->modelList[row].textureName);
|
||||
qDebug("'%s' %i x %i",qPrintable(er->modelList[row].textureName),ttt.width(),ttt.height());
|
||||
//ui::maskImageWidget masker(QImage(er->modelList[row].textureName));
|
||||
ui::maskImageWidget masker(ttt);
|
||||
if (QFile::exists(er->modelList[row].maskName))
|
||||
masker.loadMask(er->modelList[row].maskName);
|
||||
|
||||
QImage mymask;
|
||||
if (masker.exec() == QDialog::Accepted) mymask = masker.getMask();
|
||||
if (!mymask.isNull())
|
||||
{
|
||||
mymask.save(er->modelList[row].maskName,"png");
|
||||
QLabel *imageLabel = new QLabel(imageTableWidget);
|
||||
imageLabel->setPixmap(QPixmap(er->modelList[row].maskName).scaledToHeight(64));
|
||||
imageTableWidget->itemAt(row,2)->setText("");
|
||||
imageTableWidget->setCellWidget(row,2,imageLabel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void v3dImportDialog::on_minCountSpinBox_valueChanged(int val)
|
||||
{
|
||||
if(minCountSlider->value()!=val) minCountSlider->setValue(val);
|
||||
}
|
||||
|
||||
void v3dImportDialog::on_minCountSlider_valueChanged(int val)
|
||||
{
|
||||
if(minCountSpinBox->value()!=val) minCountSpinBox->setValue(val);
|
||||
}
|
||||
|
||||
void v3dImportDialog::on_subsampleSpinBox_valueChanged(int)
|
||||
{
|
||||
int ss=subsampleSpinBox->value();
|
||||
if(ss==0)
|
||||
{
|
||||
subsampleSpinBox->setValue(1);
|
||||
return;
|
||||
}
|
||||
imgSizeLabel->setText(QString("(%1 x %2) -> (%3 x %4)").arg(imgSize.width()).arg(imgSize.height()).arg(imgSize.width()/ss).arg(imgSize.height()/ss) );
|
||||
}
|
||||
|
||||
void v3dImportDialog::on_mergeResolutionSpinBox_valueChanged(int)
|
||||
{
|
||||
fastMergeCheckBox->setChecked(true); // if someone touch the slider check the fast merging box
|
||||
}
|
||||
|
||||
void v3dImportDialog::dilationSizeChanged(int size)
|
||||
{
|
||||
int winsize = size * 2 + 1;
|
||||
QString str = QString("%1 x %2").arg(winsize).arg(winsize);
|
||||
lblDilationSizeValue->setText(str);
|
||||
}
|
||||
|
||||
void v3dImportDialog::erosionSizeChanged(int size)
|
||||
{
|
||||
int winsize = size * 2 + 1;
|
||||
QString str = QString("%1 x %2").arg(winsize).arg(winsize);
|
||||
lblErosionSizeValue->setText(str);
|
||||
}
|
||||
81
src/plugins_experimental/edit_epoch/v3dImportDialog.h
Normal file
81
src/plugins_experimental/edit_epoch/v3dImportDialog.h
Normal file
@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program 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 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef V3DIMPORTER_DIALOG_H
|
||||
#define V3DIMPORTER_DIALOG_H
|
||||
|
||||
// for options on decimator
|
||||
#include <QDialog>
|
||||
#include <qfiledialog.h>
|
||||
#include "ui_v3dImportDialog.h"
|
||||
#include "epoch_reconstruction.h"
|
||||
|
||||
class v3dImportDialog : public QDialog, public Ui::v3dImportDialog {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
v3dImportDialog() : QDialog()
|
||||
{
|
||||
setupUi( this );
|
||||
subsampleSpinBox->setValue(2);
|
||||
minCountSpinBox->setValue(3);
|
||||
|
||||
// connections
|
||||
connect(dilationSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(dilationSizeChanged(int)));
|
||||
connect(erosionSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(erosionSizeChanged(int)));
|
||||
|
||||
er=0;
|
||||
exportToPLY=false;
|
||||
|
||||
fileName = QFileDialog::getOpenFileName(this->parentWidget(), tr("Select v3D File"), ".", "*.v3d");
|
||||
}
|
||||
|
||||
public:
|
||||
void setEpochReconstruction(EpochReconstruction *_er);
|
||||
bool exportToPLY; /// when true all the selected range maps are exported as separated ply
|
||||
QString fileName;
|
||||
|
||||
public slots:
|
||||
void on_selectButton_clicked();
|
||||
void on_imageTableWidget_itemClicked(QTableWidgetItem * item );
|
||||
void on_imageTableWidget_itemSelectionChanged();
|
||||
void on_imageTableWidget_itemDoubleClicked(QTableWidgetItem * item );
|
||||
void on_plyButton_clicked();
|
||||
private:
|
||||
EpochReconstruction *er;
|
||||
QString erCreated;
|
||||
|
||||
QSize imgSize;
|
||||
|
||||
|
||||
private slots:
|
||||
void on_mergeResolutionSpinBox_valueChanged(int);
|
||||
void on_subsampleSpinBox_valueChanged(int);
|
||||
void on_minCountSlider_valueChanged(int);
|
||||
void on_minCountSpinBox_valueChanged(int);
|
||||
void dilationSizeChanged(int);
|
||||
void erosionSizeChanged(int);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user