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(logFP) fprintf(logFP,"**** 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(logFP) fprintf(logFP,"**** depthFilter: deleted %i on %i\n",deletedCnt,w*h); }
bool ExtraMeshColorizePlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb){ MeshModel &m=*(md.mm()); switch(ID(filter)) { case CP_SATURATE_QUALITY:{ m.updateDataMask(MeshModel::MM_VERTFACETOPO); tri::UpdateQuality<CMeshO>::VertexSaturate(m.cm, par.getFloat("gradientThr")); if(par.getBool("updateColor")) { Histogramf H; tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H); m.updateDataMask(MeshModel::MM_VERTCOLOR); tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f)); } Log("Saturated "); } break; case CP_MAP_VQUALITY_INTO_COLOR: m.updateDataMask(MeshModel::MM_VERTCOLOR); case CP_CLAMP_QUALITY: { float RangeMin = par.getFloat("minVal"); float RangeMax = par.getFloat("maxVal"); bool usePerc = par.getDynamicFloat("perc")>0; Histogramf H; tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H); float PercLo = H.Percentile(par.getDynamicFloat("perc")/100.f); float PercHi = H.Percentile(1.0-par.getDynamicFloat("perc")/100.f); if(par.getBool("zeroSym")) { RangeMin = min(RangeMin, -math::Abs(RangeMax)); RangeMax = max(math::Abs(RangeMin), RangeMax); PercLo = min(PercLo, -math::Abs(PercHi)); PercHi = max(math::Abs(PercLo), PercHi); } if(usePerc) { if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,PercLo,PercHi); else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,PercLo,PercHi); Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ",H.MinV(),H.MaxV(),PercLo,PercHi,par.getDynamicFloat("perc"),100-par.getDynamicFloat("perc")); } else { if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,RangeMin,RangeMax); else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,RangeMin,RangeMax); Log("Quality Range: %f %f; Used (%f %f)",H.MinV(),H.MaxV(),RangeMin,RangeMax); } break; } case CP_MAP_FQUALITY_INTO_COLOR: { m.updateDataMask(MeshModel::MM_FACECOLOR); float RangeMin = par.getFloat("minVal"); float RangeMax = par.getFloat("maxVal"); float perc = par.getDynamicFloat("perc"); Histogramf H; tri::Stat<CMeshO>::ComputePerFaceQualityHistogram(m.cm,H); float PercLo = H.Percentile(perc/100.f); float PercHi = H.Percentile(1.0-perc/100.f); // Make the range and percentile symmetric w.r.t. zero, so that // the value zero is always colored in yellow if(par.getBool("zeroSym")){ RangeMin = min(RangeMin, -math::Abs(RangeMax)); RangeMax = max(math::Abs(RangeMin), RangeMax); PercLo = min(PercLo, -math::Abs(PercHi)); PercHi = max(math::Abs(PercLo), PercHi); } tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,PercLo,PercHi); Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ", H.MinV(), H.MaxV(), PercLo, PercHi, perc, 100-perc); break; } case CP_DISCRETE_CURVATURE: { m.updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTCURV); m.updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY); tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m.cm); if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m.cm) > 0) { errorMessage = "Mesh has some not 2-manifold faces, Curvature computation requires manifoldness"; // text return false; // can't continue, mesh can't be processed } int delvert=tri::Clean<CMeshO>::RemoveUnreferencedVertex(m.cm); if(delvert) Log("Pre-Curvature Cleaning: Removed %d unreferenced vertices",delvert); tri::Allocator<CMeshO>::CompactVertexVector(m.cm); tri::UpdateCurvature<CMeshO>::MeanAndGaussian(m.cm); int curvType = par.getEnum("CurvatureType"); switch(curvType){ case 0: tri::UpdateQuality<CMeshO>::VertexFromMeanCurvature(m.cm); Log( "Computed Mean Curvature"); break; case 1: tri::UpdateQuality<CMeshO>::VertexFromGaussianCurvature(m.cm); Log( "Computed Gaussian Curvature"); break; case 2: tri::UpdateQuality<CMeshO>::VertexFromRMSCurvature(m.cm); Log( "Computed RMS Curvature"); break; case 3: tri::UpdateQuality<CMeshO>::VertexFromAbsoluteCurvature(m.cm); Log( "Computed ABS Curvature"); break; default : assert(0); } Histogramf H; tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H); tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f)); Log( "Curvature Range: %f %f (Used 90 percentile %f %f) ",H.MinV(),H.MaxV(),H.Percentile(0.1f),H.Percentile(0.9f)); break; } case CP_TRIANGLE_QUALITY: { m.updateDataMask(MeshModel::MM_FACECOLOR | MeshModel::MM_FACEQUALITY); CMeshO::FaceIterator fi; Distribution<float> distrib; float minV = 0; float maxV = 1.0; int metric = par.getEnum("Metric"); if(metric ==4 || metric ==5 ) { if(!m.hasDataMask(MeshModel::MM_VERTTEXCOORD) && !m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)) { this->errorMessage = "This metric need Texture Coordinate"; return false; } } switch(metric){ case 0: { //area / max edge minV = 0; maxV = sqrt(3.0f)/2.0f; for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::Quality((*fi).P(0), (*fi).P(1),(*fi).P(2)); } break; case 1: { //inradius / circumradius for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::QualityRadii((*fi).P(0), (*fi).P(1), (*fi).P(2)); } break; case 2: { //mean ratio for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::QualityMeanRatio((*fi).P(0), (*fi).P(1), (*fi).P(2)); } break; case 3: { // AREA for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = vcg::DoubleArea((*fi))*0.5f; tri::Stat<CMeshO>::ComputePerFaceQualityMinMax(m.cm,minV,maxV); } break; case 4: { //TEXTURE Angle Distortion if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)) { for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,true>::AngleDistortion(&*fi); } else { for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,false>::AngleDistortion(&*fi); } tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib); minV = distrib.Percentile(0.05); maxV = distrib.Percentile(0.95); } break; case 5: { //TEXTURE Area Distortion float areaScaleVal, edgeScaleVal; if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)) { Distortion<CMeshO,true>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal); for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,true>::AreaDistortion(&*fi,areaScaleVal); } else { Distortion<CMeshO,false>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal); for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) (*fi).Q() = Distortion<CMeshO,false>::AreaDistortion(&*fi,areaScaleVal); } tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib); minV = distrib.Percentile(0.05); maxV = distrib.Percentile(0.95); } break; default: assert(0); } tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,minV,maxV,false); break; } case CP_RANDOM_CONNECTED_COMPONENT: m.updateDataMask(MeshModel::MM_FACEFACETOPO); m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR); vcg::tri::UpdateColor<CMeshO>::FaceRandomConnectedComponent(m.cm); break; case CP_RANDOM_FACE: m.updateDataMask(MeshModel::MM_FACEFACETOPO); m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR); vcg::tri::UpdateColor<CMeshO>::MultiFaceRandom(m.cm); break; case CP_VERTEX_SMOOTH: { int iteration = par.getInt("iteration"); tri::Smooth<CMeshO>::VertexColorLaplacian(m.cm,iteration,false,cb); } break; case CP_FACE_SMOOTH: { m.updateDataMask(MeshModel::MM_FACEFACETOPO); int iteration = par.getInt("iteration"); tri::Smooth<CMeshO>::FaceColorLaplacian(m.cm,iteration,false,cb); } break; case CP_FACE_TO_VERTEX: m.updateDataMask(MeshModel::MM_VERTCOLOR); tri::UpdateColor<CMeshO>::VertexFromFace(m.cm); break; case CP_VERTEX_TO_FACE: m.updateDataMask(MeshModel::MM_FACECOLOR); tri::UpdateColor<CMeshO>::FaceFromVertex(m.cm); break; case CP_TEXTURE_TO_VERTEX: { m.updateDataMask(MeshModel::MM_VERTCOLOR); if(!HasPerWedgeTexCoord(m.cm)) break; CMeshO::FaceIterator fi; QImage tex(m.cm.textures[0].c_str()); for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) { for (int i=0; i<3; i++) { // note the trick for getting only the fractional part of the uv with the correct wrapping (e.g. 1.5 -> 0.5 and -0.3 -> 0.7) vcg::Point2f newcoord((*fi).WT(i).P().X()-floor((*fi).WT(i).P().X()),(*fi).WT(i).P().Y()-floor((*fi).WT(i).P().Y())); QRgb val = tex.pixel(newcoord[0]*tex.width(),(1-newcoord[1])*tex.height()-1); (*fi).V(i)->C().SetRGB(qRed(val),qGreen(val),qBlue(val)); } } } break; } return true; }
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(logFP) fprintf(logFP,"**** 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); }