void Arc3DModel::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])); 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"); }
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; }
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; }