Point3m Arc3DModel::TraCorrection(CMeshO &m, int subsampleFactor, int minCount, int smoothSteps) { FloatImage depthImgf; CharImage countImgc; depthImgf.Open(depthName.toUtf8().data()); countImgc.Open(countName.toUtf8().data()); QImage TextureImg; TextureImg.load(textureName); 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"); float depthThr = ComputeDepthJumpThr(depthSubf,0.8f); for(int ii=0;ii<smoothSteps;++ii) Laplacian2(depthSubf,countSubf,minCount,FeatureMask,depthThr); vcg::tri::Grid<CMeshO>(m,depthSubf.w,depthSubf.h,depthImgf.w,depthImgf.h,&*depthSubf.v.begin()); // 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). ComputeDepthJumpThr(depthSubf,0.95f); 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.toUtf8().data()); CMeshO::VertexIterator vi; Matrix33d Rinv= Inverse(cam.R); Point3m correction(0.0,0.0,0.0); int numSamp=0; for(vi=m.vert.begin();vi!=m.vert.end();++vi)if(!(*vi).IsD()) { Point3m in=(*vi).P(); Point3d out; correction+=cam.DepthTo3DPoint(in[0], in[1], in[2], out); numSamp++; } if (numSamp!=0) correction/=(double)numSamp; return correction; }
/* 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::setArc3DReconstruction(Arc3DReconstruction *_er) { // if the epoch reconstruction has not changed do nothing if(erCreated == _er->created) { er=_er; return; } er=_er; erCreated=er->created; ui.infoLabel->setText(er->name + " - " + er->author + " - " + er->created); ui.imageTableWidget->clear(); ui.imageTableWidget->setRowCount(er->modelList.size()); ui.imageTableWidget->setColumnCount(4); //imageTableWidget->setColumnWidth (1,64); ui.imageTableWidget->setSelectionBehavior (QAbstractItemView::SelectRows); ui.imageTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui.imageTableWidget->setMinimumWidth(64*8); ui.rangeLabel->setPixmap(generateColorRamp()); ui.rangeLabel->setMaximumHeight(10); ui.rangeLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); ui.rangeLabel->setScaledContents(true); ui.minCountSlider->setMaximumHeight(12); int i; for(i=0; i<er->modelList.size() ;++i) { QString ThumbImgName=Arc3DModel::ThumbName(er->modelList[i].textureName); QString ThumbCntName=Arc3DModel::ThumbName(er->modelList[i].countName); ui.imageTableWidget->setRowHeight (i,64); QTableWidgetItem *emptyHeaderItem = new QTableWidgetItem(i*2); QTableWidgetItem *texNameHeaderItem = new QTableWidgetItem(er->modelList[i].textureName,i); ui.imageTableWidget->setItem(i, 0, texNameHeaderItem); ui.imageTableWidget->setItem(i, 1, emptyHeaderItem); QLabel *imageLabel = new QLabel(ui.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(Arc3DModel::ThumbName(er->modelList[i].textureName))); ui.imageTableWidget->setCellWidget(i,1,imageLabel); if(QFile::exists(er->modelList[i].maskName)) { QTableWidgetItem *emptyHeaderItem = new QTableWidgetItem(i*4); ui.imageTableWidget->setItem(i, 2, emptyHeaderItem); QLabel *maskLabel = new QLabel(ui.imageTableWidget); maskLabel->setPixmap(QPixmap(er->modelList[i].maskName).scaledToHeight(64)); ui.imageTableWidget->setCellWidget(i,2,maskLabel); } else { QTableWidgetItem *maskHeaderItem = new QTableWidgetItem(QString("double click for\nediting the mask"),i*3); ui.imageTableWidget->setItem(i, 2, maskHeaderItem); } if(!QFile::exists(ThumbCntName)) { CharImage chi; bool ret=chi.Open(er->modelList[i].countName.toUtf8().data()); 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(ui.imageTableWidget); countLabel->setPixmap(QPixmap(ThumbCntName)); QPixmap tmp(ThumbCntName); if(tmp.isNull()) QMessageBox::warning(this,"Error in Thumb creation",QString("Null Pixmap '%1'").arg(ThumbCntName)); ui.imageTableWidget->setCellWidget(i,3,countLabel); } show(); // necessary to make the size of the image preview correct. ui.imageTableWidget->setItemSelected(ui.imageTableWidget->item(0,0),true); ui.imageTableWidget->setItemSelected(ui.imageTableWidget->item(0,1),true); ui.imageTableWidget->setItemSelected(ui.imageTableWidget->item(0,2),true); }
bool Arc3DModel::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; clock(); depthImgf.Open(depthName.toUtf8().data()); countImgc.Open(countName.toUtf8().data()); QImage TextureImg; TextureImg.load(textureName); clock(); 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"); clock(); float depthThr = ComputeDepthJumpThr(depthSubf,0.8f); for(int ii=0;ii<smoothSteps;++ii) Laplacian2(depthSubf,countSubf,minCount,FeatureMask,depthThr); clock(); vcg::tri::Grid<CMeshO>(m,depthSubf.w,depthSubf.h,depthImgf.w,depthImgf.h,&*depthSubf.v.begin()); clock(); // 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.toUtf8().data()); CMeshO::VertexIterator vi; Matrix33d Rinv= Inverse(cam.R); for(vi=m.vert.begin();vi!=m.vert.end();++vi)if(!(*vi).IsD()) { Point3m 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])); vcg::Color4b tmpcol(qRed(c),qGreen(c),qBlue(c),0); (*vi).C().Import(tmpcol); 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; } clock(); CMeshO::FaceIterator fi; Point3m CameraPos = Point3m::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 { Point3m n=vcg::TriangleNormal(*fi); n.Normalize(); Point3m dir=CameraPos-vcg::Barycenter(*fi); dir.Normalize(); if(dir.dot(n) < minAngleCos) { (*fi).SetD(); --m.fn; } } } tri::Clean<CMeshO>::RemoveUnreferencedVertex(m); clock(); Matrix44m scaleMat; scaleMat.SetScale(scalingFactor,scalingFactor,scalingFactor); vcg::tri::UpdatePosition<CMeshO>::Matrix(m, scaleMat); return true; }