优化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]; 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 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 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)); 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); mainPatch.convertTo(mainFloat, CV_32FC3, 1.0f / 255.0f);
cv::Mat mainLowFreq; 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; // 高频 = 原图 - 低频 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 + highFreq;
// cv::Mat finalPatch = lowFreqPatch.clone(); // cv::Mat finalPatch = highFreq.clone();
// finalPatch = cv::Mat::zeros(finalPatch.size(), finalPatch.type()); // finalPatch = cv::Mat::zeros(finalPatch.size(), finalPatch.type());
// 钳制到 [0, 1] // 钳制到 [0, 1]
@@ -16472,33 +16475,50 @@ bool MeshTexture::RasterizeVirtualFaces(
cv::Mat finalPatch8U; cv::Mat finalPatch8U;
clampedPatch.convertTo(finalPatch8U, CV_8UC3, 255.0f); clampedPatch.convertTo(finalPatch8U, CV_8UC3, 255.0f);
// ========== 写入 atlas ========== // 在写入 atlas 时,对边界像素做衰减混合
#pragma omp critical (atlas_write) #pragma omp critical (atlas_write)
{ {
for (int y = 0; y < patchH; ++y) { for (int y = 0; y < patchH; ++y) {
for (int x = 0; x < patchW; ++x) { for (int x = 0; x < patchW; ++x) {
cv::Vec3b color = finalPatch8U.at<cv::Vec3b>(y, x); cv::Vec3b color = finalPatch8U.at<cv::Vec3b>(y, x);
if (color[0] == 0 && color[1] == 0 && color[2] == 0) continue; if (color[0] == 0 && color[1] == 0 && color[2] == 0) continue;
int atlasX = x + minX, atlasY = y + minY; int atlasX = x + minX, atlasY = y + minY;
if (atlasX<0||atlasX>=textureSize||atlasY<0||atlasY>=textureSize) continue; if (atlasX<0||atlasX>=textureSize||atlasY<0||atlasY>=textureSize) continue;
size_t idx = atlasY * textureSize + atlasX; size_t idx = atlasY * textureSize + atlasX;
if (currentScore > m_texelScores[idx].score) { // ===== 新增:边界衰减权重 =====
if (atlasY >= 0 && atlasY < atlas.rows && atlasX >= 0 && atlasX < atlas.cols) { float weight = 1.0f;
cv::Vec3b& pixel = atlas.at<cv::Vec3b>(atlasY, atlasX); float distToEdgeX = std::min((float)x, (float)(patchW - 1 - x));
pixel[0] = color[0]; float distToEdgeY = std::min((float)y, (float)(patchH - 1 - y));
pixel[1] = color[1]; float minDist = std::min(distToEdgeX, distToEdgeY);
pixel[2] = color[2];
} if (minDist < pad) {
m_texelScores[idx].score = currentScore; // 边界 8 像素内做线性衰减
m_texelScores[idx].viewID = mainView; weight = minDist / (float)pad;
m_texelPatchID[idx] = i; 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..."); VERBOSE("[Raster] Step 3: rasterization done, building RC patches...");
@@ -16566,7 +16586,7 @@ bool MeshTexture::RasterizeVirtualFaces(
if (m_texelPatchID[i] != NO_ID) validPixels++; if (m_texelPatchID[i] != NO_ID) validPixels++;
DEBUG_EXTRA("m_texelPatchID: %d valid pixels out of %zu", validPixels, m_texelPatchID.size()); 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; return true;
} }