From b0c165499c3704dc2b242e2b0192c78542cd1d04 Mon Sep 17 00:00:00 2001 From: hesuicong Date: Mon, 20 Jul 2026 09:36:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E9=97=B4=E7=89=88=E6=9C=AC=E4=BF=9D?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/MVS/SceneTexture.cpp | 283 +++++--------------------------------- 1 file changed, 35 insertions(+), 248 deletions(-) diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 3e67881..3c33c7a 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -6935,6 +6935,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT // printf("FaceViewSelection3 2 scene.mesh.vertices.size=%d\n", scene.mesh.vertices.size()); bool bUseVirtualFaces(minCommonCameras > 0); + bUseVirtualFaces = false; // list all views for each face FaceDataViewArr facesDatas; @@ -7673,263 +7674,49 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT if (!bUseVirtualFaces) { - // assign the best view to each face - labels.resize(faces.size()); - { - // normalize quality values - float maxQuality(0); - for (const FaceDataArr& faceDatas: facesDatas) { - for (const FaceData& faceData: faceDatas) - if (maxQuality < faceData.quality) - maxQuality = faceData.quality; - } - Histogram32F hist(std::make_pair(0.f, maxQuality), 1000); - for (const FaceDataArr& faceDatas: facesDatas) { - for (const FaceData& faceData: faceDatas) - hist.Add(faceData.quality); - } - const float normQuality(hist.GetApproximatePermille(0.95f)); - - #if TEXOPT_INFERENCE == TEXOPT_INFERENCE_LBP - // initialize inference structures - const LBPInference::EnergyType MaxEnergy(fRatioDataSmoothness*(LBPInference::EnergyType)LBPInference::MaxEnergy); - LBPInference inference; { - inference.SetNumNodes(faces.size()); - inference.SetSmoothCost(SmoothnessPotts); - // inference.SetSmoothCost(SmoothnessLinear); - // inference.SetSmoothCost(NewSmoothness); - - EdgeOutIter ei, eie; - FOREACH(f, faces) { - for (boost::tie(ei, eie) = boost::out_edges(f, graph); ei != eie; ++ei) { - ASSERT(f == (FIndex)ei->m_source); - const FIndex fAdj((FIndex)ei->m_target); - if (f < fAdj) // add edges only once - inference.SetNeighbors(f, fAdj); - } - // set costs for label 0 (undefined) - inference.SetDataCost((Label)0, f, MaxEnergy); - } - } + // 分配最佳视图给每个面片 + labels.resize(faces.size()); + labelsInvalid.resize(faces.size()); + + FOREACH(l, labelsInvalid) { + labelsInvalid[l] = NO_ID; + } - //* - for (const FaceDataArr& faceDatas : facesDatas) { - for (const FaceData& faceData : faceDatas) { - if (faceData.quality > maxQuality) - maxQuality = faceData.quality; - } - } - for (const FaceDataArr& faceDatas : facesDatas) { - for (const FaceData& faceData : faceDatas) - hist.Add(faceData.quality); + // 直接为每个面片选择最佳视图(跳过推理) + FOREACH(f, faces) { + const FaceDataArr& faceDatas = facesDatas[f]; + if (faceDatas.empty()) { + labels[f] = NO_ID; + continue; } - FOREACH(f, facesDatas) { - // if (scene.mesh.invalidFacesRelative.data.contains(f)) - // continue; - - const FaceDataArr& faceDatas = facesDatas[f]; - const size_t numViews = faceDatas.size(); - const unsigned minSingleView = 6; // 与虚拟面模式相同的阈值 - - bool bInvalidFacesRelative = false; - IIndex invalidView; - float invalidQuality; - - // if (numViews <= minSingleView) { - if (true) { - - std::vector> sortedViews; - sortedViews.reserve(faceDatas.size()); - for (const FaceData& fd : faceDatas) { - - if (fd.bInvalidFacesRelative) - { - bInvalidFacesRelative = true; - // sortedViews.emplace_back(fd.quality, fd.idxView); - invalidView = fd.idxView; - invalidQuality = fd.quality; - } - else - { - // if (fd.quality<=999.0) - { - sortedViews.emplace_back(fd.quality, fd.idxView); - // printf("1fd.quality=%f\n", fd.quality); - } - // else - // printf("2fd.quality=%f\n", fd.quality); - } - } - - std::sort(sortedViews.begin(), sortedViews.end(), - [](const auto& a, const auto& b) { return a.first > b.first; }); - // 设置数据成本:最佳视角成本最低,其他按质量排序递增 - const float baseCostScale = 0.1f; // 基础成本缩放系数 - const float costStep = 0.3f; // 相邻视角成本增量 - - for (const auto& image : images) - { - // printf("image name=%s\n", image.name.c_str()); - } - - if (bInvalidFacesRelative && sortedViews.size() == 0) - { - // const Label label = (Label)sortedViews[0].second + 1; - const Label label = (Label)invalidView + 1; - float cost = (1.f - invalidQuality / normQuality) * MaxEnergy; - // float cost = 0; - inference.SetDataCost(label, f, cost); - continue; - } - - // printf("sortedViews size=%d\n", sortedViews.size()); - for (size_t i = 0; i < sortedViews.size(); ++i) { - const Label label = (Label)sortedViews[i].second + 1; - float cost; - - std::string strPath = images[label-1].name; - size_t lastSlash = strPath.find_last_of("/\\"); - if (lastSlash == std::string::npos) lastSlash = 0; // 若无分隔符,从头开始 - else lastSlash++; // 跳过分隔符 - - // 查找扩展名分隔符 '.' 的位置 - size_t lastDot = strPath.find_last_of('.'); - if (lastDot == std::string::npos) lastDot = strPath.size(); // 若无扩展名,截到末尾 - - // 截取文件名(不含路径和扩展名) - std::string strName = strPath.substr(lastSlash, lastDot - lastSlash); - - if (i == 0) { - // if (true) { - // 最佳视角 - // cost = (1.f - sortedViews[i].first / normQuality) * MaxEnergy * baseCostScale; - cost = (1.f - sortedViews[i].first / normQuality) * MaxEnergy; - // cost = 0; - inference.SetDataCost(label, f, cost); - } else { - // 其他视角:成本随排名线性增加 - int stepIndex = i; - // if (i > 3) - // stepIndex = i - 3; - cost = MaxEnergy * (baseCostScale + costStep * stepIndex); - // 确保成本不超过MaxEnergy - cost = std::min(cost, MaxEnergy); - // cost = MaxEnergy; - inference.SetDataCost(label, f, cost); - } - } - - } else { - for (const FaceData& fd : faceDatas) { - const Label label = (Label)fd.idxView + 1; - const float normalizedQuality = fd.quality / normQuality; - const float cost = (1.f - normalizedQuality) * MaxEnergy; - inference.SetDataCost(label, f, cost); + float bestQuality = -1.0f; + IIndex bestView = NO_ID; + bool bBestIsInvalid = false; + + for (const FaceData& fd : faceDatas) { + // 跳过无效视图(根据你的需求决定是否跳过) + if (fd.bInvalidFacesRelative) { + // 如果没有有效视图,才考虑无效视图 + if (bestView == NO_ID) { + bestView = fd.idxView; + bestQuality = fd.quality; + bBestIsInvalid = true; } - } - } - //*/ - - // assign the optimal view (label) to each face - // (label 0 is reserved as undefined) - inference.Optimize(); - - // extract resulting labeling - labels.Memset(0xFF); - FOREACH(l, labels) { - const Label label(inference.GetLabel(l)); - ASSERT(label < images.size()+1); - if (label > 0) - labels[l] = label-1; - } - #endif - - #if TEXOPT_INFERENCE == TEXOPT_INFERENCE_TRWS - // find connected components - ASSERT((FIndex)boost::num_vertices(graph) == faces.size()); - components.resize(faces.size()); - const FIndex nComponents(boost::connected_components(graph, components.data())); - - // map face ID from global to component space - typedef cList NodeIDs; - NodeIDs nodeIDs(faces.size()); - NodeIDs sizes(nComponents); - sizes.Memset(0); - FOREACH(c, components) - nodeIDs[c] = sizes[components[c]]++; - - // initialize inference structures - const LabelID numLabels(images.size()+1); - CLISTDEFIDX(TRWSInference, FIndex) inferences(nComponents); - FOREACH(s, sizes) { - const NodeID numNodes(sizes[s]); - ASSERT(numNodes > 0); - if (numNodes <= 1) continue; - TRWSInference& inference = inferences[s]; - inference.Init(numNodes, numLabels); - } - - // set data costs - { - // add nodes - CLISTDEF0(EnergyType) D(numLabels); - FOREACH(f, facesDatas) { - TRWSInference& inference = inferences[components[f]]; - if (inference.IsEmpty()) - continue; - D.MemsetValue(MaxEnergy); - const FaceDataArr& faceDatas = facesDatas[f]; - for (const FaceData& faceData: faceDatas) { - const Label label((Label)faceData.idxView); - const float normalizedQuality(faceData.quality>=normQuality ? 1.f : faceData.quality/normQuality); - const EnergyType dataCost(MaxEnergy*(1.f-normalizedQuality)); - D[label] = dataCost; - } - const NodeID nodeID(nodeIDs[f]); - inference.AddNode(nodeID, D.Begin()); } - // add edges - EdgeOutIter ei, eie; - FOREACH(f, faces) { - TRWSInference& inference = inferences[components[f]]; - if (inference.IsEmpty()) - continue; - for (boost::tie(ei, eie) = boost::out_edges(f, graph); ei != eie; ++ei) { - ASSERT(f == (FIndex)ei->m_source); - const FIndex fAdj((FIndex)ei->m_target); - ASSERT(components[f] == components[fAdj]); - if (f < fAdj) // add edges only once - inference.AddEdge(nodeIDs[f], nodeIDs[fAdj]); - } + + if (fd.quality > bestQuality) { + bestQuality = fd.quality; + bestView = fd.idxView; + bBestIsInvalid = false; } } - - // assign the optimal view (label) to each face - #ifdef TEXOPT_USE_OPENMP - #pragma omp parallel for schedule(dynamic) - for (int i=0; i<(int)inferences.size(); ++i) { - #else - FOREACH(i, inferences) { - #endif - TRWSInference& inference = inferences[i]; - if (inference.IsEmpty()) - continue; - inference.Optimize(); - } - // extract resulting labeling - labels.Memset(0xFF); - FOREACH(l, labels) { - TRWSInference& inference = inferences[components[l]]; - if (inference.IsEmpty()) - continue; - const Label label(inference.GetLabel(nodeIDs[l])); - ASSERT(label >= 0 && label < numLabels); - if (label < images.size()) - labels[l] = label; + + labels[f] = bestView; + if (bBestIsInvalid) { + labelsInvalid[f] = bestView; } - #endif } }