dellepiane: porting of arc3D filter to edit

This commit is contained in:
Matteo Dellepiane matteodelle 2012-01-31 16:52:39 +00:00
parent 3c6652dd2f
commit 810e38942f
32 changed files with 5234 additions and 0 deletions

View 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()
{
}

View 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

View 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
}

View 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>

View 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)

View 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

View 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;
}

View 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);
};
}

View 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;
//}

View 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

View 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

View 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));
}
}

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View 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);
}
};

View 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

View 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();
}
};

View 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

View 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;
}
}
}

View 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_;
};

View 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;
}
}
}

View 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

View 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

View 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;
};

View 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

View 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>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-style:normal; text-decoration:none;">&lt;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:&lt;/p>&lt;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&lt;/p>&lt;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 &lt;span style=" font-style:italic;">(one point every 4)&lt;/span>&lt;/p>&lt;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 &lt;span style=" font-style:italic;">(one point every 9)&lt;/span>&lt;/p>&lt;/body>&lt;/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>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-style:normal; text-decoration:none;">&lt;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&lt;/p>&lt;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&lt;/p>&lt;/body>&lt;/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>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-style:normal; text-decoration:none;">&lt;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.&lt;/p>&lt;/body>&lt;/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>

View 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

View 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);
}

View 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