Browse Source

处理编译问题

ManualUV
hesuicong 3 weeks ago
parent
commit
c9d1eac96a
  1. 678
      libs/MVS/SceneTexture.cpp

678
libs/MVS/SceneTexture.cpp

@ -10231,7 +10231,92 @@ bool MeshTexture::PackTextureAtlases(
return true; return true;
} }
cv::Rect MeshTexture::ComputeOptimalPatchBounds(const AABB2f& aabb, const cv::Size& imageSize, int border) {
DEBUG_EXTRA("Computing optimal patch bounds for AABB, image: %dx%d, border: %d",
imageSize.width, imageSize.height, border);
// 检查输入参数的有效性
if (imageSize.width <= 0 || imageSize.height <= 0) {
DEBUG_EXTRA("Error: Invalid image size: %dx%d", imageSize.width, imageSize.height);
return cv::Rect(0, 0, 0, 0);
}
if (border < 0) {
border = 0;
}
// 步骤1: 获取AABB的边界值
float x1, y1, x2, y2;
// 确保aabb是有效的
if (aabb.ptMin.x() >= aabb.ptMax.x() || aabb.ptMin.y() >= aabb.ptMax.y()) {
DEBUG_EXTRA("Error: Invalid AABB");
return cv::Rect(0, 0, 0, 0);
}
x1 = aabb.ptMin.x();
y1 = aabb.ptMin.y();
x2 = aabb.ptMax.x();
y2 = aabb.ptMax.y();
DEBUG_EXTRA("AABB bounds: [%f, %f] - [%f, %f]", x1, y1, x2, y2);
// 步骤2: 计算基本边界(包含边距)
float minX = x1 - border;
float minY = y1 - border;
float maxX = x2 + border;
float maxY = y2 + border;
// 步骤3: 确保边界不超出图像范围
minX = std::max(0.0f, minX);
minY = std::max(0.0f, minY);
maxX = std::min(static_cast<float>(imageSize.width) - 1.0f, maxX);
maxY = std::min(static_cast<float>(imageSize.height) - 1.0f, maxY);
// 检查边界是否有效
if (minX >= maxX || minY >= maxY) {
DEBUG_EXTRA("Warning: Invalid bounds after clamping: [%f, %f] - [%f, %f]",
minX, minY, maxX, maxY);
// 返回一个最小边界
int x = static_cast<int>(std::floor(x1));
int y = static_cast<int>(std::floor(y1));
x = std::max(0, std::min(x, imageSize.width - 1));
y = std::max(0, std::min(y, imageSize.height - 1));
return cv::Rect(x, y, 1, 1);
}
// 步骤4: 对齐到整数像素坐标
int x = static_cast<int>(std::floor(minX));
int y = static_cast<int>(std::floor(minY));
int width = static_cast<int>(std::ceil(maxX)) - x;
int height = static_cast<int>(std::ceil(maxY)) - y;
// 确保最小尺寸
width = std::max(1, width);
height = std::max(1, height);
// 确保不超出图像范围
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= imageSize.width) x = imageSize.width - 1;
if (y >= imageSize.height) y = imageSize.height - 1;
if (x + width > imageSize.width) {
width = imageSize.width - x;
}
if (y + height > imageSize.height) {
height = imageSize.height - y;
}
// 最终验证
width = std::max(1, width);
height = std::max(1, height);
cv::Rect result(x, y, width, height);
DEBUG_EXTRA("Optimal patch bounds computed: [%d, %d, %d, %d]",
result.x, result.y, result.width, result.height);
return result;
}
// 主要改进的纹理映射函数 // 主要改进的纹理映射函数
bool MeshTexture::GenerateTextureWithViewConsistency( bool MeshTexture::GenerateTextureWithViewConsistency(
bool bGlobalSeamLeveling, bool bLocalSeamLeveling, bool bGlobalSeamLeveling, bool bLocalSeamLeveling,
@ -10243,55 +10328,149 @@ bool MeshTexture::GenerateTextureWithViewConsistency(
TD_TIMER_START(); TD_TIMER_START();
const int border = (bOriginFaceview) ? 2 : 4; const int border = (bOriginFaceview) ? 2 : 4;
const int minPatchSize = 50; // 最小纹理块大小 const int minPatchSize = 50;
// 1. 创建视图一致性映射 // 1. 创建视图一致性映射
std::vector<ViewSelectionData> faceViewData(faces.size()); std::vector<ViewSelectionData> faceViewData(faces.size());
std::vector<int> patchAssignments(faces.size(), -1); std::vector<int> patchAssignments(faces.size(), -1);
// 2. 为每个面选择最佳视图(考虑相邻面一致性) // 2. 为每个面选择最佳视图
SelectOptimalViewsWithConsistency(faceViewData, minPatchSize); SelectOptimalViewsWithConsistency(faceViewData, minPatchSize);
// 3. 基于视图一致性创建纹理块 // 3. 基于视图一致性创建纹理块
CreateConsistentTexturePatches(faceViewData, patchAssignments, minPatchSize); CreateConsistentTexturePatches(faceViewData, patchAssignments, minPatchSize);
DEBUG_EXTRA("Created %zu texture patches", texturePatches.size());
// 检查纹理块是否有效
if (texturePatches.IsEmpty()) {
DEBUG_EXTRA("Error: No texture patches created");
return false;
}
// 4. 生成纹理坐标 // 4. 生成纹理坐标
Mesh::TexCoordArr faceTexcoords2(faces.size() * 3); Mesh::TexCoordArr faceTexcoords2(faces.size() * 3);
Mesh::TexIndexArr faceTexindices2(faces.size()); Mesh::TexIndexArr faceTexindices2(faces.size());
#ifdef TEXOPT_USE_OPENMP DEBUG_EXTRA("Processing %zu texture patches", texturePatches.size());
#pragma omp parallel for schedule(dynamic)
for (int_t idx = 0; idx < (int_t)texturePatches.size() - 1; ++idx) { // 计算需要处理的纹理块数量
#else size_t numPatchesToProcess = texturePatches.size();
for (uint32_t idx = 0; idx < texturePatches.size() - 1; ++idx) { if (!texturePatches.empty() && texturePatches.back().label == NO_ID) {
#endif numPatchesToProcess = texturePatches.size() - 1;
}
DEBUG_EXTRA("Processing %zu valid texture patches", numPatchesToProcess);
// 处理有效纹理块
for (size_t idx = 0; idx < numPatchesToProcess; ++idx) {
TexturePatch& texturePatch = texturePatches[idx]; TexturePatch& texturePatch = texturePatches[idx];
// 检查纹理块是否有效
if (texturePatch.faces.IsEmpty()) {
DEBUG_EXTRA("Warning: Texture patch %zu is empty", idx);
continue;
}
// 检查视图ID是否有效
if (texturePatch.label < 0 || texturePatch.label >= (int)images.size()) {
DEBUG_EXTRA("Warning: Texture patch %zu has invalid label: %d", idx, texturePatch.label);
continue;
}
const Image& imageData = images[texturePatch.label]; const Image& imageData = images[texturePatch.label];
// 检查图像是否有效
if (imageData.image.empty()) {
DEBUG_EXTRA("Warning: Image for patch %zu is empty", idx);
continue;
}
AABB2f aabb(true); AABB2f aabb(true);
// 计算纹理块的UV边界 // 计算纹理块的UV边界
bool validAABB = false;
for (const FIndex idxFace : texturePatch.faces) { for (const FIndex idxFace : texturePatch.faces) {
if (idxFace >= faces.size()) {
DEBUG_EXTRA("Warning: Invalid face index in patch %zu: %u", idx, idxFace);
continue;
}
const Face& face = faces[idxFace]; const Face& face = faces[idxFace];
TexCoord* texcoords = faceTexcoords2.data() + idxFace * 3; TexCoord* texcoords = faceTexcoords2.data() + idxFace * 3;
bool faceValid = true;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
if (face[i] >= vertices.size()) {
DEBUG_EXTRA("Warning: Invalid vertex index in face %u", idxFace);
faceValid = false;
break;
}
texcoords[i] = imageData.camera.ProjectPointP(vertices[face[i]]); texcoords[i] = imageData.camera.ProjectPointP(vertices[face[i]]);
ASSERT(imageData.image.isInsideWithBorder(texcoords[i], border));
// 检查纹理坐标是否在图像边界内
if (!imageData.image.isInsideWithBorder(texcoords[i], border)) {
float border_f = static_cast<float>(border);
float imgWidth = static_cast<float>(imageData.image.width());
float imgHeight = static_cast<float>(imageData.image.height());
texcoords[i].x = std::max(border_f, std::min(texcoords[i].x, imgWidth - border_f - 1.0f));
texcoords[i].y = std::max(border_f, std::min(texcoords[i].y, imgHeight - border_f - 1.0f));
}
aabb.InsertFull(texcoords[i]); aabb.InsertFull(texcoords[i]);
} }
if (faceValid) {
validAABB = true;
}
}
if (!validAABB) {
DEBUG_EXTRA("Warning: Texture patch %zu has no valid faces", idx);
texturePatch.rect = cv::Rect(0, 0, 1, 1);
continue;
} }
// 设置纹理块边界 // 设置纹理块边界
texturePatch.rect = ComputeOptimalPatchBounds(aabb, imageData.image.size(), border); cv::Rect patchRect = ComputeOptimalPatchBounds(aabb, imageData.image.size(), border);
// 检查边界是否有效
if (patchRect.width <= 0 || patchRect.height <= 0 ||
patchRect.x < 0 || patchRect.y < 0 ||
patchRect.x + patchRect.width > imageData.image.width() ||
patchRect.y + patchRect.height > imageData.image.height()) {
DEBUG_EXTRA("Warning: Invalid rect for patch %zu: [%d, %d, %d, %d]", idx,
patchRect.x, patchRect.y, patchRect.width, patchRect.height);
// 设置一个安全的边界
int safeX = std::max(0, patchRect.x);
int safeY = std::max(0, patchRect.y);
int safeWidth = std::max(1, std::min(imageData.image.width() - safeX, patchRect.width));
int safeHeight = std::max(1, std::min(imageData.image.height() - safeY, patchRect.height));
patchRect = cv::Rect(safeX, safeY, safeWidth, safeHeight);
}
texturePatch.rect = patchRect;
DEBUG_EXTRA("Patch %zu bounds: [%d, %d, %d, %d]", idx,
patchRect.x, patchRect.y, patchRect.width, patchRect.height);
} }
// 5. 处理剩余的"无效视图"面(分配到默认纹理块) // 5. 处理无效视图纹理块
if (!texturePatches.empty() && texturePatches.back().label == NO_ID) { if (!texturePatches.empty() && texturePatches.back().label == NO_ID) {
DEBUG_EXTRA("Processing invalid view patch");
TexturePatch& texturePatch = texturePatches.back(); TexturePatch& texturePatch = texturePatches.back();
const int sizePatch = border * 2 + 1; const int sizePatch = border * 2 + 1;
texturePatch.rect = cv::Rect(0, 0, sizePatch, sizePatch); texturePatch.rect = cv::Rect(0, 0, sizePatch, sizePatch);
for (const FIndex idxFace : texturePatch.faces) { for (const FIndex idxFace : texturePatch.faces) {
if (idxFace >= faces.size()) {
DEBUG_EXTRA("Warning: Invalid face index in invalid patch: %u", idxFace);
continue;
}
TexCoord* texcoords = faceTexcoords2.data() + idxFace * 3; TexCoord* texcoords = faceTexcoords2.data() + idxFace * 3;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
texcoords[i] = TexCoord(0.5f, 0.5f); texcoords[i] = TexCoord(0.5f, 0.5f);
@ -10301,39 +10480,45 @@ bool MeshTexture::GenerateTextureWithViewConsistency(
// 6. 执行接缝均衡 // 6. 执行接缝均衡
if (texturePatches.size() > 2) { if (texturePatches.size() > 2) {
DEBUG_EXTRA("Creating seam vertices");
CreateSeamVertices(); CreateSeamVertices();
if (bGlobalSeamLeveling) { if (bGlobalSeamLeveling) {
DEBUG_EXTRA("Starting global seam leveling");
GlobalSeamLevelingEnhanced(); GlobalSeamLevelingEnhanced();
} }
if (bLocalSeamLeveling) { if (bLocalSeamLeveling) {
DEBUG_EXTRA("Starting local seam leveling");
LocalSeamLevelingEnhanced(); LocalSeamLevelingEnhanced();
} }
} }
// 7. 合并重叠的纹理块 // 7. 合并重叠的纹理块
DEBUG_EXTRA("Merging overlapping patches");
MergeOverlappingPatches(faceTexcoords2); MergeOverlappingPatches(faceTexcoords2);
// 8. 打包纹理块 // 8. 打包纹理块
DEBUG_EXTRA("Packing texture atlases");
std::vector<Image8U3> generatedTextures; std::vector<Image8U3> generatedTextures;
// 修正:使用正确的函数名和参数
// 在 OpenMVS 中,纹理打包通常使用 PackTextureAtlases
PackTextureAtlases(faceTexcoords2, faceTexindices2, generatedTextures, PackTextureAtlases(faceTexcoords2, faceTexindices2, generatedTextures,
nTextureSizeMultiple, nRectPackingHeuristic, nTextureSizeMultiple, nRectPackingHeuristic,
colEmpty, maxTextureSize); colEmpty, maxTextureSize);
// 9. 高质量纹理采样 // 9. 高质量纹理采样
DEBUG_EXTRA("Generating high-quality texture");
GenerateHighQualityTexture(generatedTextures, faceTexcoords2, faceTexindices2, GenerateHighQualityTexture(generatedTextures, faceTexcoords2, faceTexindices2,
fSharpnessWeight, colEmpty); fSharpnessWeight, colEmpty);
// 10. 应用纹理锐化 // 10. 应用纹理锐化
if (fSharpnessWeight > 0) { if (fSharpnessWeight > 0) {
DEBUG_EXTRA("Applying adaptive sharpening");
ApplyAdaptiveSharpening(generatedTextures, fSharpnessWeight); ApplyAdaptiveSharpening(generatedTextures, fSharpnessWeight);
} }
// 11. 填充空洞 // 11. 填充空洞
DEBUG_EXTRA("Filling texture holes");
FillTextureHoles(generatedTextures, colEmpty); FillTextureHoles(generatedTextures, colEmpty);
// 12. 保存结果 // 12. 保存结果
@ -10565,7 +10750,6 @@ void MeshTexture::SelectOptimalViewsWithConsistency(
DEBUG_EXTRA("View selection with consistency completed"); DEBUG_EXTRA("View selection with consistency completed");
} }
// 创建一致性纹理块 // 创建一致性纹理块
void MeshTexture::CreateConsistentTexturePatches( void MeshTexture::CreateConsistentTexturePatches(
const std::vector<ViewSelectionData>& faceViewData, const std::vector<ViewSelectionData>& faceViewData,
@ -10574,10 +10758,28 @@ void MeshTexture::CreateConsistentTexturePatches(
{ {
DEBUG_EXTRA("Creating consistent texture patches"); DEBUG_EXTRA("Creating consistent texture patches");
const int numFaces = faces.size(); const int numFaces = static_cast<int>(faces.size());
std::vector<bool> visited(numFaces, false); std::vector<bool> visited(numFaces, false);
int patchCounter = 0; int patchCounter = 0;
// 清空现有的纹理块
texturePatches.clear();
// 步骤0: 构建边到面的映射
std::unordered_map<uint64_t, std::vector<FIndex>> edgeToFaceMap;
for (int fid = 0; fid < numFaces; ++fid) {
const Face& face = faces[fid];
for (int i = 0; i < 3; ++i) {
VIndex v0 = face[i];
VIndex v1 = face[(i + 1) % 3];
if (v0 > v1) std::swap(v0, v1);
uint64_t edgeKey = (static_cast<uint64_t>(v0) << 32) | v1;
edgeToFaceMap[edgeKey].push_back(static_cast<FIndex>(fid));
}
}
// 步骤1: 创建基于视图的纹理块 // 步骤1: 创建基于视图的纹理块
std::vector<std::vector<FIndex>> patchFaces; std::vector<std::vector<FIndex>> patchFaces;
@ -10597,24 +10799,29 @@ void MeshTexture::CreateConsistentTexturePatches(
int fid = faceQueue.front(); int fid = faceQueue.front();
faceQueue.pop(); faceQueue.pop();
currentPatch.push_back(fid); currentPatch.push_back(static_cast<FIndex>(fid));
patchAssignments[fid] = patchCounter; patchAssignments[fid] = patchCounter;
const Face& face = faces[fid]; const Face& face = faces[fid];
// 查找相同视图的相邻面 // 查找相同视图的相邻面
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
const VIndex idxV0 = face[i]; VIndex idxV0 = face[i];
const VIndex idxV1 = face[(i + 1) % 3]; VIndex idxV1 = face[(i + 1) % 3];
const Edge edge = mesh.EdgeFromVertices(idxV0, idxV1);
if (edge != NO_ID) { if (idxV0 > idxV1) std::swap(idxV0, idxV1);
const FaceIdxArr& facePairs = mesh.edgeFaces[edge]; uint64_t edgeKey = (static_cast<uint64_t>(idxV0) << 32) | idxV1;
for (FIndex neighborFid : facePairs) {
if (!visited[neighborFid] && auto it = edgeToFaceMap.find(edgeKey);
faceViewData[neighborFid].viewID == viewID) { if (it != edgeToFaceMap.end()) {
visited[neighborFid] = true; for (FIndex neighborFid : it->second) {
faceQueue.push(neighborFid); int nfid = static_cast<int>(neighborFid);
if (nfid == fid) continue;
if (visited[nfid]) continue;
if (faceViewData[nfid].viewID == viewID) {
visited[nfid] = true;
faceQueue.push(nfid);
} }
} }
} }
@ -10622,18 +10829,20 @@ void MeshTexture::CreateConsistentTexturePatches(
} }
// 只保留足够大的纹理块 // 只保留足够大的纹理块
if (currentPatch.size() >= minPatchSize) { if (static_cast<int>(currentPatch.size()) >= minPatchSize) {
patchFaces.push_back(std::move(currentPatch)); patchFaces.push_back(std::move(currentPatch));
patchCounter++; patchCounter++;
} else { } else {
// 小纹理块重新标记为未分配 // 小纹理块重新标记为未分配
for (FIndex fid : currentPatch) { for (FIndex fid : currentPatch) {
patchAssignments[fid] = -1; patchAssignments[static_cast<int>(fid)] = -1;
} }
} }
} }
// 步骤2: 处理未分配的面(分配到最近的纹理块) DEBUG_EXTRA("Initial patch creation: %zu patches", patchFaces.size());
// 步骤2: 处理未分配的面
std::vector<int> unassignedFaces; std::vector<int> unassignedFaces;
for (int fid = 0; fid < numFaces; ++fid) { for (int fid = 0; fid < numFaces; ++fid) {
if (patchAssignments[fid] == -1 && faceViewData[fid].viewID != -1) { if (patchAssignments[fid] == -1 && faceViewData[fid].viewID != -1) {
@ -10641,43 +10850,100 @@ void MeshTexture::CreateConsistentTexturePatches(
} }
} }
#pragma omp parallel for schedule(dynamic) DEBUG_EXTRA("Found %zu unassigned faces", unassignedFaces.size());
for (int idx = 0; idx < unassignedFaces.size(); ++idx) {
int fid = unassignedFaces[idx]; if (!unassignedFaces.empty()) {
int bestPatch = -1; // 构建相邻面映射
float bestDistance = FLT_MAX; std::vector<std::vector<int>> faceNeighbors(numFaces);
for (int fid = 0; fid < numFaces; ++fid) {
const Face& face = faces[fid];
for (int i = 0; i < 3; ++i) {
VIndex idxV0 = face[i];
VIndex idxV1 = face[(i + 1) % 3];
if (idxV0 > idxV1) std::swap(idxV0, idxV1);
uint64_t edgeKey = (static_cast<uint64_t>(idxV0) << 32) | idxV1;
auto it = edgeToFaceMap.find(edgeKey);
if (it != edgeToFaceMap.end()) {
for (FIndex neighborFid : it->second) {
int nfid = static_cast<int>(neighborFid);
if (nfid != fid) {
faceNeighbors[fid].push_back(nfid);
}
}
}
}
}
// 为未分配的面找到最近的纹理块
std::vector<int> faceDistances(numFaces, -1);
std::queue<int> bfsQueue;
// 初始化BFS
for (int fid = 0; fid < numFaces; ++fid) {
if (patchAssignments[fid] != -1) {
bfsQueue.push(fid);
faceDistances[fid] = 0;
}
}
// 执行BFS
std::vector<std::pair<int, int>> assignments;
for (int patchID = 0; patchID < patchFaces.size(); ++patchID) { while (!bfsQueue.empty()) {
if (patchFaces[patchID].empty()) continue; int fid = bfsQueue.front();
bfsQueue.pop();
// 查找最近的已分配面 int currentPatch = patchAssignments[fid];
for (FIndex assignedFid : patchFaces[patchID]) { int currentDist = faceDistances[fid];
float distance = ComputeFaceDistance(fid, assignedFid);
if (distance < bestDistance) { for (int neighborFid : faceNeighbors[fid]) {
bestDistance = distance; if (faceDistances[neighborFid] == -1) {
bestPatch = patchID; faceDistances[neighborFid] = currentDist + 1;
bfsQueue.push(neighborFid);
if (patchAssignments[neighborFid] == -1) {
assignments.push_back(std::make_pair(neighborFid, currentPatch));
}
} }
} }
} }
if (bestPatch != -1) { // 处理分配
patchAssignments[fid] = bestPatch; for (const auto& assignment : assignments) {
patchFaces[bestPatch].push_back(fid); int fid = assignment.first;
int patchID = assignment.second;
patchAssignments[fid] = patchID;
patchFaces[patchID].push_back(static_cast<FIndex>(fid));
} }
} }
// 步骤3: 创建纹理块 // 步骤3: 创建纹理块
texturePatches.Resize(patchFaces.size() + 1); // +1 用于无效面 texturePatches.Resize(patchFaces.size() + 1); // +1 用于无效面
#pragma omp parallel for schedule(static) DEBUG_EXTRA("Allocated %zu texture patches", texturePatches.size());
for (int patchID = 0; patchID < patchFaces.size(); ++patchID) {
for (size_t patchID = 0; patchID < patchFaces.size(); ++patchID) {
TexturePatch& patch = texturePatches[patchID]; TexturePatch& patch = texturePatches[patchID];
patch.faces = patchFaces[patchID];
// 确定纹理块的视图(取最常见的视图) // 检查patchFaces是否为空
if (patchFaces[patchID].empty()) {
DEBUG_EXTRA("Warning: Patch %zu is empty", patchID);
continue;
}
// 复制面索引
patch.faces.Resize(patchFaces[patchID].size());
for (size_t i = 0; i < patchFaces[patchID].size(); ++i) {
patch.faces[i] = patchFaces[patchID][i];
}
// 确定纹理块的视图
std::unordered_map<int, int> viewCounts; std::unordered_map<int, int> viewCounts;
for (FIndex fid : patch.faces) { for (FIndex fid : patch.faces) {
int viewID = faceViewData[fid].viewID; int viewID = faceViewData[static_cast<int>(fid)].viewID;
if (viewID != -1) { if (viewID != -1) {
viewCounts[viewID]++; viewCounts[viewID]++;
} }
@ -10693,16 +10959,26 @@ void MeshTexture::CreateConsistentTexturePatches(
} }
patch.label = dominantView; patch.label = dominantView;
DEBUG_EXTRA("Patch %zu: %zu faces, label: %d",
patchID, patch.faces.size(), patch.label);
} }
// 步骤4: 创建无效面纹理块 // 步骤4: 创建无效面纹理块
TexturePatch& invalidPatch = texturePatches.back(); if (!texturePatches.empty()) {
invalidPatch.label = NO_ID; TexturePatch& invalidPatch = texturePatches.back();
for (int fid = 0; fid < numFaces; ++fid) { invalidPatch.label = NO_ID;
if (faceViewData[fid].viewID == -1) { invalidPatch.faces.Resize(0);
invalidPatch.faces.Insert(fid);
for (int fid = 0; fid < numFaces; ++fid) {
if (faceViewData[fid].viewID == -1) {
invalidPatch.faces.Insert(static_cast<FIndex>(fid));
}
} }
DEBUG_EXTRA("Invalid patch: %zu faces", invalidPatch.faces.size());
} }
DEBUG_EXTRA("Created %zu texture patches", texturePatches.size());
} }
// 高质量纹理生成 // 高质量纹理生成
@ -11006,7 +11282,7 @@ float MeshTexture::ComputeFaceDistance(FIndex fid1, FIndex fid2)
Point3f diff = center2 - center1; Point3f diff = center2 - center1;
return std::sqrt(diff.x * diff.x + diff.y * diff.y + diff.z * diff.z); return std::sqrt(diff.x * diff.x + diff.y * diff.y + diff.z * diff.z);
} }
// 判断面是否在视图中可见
// 判断面是否在视图中可见 // 判断面是否在视图中可见
bool MeshTexture::IsFaceVisibleFromView(FIndex idxFace, int viewID) bool MeshTexture::IsFaceVisibleFromView(FIndex idxFace, int viewID)
{ {
@ -11021,8 +11297,15 @@ bool MeshTexture::IsFaceVisibleFromView(FIndex idxFace, int viewID)
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
const cv::Point3f& vertex = vertices[face[i]]; const cv::Point3f& vertex = vertices[face[i]];
// 投影到图像平面 // 将cv::Point3f转换为OpenMVS的Point3类型
Point2f proj = imageData.camera.ProjectPointP(vertex); // Camera类使用double精度,但ProjectPointP是模板函数,支持多种类型
cv::Point3d vertex3d(static_cast<double>(vertex.x),
static_cast<double>(vertex.y),
static_cast<double>(vertex.z));
// 使用正确的ProjectPointP函数
// 从Camera头文件可以看到ProjectPointP返回TPoint2<TYPE>
cv::Point2d proj = imageData.camera.ProjectPointP<double>(vertex3d);
// 检查是否在图像范围内(添加边界容差) // 检查是否在图像范围内(添加边界容差)
const float border = 5.0f; const float border = 5.0f;
@ -11031,39 +11314,40 @@ bool MeshTexture::IsFaceVisibleFromView(FIndex idxFace, int viewID)
return false; return false;
} }
// 检查深度(如果需要) // 可选:检查深度(点在相机前方)
// 这里可以添加深度测试逻辑 // 可以使用camera.PointDepth函数
double depth = imageData.camera.PointDepth(vertex3d);
if (depth <= 0) {
return false; // 点在相机后面
}
} }
// 检查面法线和视图方向的夹角 // 检查面法线和视图方向的夹角
const Point3f& faceNormal = scene.mesh.faceNormals[idxFace]; const cv::Point3f& faceNormal = scene.mesh.faceNormals[idxFace];
// 计算面中心 // 计算面中心
const cv::Point3f faceCenter = (vertices[face[0]] + vertices[face[1]] + vertices[face[2]]) * (1.0f / 3.0f); cv::Point3f faceCenter = (vertices[face[0]] + vertices[face[1]] + vertices[face[2]]) * (1.0f / 3.0f);
cv::Point3d faceCenter3d(faceCenter.x, faceCenter.y, faceCenter.z);
// 计算相机中心 // 计算相机中心
const cv::Point3f cameraCenter( const cv::Point3d& cameraCenter = imageData.camera.C;
static_cast<float>(imageData.camera.C.x),
static_cast<float>(imageData.camera.C.y),
static_cast<float>(imageData.camera.C.z)
);
// 计算视图方向 // 计算视图方向
cv::Point3f viewDir = cameraCenter - faceCenter; cv::Point3d viewDir = cameraCenter - faceCenter3d;
float viewLen = cv::norm(viewDir); double viewLen = cv::norm(viewDir);
if (viewLen > 0) { if (viewLen > 0) {
// 归一化 // 归一化
viewDir /= viewLen; viewDir /= viewLen;
// 计算法线点积 // 计算法线点积
float cosAngle = faceNormal.x * viewDir.x + double cosAngle = faceNormal.x * viewDir.x +
faceNormal.y * viewDir.y + faceNormal.y * viewDir.y +
faceNormal.z * viewDir.z; faceNormal.z * viewDir.z;
// 如果夹角太大(接近90度),面可能不可见 // 如果夹角太大(接近90度),面可能不可见
// 使用阈值cos(85°) ≈ 0.087 // 使用阈值cos(85°) ≈ 0.087
if (cosAngle < 0.1f) { if (cosAngle < 0.1) {
return false; return false;
} }
} }
@ -11071,7 +11355,6 @@ bool MeshTexture::IsFaceVisibleFromView(FIndex idxFace, int viewID)
return true; return true;
} }
// 优化纹理接缝 // 优化纹理接缝
void MeshTexture::OptimizeTextureSeams(const std::vector<cv::Mat>& textures, void MeshTexture::OptimizeTextureSeams(const std::vector<cv::Mat>& textures,
const std::vector<std::vector<Point2f>>& seamPoints) const std::vector<std::vector<Point2f>>& seamPoints)
@ -11276,47 +11559,41 @@ void MeshTexture::LocalSeamLevelingEnhanced()
if (viewID < 0 || viewID >= (int)images.size()) continue; if (viewID < 0 || viewID >= (int)images.size()) continue;
const Image& image = images[viewID]; const Image& image = images[viewID];
// 为面的每个顶点采样颜色 // 为面的每个顶点采样颜色
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
VIndex vid = face[i]; VIndex vid = face[i];
const cv::Point3f& vertex = vertices[vid]; const cv::Point3f& vertex = vertices[vid];
// 方法1: 使用 OpenMVS 中的点类型 // 将cv::Point3f转换为OpenMVS的Point3d类型
// 在 OpenMVS 中,通常使用 Point3f 而不是 cv::Point3f // Camera类使用double精度进行计算
// 我们需要转换类型 Point3d point(static_cast<double>(vertex.x),
Point3f point(vertex.x, vertex.y, vertex.z); static_cast<double>(vertex.y),
static_cast<double>(vertex.z));
// 方法2: 使用 OpenMVS Camera 类的正确投影函数
// 根据 OpenMVS 源码,通常有两种方式: // 使用ProjectPoint函数进行投影
// 1. camera.ProjectPoint(point) - 用于投影 3D 点 Point2d projd = image.camera.ProjectPoint(point);
// 2. 或者通过相机矩阵手动计算
// 转换为浮点数坐标用于图像采样
Point2f proj; Point2f proj(static_cast<float>(projd.x),
static_cast<float>(projd.y));
// 尝试第一种方法: 使用 ProjectPoint
proj = image.camera.ProjectPoint(point); // 检查投影点是否在图像内
if (proj.x >= 0 && proj.x < image.image.cols &&
// 如果上面失败,尝试第二种方法: 手动计算投影 proj.y >= 0 && proj.y < image.image.rows) {
// Point2f proj = ProjectPoint(point, image.camera.K, image.camera.R, image.camera.C);
// 采样颜色
// 检查投影点是否在图像内 int x = (int)std::floor(proj.x);
if (proj.x >= 0 && proj.x < image.image.cols && int y = (int)std::floor(proj.y);
proj.y >= 0 && proj.y < image.image.rows) {
if (x >= 0 && x < image.image.cols && y >= 0 && y < image.image.rows) {
// 采样颜色 cv::Vec3b color = image.image.at<cv::Vec3b>(y, x);
int x = (int)std::floor(proj.x);
int y = (int)std::floor(proj.y); // 累积颜色
vertexColors[vid] += cv::Vec3f(color[0], color[1], color[2]);
if (x >= 0 && x < image.image.cols && y >= 0 && y < image.image.rows) { vertexCounts[vid]++;
cv::Vec3b color = image.image.at<cv::Vec3b>(y, x); }
}
// 累积颜色 }
vertexColors[vid] += cv::Vec3f(color[0], color[1], color[2]);
vertexCounts[vid]++;
}
}
}
} }
// 计算平均颜色 // 计算平均颜色
@ -11411,6 +11688,138 @@ void MeshTexture::LocalSeamLevelingEnhanced()
// 要将这些颜色应用到纹理中,需要在纹理生成过程中使用这些颜色 // 要将这些颜色应用到纹理中,需要在纹理生成过程中使用这些颜色
// 这通常需要在纹理图集生成后,对纹理像素进行调整 // 这通常需要在纹理图集生成后,对纹理像素进行调整
} }
void MeshTexture::GlobalSeamLevelingEnhanced() {
DEBUG_EXTRA("Starting enhanced global seam leveling...");
// 检查是否有纹理块
if (texturePatches.IsEmpty()) {
DEBUG_EXTRA("No texture patches found. Skipping enhanced global seam leveling.");
return;
}
// 创建一个从面索引到纹理块索引的映射
std::vector<int> faceToPatchMap(faces.size(), -1);
// 遍历所有纹理块,填充映射
for (int patchIdx = 0; patchIdx < (int)texturePatches.size(); ++patchIdx) {
const TexturePatch& patch = texturePatches[patchIdx];
for (FIndex fid : patch.faces) {
if (fid < faceToPatchMap.size()) {
faceToPatchMap[fid] = patchIdx;
}
}
}
// 创建顶点到纹理块的映射
std::vector<std::vector<uint32_t>> vertexLabels(vertices.size());
// 收集每个顶点的候选标签
for (FIndex idxFace = 0; idxFace < faces.size(); ++idxFace) {
const Face& face = faces[idxFace];
int label = faceToPatchMap[idxFace];
if (label == -1) continue; // 没有分配纹理块的面
for (int v = 0; v < 3; ++v) {
const VIndex idxVertex = face[v];
vertexLabels[idxVertex].push_back(label);
}
}
// 移除重复标签并排序
for (auto& labels : vertexLabels) {
std::sort(labels.begin(), labels.end());
labels.erase(std::unique(labels.begin(), labels.end()), labels.end());
}
// 计算纹理块的平均颜色
std::vector<cv::Vec3f> patchColors(texturePatches.size(), cv::Vec3f(0, 0, 0));
std::vector<int> patchCounts(texturePatches.size(), 0);
// 遍历所有面,计算纹理块颜色
for (FIndex idxFace = 0; idxFace < faces.size(); ++idxFace) {
int label = faceToPatchMap[idxFace];
if (label == -1) continue;
// 计算面的颜色(这里使用简单的颜色)
cv::Vec3f faceColor(0.5f, 0.5f, 0.5f); // 使用中性灰色作为默认颜色
patchColors[label] += faceColor;
patchCounts[label]++;
}
for (size_t i = 0; i < patchColors.size(); ++i) {
if (patchCounts[i] > 0) {
patchColors[i] /= (float)patchCounts[i];
}
}
// 使用简单的贪婪算法优化接缝
int changed = 0;
for (FIndex idxFace = 0; idxFace < faces.size(); ++idxFace) {
const Face& face = faces[idxFace];
int currentLabel = faceToPatchMap[idxFace];
if (currentLabel == -1) continue;
// 收集相邻面的标签
std::unordered_map<int, int> neighborLabelCounts;
for (int v = 0; v < 3; ++v) {
const VIndex idxVertex = face[v];
// 获取与顶点相邻的面
// 在OpenMVS中,vertexFaces通常是一个包含索引数组的容器
if (idxVertex < scene.mesh.vertexFaces.size()) {
// 使用auto自动推导类型,避免类型不匹配
const auto& adjacentFaces = scene.mesh.vertexFaces[idxVertex];
for (FIndex adjFaceIdx : adjacentFaces) {
if (adjFaceIdx == idxFace) continue;
int neighborLabel = faceToPatchMap[adjFaceIdx];
if (neighborLabel != -1) {
neighborLabelCounts[neighborLabel]++;
}
}
}
}
// 如果没有相邻面,跳过
if (neighborLabelCounts.empty()) continue;
// 找到出现次数最多的相邻标签
int bestLabel = currentLabel;
int maxCount = 0;
for (const auto& pair : neighborLabelCounts) {
if (pair.second > maxCount) {
maxCount = pair.second;
bestLabel = pair.first;
}
}
// 如果最佳标签与当前不同,且满足一定条件,则更改标签
if (bestLabel != currentLabel && maxCount >= 2) {
// 计算颜色差异
float colorDiff = cv::norm(patchColors[currentLabel], patchColors[bestLabel]);
// 如果颜色差异不大,则更改标签
if (colorDiff < 0.3f) { // 阈值可根据需要调整
// 更新面的纹理块映射
// 注意:这需要更新texturePatches中的面分配
// 这里我们只是更新映射,实际的纹理块更新需要更多操作
faceToPatchMap[idxFace] = bestLabel;
changed++;
}
}
}
DEBUG_EXTRA("Enhanced global seam leveling completed. Changed %d face labels.", changed);
// 注意:这里只是更新了faceToPatchMap,实际更新纹理块需要更多操作
// 可能需要重新构建纹理块或更新纹理坐标
}
// 合并重叠的纹理块 // 合并重叠的纹理块
void MeshTexture::MergeOverlappingPatches(Mesh::TexCoordArr& faceTexcoords2) void MeshTexture::MergeOverlappingPatches(Mesh::TexCoordArr& faceTexcoords2)
@ -11450,8 +11859,8 @@ void MeshTexture::MergeOverlappingPatches(Mesh::TexCoordArr& faceTexcoords2)
// 计算两个纹理块的重叠区域 // 计算两个纹理块的重叠区域
cv::Rect intersection = patch1.rect & patch2.rect; cv::Rect intersection = patch1.rect & patch2.rect;
if (!intersection.empty()) { if (!intersection.empty()) {
float overlapArea = intersection.area(); float overlapArea = (float)intersection.area();
float minArea = std::min(patch1.rect.area(), patch2.rect.area()); float minArea = std::min((float)patch1.rect.area(), (float)patch2.rect.area());
float overlapRatio = overlapArea / minArea; float overlapRatio = overlapArea / minArea;
if (overlapRatio > 0.1f) { // 重叠超过10% if (overlapRatio > 0.1f) { // 重叠超过10%
@ -11484,31 +11893,40 @@ void MeshTexture::MergeOverlappingPatches(Mesh::TexCoordArr& faceTexcoords2)
// 计算合并后的边界框 // 计算合并后的边界框
cv::Rect mergedRect = patch1.rect | patch2.rect; cv::Rect mergedRect = patch1.rect | patch2.rect;
// 合并面列表 // 合并面列表 - 使用 std::vector 代替 FIndexArr
FaceIdxArr mergedFaces = patch1.faces; std::vector<FIndex> mergedFaces;
for (FIndex fid : patch2.faces) { // 从 patch1.faces 复制
mergedFaces.Insert(fid); for (size_t k = 0; k < patch1.faces.GetSize(); ++k) {
mergedFaces.push_back(patch1.faces[k]);
}
// 从 patch2.faces 添加
for (size_t k = 0; k < patch2.faces.GetSize(); ++k) {
mergedFaces.push_back(patch2.faces[k]);
} }
// 创建新的纹理块 // 创建新的纹理块
patch1.rect = mergedRect; patch1.rect = mergedRect;
patch1.faces = mergedFaces; // 将 std::vector 转回 patch1.faces
patch1.faces.Release();
for (FIndex fid : mergedFaces) {
patch1.faces.Insert(fid);
}
// 标记第二个纹理块为已合并 // 标记第二个纹理块为已合并
patch2.label = NO_ID; patch2.label = NO_ID;
patch2.faces.Release(); patch2.faces.Release();
merged[idx2] = true; merged[idx2] = true;
DEBUG_VERBOSE("Merged patches %d and %d (overlap: %.2f%%)", DEBUG_EXTRA("Merged patches %d and %d (overlap: %.2f%%)",
idx1, idx2, overlap.first * 100.0f); idx1, idx2, overlap.first * 100.0f);
} }
} }
// 移除空的纹理块 // 移除空的纹理块
TexturePatchIdxArr newIndices(texturePatches.size()); std::vector<int> newIndices(texturePatches.size(), NO_ID);
int newIdx = 0; int newIdx = 0;
for (int i = 0; i < (int)texturePatches.size(); ++i) { for (int i = 0; i < (int)texturePatches.size(); ++i) {
if (texturePatches[i].label != NO_ID && !texturePatches[i].faces.IsEmpty()) { if (texturePatches[i].label != NO_ID && texturePatches[i].faces.GetSize() > 0) {
texturePatches[newIdx] = texturePatches[i]; texturePatches[newIdx] = texturePatches[i];
newIndices[i] = newIdx; newIndices[i] = newIdx;
++newIdx; ++newIdx;
@ -11518,14 +11936,6 @@ void MeshTexture::MergeOverlappingPatches(Mesh::TexCoordArr& faceTexcoords2)
} }
texturePatches.Resize(newIdx); texturePatches.Resize(newIdx);
// 更新面的纹理索引
for (FIndex fid = 0; fid < (FIndex)faces.size(); ++fid) {
int oldIdx = faceTexidx[fid];
if (oldIdx != NO_ID) {
faceTexidx[fid] = newIndices[oldIdx];
}
}
DEBUG_EXTRA("Merged overlapping patches, new count: %d", texturePatches.size()); DEBUG_EXTRA("Merged overlapping patches, new count: %d", texturePatches.size());
} }
@ -11742,7 +12152,7 @@ void MeshTexture::FillTextureHoles(std::vector<Image8U3>& textures, Pixel8U colE
continue; // 没有空洞 continue; // 没有空洞
} }
DEBUG_VERBOSE("Texture %zu: filling %d holes", i, holeCount); // DEBUG_VERBOSE("Texture %zu: filling %d holes", i, holeCount);
// 使用修复算法填充空洞 // 使用修复算法填充空洞
cv::Mat inpainted; cv::Mat inpainted;

Loading…
Cancel
Save