Browse Source

进一步优化

ManualUV
hesuicong 4 days ago
parent
commit
4713198454
  1. 170
      libs/MVS/SceneTexture.cpp

170
libs/MVS/SceneTexture.cpp

@ -18543,6 +18543,176 @@ bool MeshTexture::SelectBestViewsForVirtualFaces( @@ -18543,6 +18543,176 @@ bool MeshTexture::SelectBestViewsForVirtualFaces(
DEBUG_EXTRA("Fallback by center face : %zu", fallbackByCenterFace);
DEBUG_EXTRA("=================================================");
// ================================================================
// ★★★ 连通域强制统一视角(消除色差碎片)★★★
// ================================================================
{
TD_TIMER_START();
const FIndex NF = (FIndex)faceToView.size();
if (NF == 0) return true;
// 1. 构建面片邻接关系(只考虑有效面片)
std::vector<std::vector<FIndex>> adjList(NF);
for (FIndex fid = 0; fid < NF; ++fid) {
if (faceToView[fid] == NO_ID) continue;
if (fid >= (FIndex)scene.mesh.faceFaces.size()) continue;
const Mesh::FaceFaces& neighbors = scene.mesh.faceFaces[fid];
for (int k = 0; k < 3; ++k) {
FIndex nb = neighbors[k];
if (nb == NO_ID || nb >= NF) continue;
if (faceToView[nb] == NO_ID) continue;
adjList[fid].push_back(nb);
}
}
// 2. 连通域标记(BFS)
std::vector<int> component(NF, -1);
int numComponents = 0;
for (FIndex fid = 0; fid < NF; ++fid) {
if (faceToView[fid] == NO_ID) continue;
if (component[fid] >= 0) continue;
std::queue<FIndex> q;
q.push(fid);
component[fid] = numComponents;
while (!q.empty()) {
FIndex cur = q.front(); q.pop();
for (FIndex nb : adjList[cur]) {
if (component[nb] < 0) {
component[nb] = numComponents;
q.push(nb);
}
}
}
numComponents++;
}
DEBUG_EXTRA("Connected components: %d components from %d faces", numComponents, NF);
// 3. 统计每个连通域的视角分布
struct CompInfo {
std::vector<FIndex> faces;
std::map<IIndex, int> viewVotes;
std::map<IIndex, float> viewScoreSum;
std::map<IIndex, float> viewAvgScore;
};
std::vector<CompInfo> comps(numComponents);
for (FIndex fid = 0; fid < NF; ++fid) {
if (faceToView[fid] == NO_ID) continue;
int c = component[fid];
if (c < 0) continue;
IIndex vid = faceToView[fid];
float score = faceScores[fid];
comps[c].faces.push_back(fid);
comps[c].viewVotes[vid]++;
comps[c].viewScoreSum[vid] += score;
}
for (int c = 0; c < numComponents; ++c) {
for (auto& vs : comps[c].viewScoreSum) {
IIndex vid = vs.first;
int votes = comps[c].viewVotes[vid];
comps[c].viewAvgScore[vid] = vs.second / votes;
}
}
// 4. 每个连通域选最佳视角
int changedFaces = 0;
int smallComponents = 0;
for (int c = 0; c < numComponents; ++c) {
auto& comp = comps[c];
if (comp.faces.empty()) continue;
// 小连通域合并
if ((int)comp.faces.size() < 5) {
smallComponents++;
std::map<int, int> neighborCompVotes;
for (FIndex fid : comp.faces) {
for (FIndex nb : adjList[fid]) {
int nc = component[nb];
if (nc >= 0 && nc != c) {
neighborCompVotes[nc]++;
}
}
}
if (!neighborCompVotes.empty()) {
auto bestNb = std::max_element(neighborCompVotes.begin(), neighborCompVotes.end(),
[](const auto& a, const auto& b) { return a.second < b.second; });
int targetComp = bestNb->first;
IIndex targetView = NO_ID;
int maxVotes = 0;
for (const auto& vv : comps[targetComp].viewVotes) {
if (vv.second > maxVotes) {
maxVotes = vv.second;
targetView = vv.first;
}
}
if (targetView != NO_ID) {
for (FIndex fid : comp.faces) {
if (faceToView[fid] != targetView) {
faceToView[fid] = targetView;
faceScores[fid] = comps[targetComp].viewAvgScore[targetView];
changedFaces++;
}
}
}
continue;
}
}
// 正常连通域选视角
IIndex bestView = NO_ID;
float bestWeightedScore = -FLT_MAX;
int totalFaces = (int)comp.faces.size();
for (const auto& vv : comp.viewVotes) {
IIndex vid = vv.first;
int votes = vv.second;
float avgScore = comp.viewAvgScore[vid];
float voteRatio = (float)votes / totalFaces;
float normalizedScore = std::max(0.0f, std::min(1.0f, avgScore));
float weightedScore = 0.6f * voteRatio + 0.4f * normalizedScore;
if (weightedScore > bestWeightedScore) {
bestWeightedScore = weightedScore;
bestView = vid;
}
}
if (bestView == NO_ID) continue;
for (FIndex fid : comp.faces) {
if (faceToView[fid] != bestView) {
faceToView[fid] = bestView;
faceScores[fid] = comp.viewAvgScore[bestView];
changedFaces++;
}
}
}
DEBUG_EXTRA("Component unification: %d faces changed, %d small components merged (%s)",
changedFaces, smallComponents, TD_TIMER_GET_FMT().c_str());
// ★★★ 注意:不要在这里更新 faceViews/faceViewWeights!
// faceViews 会在视图选择阶段的末尾,由 SelectBestViewsForVirtualFaces 根据 faceToView 重建
// 如果在这里强行同步,会破坏虚拟面片与视图的映射关系,导致采样坐标错误
DEBUG_EXTRA("Unification complete: %d components processed.", numComponents);
}
return true;
}

Loading…
Cancel
Save