微调色差
This commit is contained in:
1 parent
d442e213d7
commit
dbbcb4d557
1 file changed
+87
-51
+87
-51
@@ -8911,50 +8911,50 @@ void MeshTexture::CreateSeamVertices()
|
||||
DEBUG_EXTRA(" patch stats: single(patches<2)=%zu, multi(>=2)=%zu, maxPatches=%zu",
|
||||
svSingle, svMulti, svMaxPatches);
|
||||
|
||||
// ★★★ 截断 seamVertices 到合理规模(原版 OpenMVS 通常 < 50000)★★★
|
||||
// 按 patches 数量排序,保留最重要的(patches 多的 = 色差严重的接缝)
|
||||
const size_t MAX_SEAM_VERTICES = 40000; // ← 可调,先试 40000
|
||||
if (seamVertices.GetSize() > MAX_SEAM_VERTICES) {
|
||||
DEBUG_EXTRA(" Truncating seamVertices: %u -> %zu (keeping highest patch-count)",
|
||||
seamVertices.GetSize(), MAX_SEAM_VERTICES);
|
||||
// // ★★★ 截断 seamVertices 到合理规模(原版 OpenMVS 通常 < 50000)★★★
|
||||
// // 按 patches 数量排序,保留最重要的(patches 多的 = 色差严重的接缝)
|
||||
// const size_t MAX_SEAM_VERTICES = 40000; // ← 可调,先试 40000
|
||||
// if (seamVertices.GetSize() > MAX_SEAM_VERTICES) {
|
||||
// DEBUG_EXTRA(" Truncating seamVertices: %u -> %zu (keeping highest patch-count)",
|
||||
// seamVertices.GetSize(), MAX_SEAM_VERTICES);
|
||||
|
||||
// 建 (索引, patch数量) 对,按 patch 数量降序
|
||||
std::vector<std::pair<uint32_t, size_t>> idxAndCount(seamVertices.GetSize());
|
||||
for (uint32_t i = 0; i < seamVertices.GetSize(); ++i)
|
||||
idxAndCount[i] = {i, seamVertices[i].patches.size()};
|
||||
std::sort(idxAndCount.begin(), idxAndCount.end(),
|
||||
[](const auto& a, const auto& b) { return a.second > b.second; });
|
||||
// // 建 (索引, patch数量) 对,按 patch 数量降序
|
||||
// std::vector<std::pair<uint32_t, size_t>> idxAndCount(seamVertices.GetSize());
|
||||
// for (uint32_t i = 0; i < seamVertices.GetSize(); ++i)
|
||||
// idxAndCount[i] = {i, seamVertices[i].patches.size()};
|
||||
// std::sort(idxAndCount.begin(), idxAndCount.end(),
|
||||
// [](const auto& a, const auto& b) { return a.second > b.second; });
|
||||
|
||||
// 选前 MAX_SEAM_VERTICES 个索引,排序回原始顺序以保持稳定性
|
||||
std::vector<uint32_t> keep(idxAndCount.size());
|
||||
for (size_t i = 0; i < MAX_SEAM_VERTICES; ++i) keep[i] = idxAndCount[i].first;
|
||||
std::sort(keep.begin(), keep.begin() + MAX_SEAM_VERTICES);
|
||||
// // 选前 MAX_SEAM_VERTICES 个索引,排序回原始顺序以保持稳定性
|
||||
// std::vector<uint32_t> keep(idxAndCount.size());
|
||||
// for (size_t i = 0; i < MAX_SEAM_VERTICES; ++i) keep[i] = idxAndCount[i].first;
|
||||
// std::sort(keep.begin(), keep.begin() + MAX_SEAM_VERTICES);
|
||||
|
||||
// 重建 seamVertices(只保留选中的)
|
||||
decltype(seamVertices) newSV;
|
||||
newSV.Reserve(MAX_SEAM_VERTICES);
|
||||
std::unordered_map<uint32_t, uint32_t> old2new; // 旧索引 → 新索引
|
||||
for (size_t i = 0; i < MAX_SEAM_VERTICES; ++i) {
|
||||
const uint32_t oldIdx = keep[i];
|
||||
old2new[oldIdx] = (uint32_t)newSV.GetSize();
|
||||
newSV.push_back(std::move(seamVertices[oldIdx]));
|
||||
}
|
||||
// // 重建 seamVertices(只保留选中的)
|
||||
// decltype(seamVertices) newSV;
|
||||
// newSV.Reserve(MAX_SEAM_VERTICES);
|
||||
// std::unordered_map<uint32_t, uint32_t> old2new; // 旧索引 → 新索引
|
||||
// for (size_t i = 0; i < MAX_SEAM_VERTICES; ++i) {
|
||||
// const uint32_t oldIdx = keep[i];
|
||||
// old2new[oldIdx] = (uint32_t)newSV.GetSize();
|
||||
// newSV.push_back(std::move(seamVertices[oldIdx]));
|
||||
// }
|
||||
|
||||
// ★★★ 关键:更新所有 Patch::edges 里的 idxSeamVertex 引用 ★★★
|
||||
for (uint32_t i = 0; i < newSV.GetSize(); ++i) {
|
||||
for (auto& patch : newSV[i].patches) {
|
||||
for (auto& edge : patch.edges) {
|
||||
auto it = old2new.find(edge.idxSeamVertex);
|
||||
if (it != old2new.end())
|
||||
edge.idxSeamVertex = it->second;
|
||||
else
|
||||
edge.idxSeamVertex = i; // 指向自己(会被忽略)
|
||||
}
|
||||
}
|
||||
}
|
||||
seamVertices = std::move(newSV);
|
||||
DEBUG_EXTRA(" Truncated seamVertices: %u final", seamVertices.GetSize());
|
||||
}
|
||||
// // ★★★ 关键:更新所有 Patch::edges 里的 idxSeamVertex 引用 ★★★
|
||||
// for (uint32_t i = 0; i < newSV.GetSize(); ++i) {
|
||||
// for (auto& patch : newSV[i].patches) {
|
||||
// for (auto& edge : patch.edges) {
|
||||
// auto it = old2new.find(edge.idxSeamVertex);
|
||||
// if (it != old2new.end())
|
||||
// edge.idxSeamVertex = it->second;
|
||||
// else
|
||||
// edge.idxSeamVertex = i; // 指向自己(会被忽略)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// seamVertices = std::move(newSV);
|
||||
// DEBUG_EXTRA(" Truncated seamVertices: %u final", seamVertices.GetSize());
|
||||
// }
|
||||
}
|
||||
|
||||
// Native
|
||||
@@ -9462,8 +9462,9 @@ void MeshTexture::GlobalSeamLeveling4()
|
||||
const float r = x(v * 3 + 0);
|
||||
const float g = x(v * 3 + 1);
|
||||
const float b_ch = x(v * 3 + 2);
|
||||
const float mean = (r + g + b_ch) / 3.0f; // 去均值
|
||||
colorAdjustments[v] = Color(r - mean, g - mean, b_ch - mean);
|
||||
const float mean = (r + g + b_ch) / 3.0f;
|
||||
// colorAdjustments[v] = Color(r, g, b_ch);
|
||||
colorAdjustments[v] = Color(r - mean, g - mean, b_ch - mean);
|
||||
}
|
||||
} else {
|
||||
DEBUG_EXTRA("WARN: solve not successful, using zero adjustments");
|
||||
@@ -9513,22 +9514,28 @@ void MeshTexture::GlobalSeamLeveling4()
|
||||
if (idxFace >= faces.GetSize()) continue;
|
||||
const Face& face = faces[idxFace];
|
||||
|
||||
// ★ 检查 faceTexcoords 访问
|
||||
ASSERT(idxFace * 3 + 2 < faceTexcoords.GetSize());
|
||||
|
||||
// ★ 检查 face[v] 不越界
|
||||
ASSERT(idxFace * 3 + 2 < faceTexcoords.GetSize());
|
||||
for (int v = 0; v < 3; ++v) {
|
||||
ASSERT(face[v] < vertices.size());
|
||||
ASSERT(face[v] < vertpatch2rows.size());
|
||||
}
|
||||
|
||||
data.tri = faceTexcoords.Begin() + idxFace * 3;
|
||||
// ★ UV [0,1] → patch 局部像素坐标
|
||||
const cv::Size patchSize = texturePatch.rect.size();
|
||||
TexCoord localTri[3];
|
||||
const TexCoord* uvTri = faceTexcoords.Begin() + idxFace * 3;
|
||||
for (int v = 0; v < 3; ++v) {
|
||||
ASSERT(face[v] < vertices.size()); // ★ 加这行
|
||||
localTri[v] = TexCoord(uvTri[v].x * patchSize.width,
|
||||
uvTri[v].y * patchSize.height);
|
||||
}
|
||||
data.tri = localTri;
|
||||
|
||||
for (int v = 0; v < 3; ++v) {
|
||||
ASSERT(face[v] < vertices.size());
|
||||
auto search = vertpatch2rows[face[v]].find(idxPatch);
|
||||
if (search != vertpatch2rows[face[v]].end())
|
||||
{
|
||||
ASSERT(search->second < (Eigen::Index)colorAdjustments.size()); // ★ 关键
|
||||
ASSERT(search->second < (Eigen::Index)colorAdjustments.size());
|
||||
data.colors[v] = colorAdjustments[search->second];
|
||||
}
|
||||
else
|
||||
@@ -9536,8 +9543,7 @@ void MeshTexture::GlobalSeamLeveling4()
|
||||
}
|
||||
ColorMap::RasterizeTriangleBary(data.tri[0], data.tri[1], data.tri[2], data);
|
||||
}
|
||||
|
||||
imageAdj.DilateMean<1>(imageAdj, Color::ZERO);
|
||||
imageAdj.DilateMean<5>(imageAdj, Color::ZERO);
|
||||
|
||||
// ★ 把修正叠加到 outPatch(从 srcROI 读原始颜色)
|
||||
for (int r = 0; r < srcROI.rows; ++r) {
|
||||
@@ -15568,6 +15574,14 @@ void MeshTexture::ApplyGlobalSeamLevelingOnRCPatches(
|
||||
(int)(atlas.rows * atlas.step));
|
||||
DEBUG_EXTRA("expected: %d x %d x 3 = %d bytes",
|
||||
textureSize, textureSize, textureSize * textureSize * 3);
|
||||
|
||||
for (int i = 0; i < std::min(3, (int)images.size()); ++i) {
|
||||
char dbgName[256];
|
||||
sprintf(dbgName, "debug_image_%d_after_gsl4.png", i);
|
||||
cv::imwrite(dbgName, images[i].image); // ← 用 .image
|
||||
}
|
||||
DEBUG_EXTRA("Exported debug images after GSL4");
|
||||
|
||||
// ========== 3. 重光栅化(从已被 GSL4 修正的 images 读)==========
|
||||
ASSERT(atlas.rows == textureSize && atlas.cols == textureSize);
|
||||
for (int pi = 0; pi < (int)rcPatches.size(); ++pi) {
|
||||
@@ -15583,6 +15597,20 @@ void MeshTexture::ApplyGlobalSeamLevelingOnRCPatches(
|
||||
// cv::Mat correctedPatch = srcImg.image(tp.rect).clone();
|
||||
cv::Mat correctedPatch = correctedPatchImages[rcToTexPatch[pi]].clone(); // 局部拷贝
|
||||
|
||||
// 加上严格检查
|
||||
static int cnt = 0;
|
||||
if (cnt < 5) {
|
||||
DEBUG_EXTRA("Patch %d: rcToTexPatch=%d, correctedPatch empty=%d, size=(%dx%d), type=%d",
|
||||
cnt, rcToTexPatch[pi], correctedPatch.empty(),
|
||||
correctedPatch.cols, correctedPatch.rows, correctedPatch.type());
|
||||
|
||||
if (!correctedPatch.empty()) {
|
||||
char nm[256]; sprintf(nm, "debug_corrected_patch_%d.png", cnt);
|
||||
cv::imwrite(nm, correctedPatch);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (correctedPatch.empty()) continue;
|
||||
|
||||
const RCPatch& rp = rcPatches[pi];
|
||||
@@ -15616,6 +15644,7 @@ void MeshTexture::ApplyGlobalSeamLevelingOnRCPatches(
|
||||
cv::remap(correctedPatch, remapped, mapX, mapY, cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0,0,0));
|
||||
|
||||
for (int y = 0; y < patchH; ++y)
|
||||
{
|
||||
for (int x = 0; x < patchW; ++x) {
|
||||
cv::Vec3b color = remapped.at<cv::Vec3b>(y, x);
|
||||
if (color[0] < 5 && color[1] < 5 && color[2] < 5) continue;
|
||||
@@ -15630,8 +15659,15 @@ void MeshTexture::ApplyGlobalSeamLevelingOnRCPatches(
|
||||
pixel[2] = color[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
atlas = localAtlas;
|
||||
// // 调试用:导出调整后的 atlas
|
||||
// static int dbgCount = 0;
|
||||
// char dbgName[256];
|
||||
// sprintf(dbgName, "debug_atlas_after_gsl4_%d.png", dbgCount++);
|
||||
// cv::imwrite(dbgName, atlas);
|
||||
// DEBUG_EXTRA("Exported %s", dbgName);
|
||||
}
|
||||
}
|
||||
DEBUG_EXTRA("Re-rasterization done.");
|
||||
|
||||
Reference in new issue
Block a user