优化UV包围盒问题

This commit is contained in:
hesuicong committed 2026-10-13 16:07:50 +08:00
1 parent 5f06661d9b
commit eba47cae18
1 file changed
+49 -29
+49 -29
View File
@@ -16364,7 +16364,7 @@ bool MeshTexture::RasterizeVirtualFaces(
float currentScore = virtualFaceViewWeights[i].empty() ? -1.0f : virtualFaceViewWeights[i][0];
int pad = 4;
int pad = 8;
int minX = std::max(0, (int)floor(geom.uvBounds.ptMin.x() * textureSize - pad));
int maxX = std::min(textureSize - 1, (int)ceil(geom.uvBounds.ptMax.x() * textureSize + pad));
int minY = std::max(0, (int)floor(geom.uvBounds.ptMin.y() * textureSize - pad));
@@ -16454,13 +16454,16 @@ bool MeshTexture::RasterizeVirtualFaces(
mainPatch.convertTo(mainFloat, CV_32FC3, 1.0f / 255.0f);
cv::Mat mainLowFreq;
cv::GaussianBlur(mainFloat, mainLowFreq, cv::Size(31, 31), 2.0); // σ=10
cv::GaussianBlur(mainFloat, mainLowFreq, cv::Size(31, 31), 10.0); // σ=10
cv::Mat highFreq = mainFloat - mainLowFreq; // 高频 = 原图 - 低频
// 在合成之前,对 lowFreqPatch 再做一次轻微平滑
cv::GaussianBlur(lowFreqPatch, lowFreqPatch, cv::Size(5, 5), 1.0);
// ========== 合成:低频用多视图融合,高频用主视图细节 ==========
cv::Mat finalPatch = lowFreqPatch + highFreq;
// cv::Mat finalPatch = lowFreqPatch.clone();
// cv::Mat finalPatch = highFreq.clone();
// finalPatch = cv::Mat::zeros(finalPatch.size(), finalPatch.type());
// 钳制到 [0, 1]
@@ -16472,33 +16475,50 @@ bool MeshTexture::RasterizeVirtualFaces(
cv::Mat finalPatch8U;
clampedPatch.convertTo(finalPatch8U, CV_8UC3, 255.0f);
// ========== 写入 atlas ==========
#pragma omp critical (atlas_write)
{
for (int y = 0; y < patchH; ++y) {
for (int x = 0; x < patchW; ++x) {
cv::Vec3b color = finalPatch8U.at<cv::Vec3b>(y, x);
if (color[0] == 0 && color[1] == 0 && color[2] == 0) continue;
// 在写入 atlas 时,对边界像素做衰减混合
#pragma omp critical (atlas_write)
{
for (int y = 0; y < patchH; ++y) {
for (int x = 0; x < patchW; ++x) {
cv::Vec3b color = finalPatch8U.at<cv::Vec3b>(y, x);
if (color[0] == 0 && color[1] == 0 && color[2] == 0) continue;
int atlasX = x + minX, atlasY = y + minY;
if (atlasX<0||atlasX>=textureSize||atlasY<0||atlasY>=textureSize) continue;
size_t idx = atlasY * textureSize + atlasX;
int atlasX = x + minX, atlasY = y + minY;
if (atlasX<0||atlasX>=textureSize||atlasY<0||atlasY>=textureSize) continue;
size_t idx = atlasY * textureSize + atlasX;
if (currentScore > m_texelScores[idx].score) {
if (atlasY >= 0 && atlasY < atlas.rows && atlasX >= 0 && atlasX < atlas.cols) {
cv::Vec3b& pixel = atlas.at<cv::Vec3b>(atlasY, atlasX);
pixel[0] = color[0];
pixel[1] = color[1];
pixel[2] = color[2];
}
m_texelScores[idx].score = currentScore;
m_texelScores[idx].viewID = mainView;
m_texelPatchID[idx] = i;
}
}
}
}
// ===== 新增:边界衰减权重 =====
float weight = 1.0f;
float distToEdgeX = std::min((float)x, (float)(patchW - 1 - x));
float distToEdgeY = std::min((float)y, (float)(patchH - 1 - y));
float minDist = std::min(distToEdgeX, distToEdgeY);
if (minDist < pad) {
// 边界 8 像素内做线性衰减
weight = minDist / (float)pad;
weight = weight * weight; // 平方衰减更平滑
}
// 如果已有更高分的 texel,跳过(保持高分优先)
if (currentScore > m_texelScores[idx].score) {
// 如果有旧值,做加权混合
if (m_texelScores[idx].score > 0 && weight < 1.0f) {
cv::Vec3b oldColor = atlas.at<cv::Vec3b>(atlasY, atlasX);
float oldWeight = 1.0f - weight;
color[0] = (uchar)(color[0] * weight + oldColor[0] * oldWeight);
color[1] = (uchar)(color[1] * weight + oldColor[1] * oldWeight);
color[2] = (uchar)(color[2] * weight + oldColor[2] * oldWeight);
}
atlas.at<cv::Vec3b>(atlasY, atlasX) = color;
m_texelScores[idx].score = currentScore;
m_texelScores[idx].viewID = mainView;
m_texelPatchID[idx] = i;
}
}
}
}
}
VERBOSE("[Raster] Step 3: rasterization done, building RC patches...");
@@ -16566,7 +16586,7 @@ bool MeshTexture::RasterizeVirtualFaces(
if (m_texelPatchID[i] != NO_ID) validPixels++;
DEBUG_EXTRA("m_texelPatchID: %d valid pixels out of %zu", validPixels, m_texelPatchID.size());
// cv::imwrite("/home/algo/Documents/openMVS/data/546893/out.546893/debug_atlas_before_return.png", atlas);
cv::imwrite("/home/algo/Documents/openMVS/data/546893/out.546893/debug_atlas_before_return.png", atlas);
return true;
}