diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index d64493f..0cb1a85 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -616,6 +616,8 @@ public: unsigned nTextureSizeMultiple, Pixel8U colEmpty, float fSharpnessWeight); + float ComputeViewWeight(const Image& image, const Vertex& faceCenter, const Vertex& normal); + float ComputeProjectedArea(const Vertex& faceCenter, const Vertex& normal, const Camera& camera); void FillTextureGaps(Image8U3& texture, Pixel8U colEmpty); void ApplyColorConsistencyOptimization( Image8U3& texture, @@ -13855,6 +13857,57 @@ void MeshTexture::ApplyColorConsistencyOptimization( } } +// 改进的视图权重计算 +float MeshTexture::ComputeViewWeight(const Image& image, const Vertex& faceCenter, const Vertex& normal) +{ + // 1. 视角质量(法线与视线夹角) + Vertex cameraPos(image.camera.C.x, image.camera.C.y, image.camera.C.z); + Vertex viewDir = cameraPos - faceCenter; + float distance = cv::norm(viewDir); + + if (distance < 1e-6f) return 0.0f; + + viewDir = viewDir / distance; + float cosAngle = std::abs(viewDir.dot(normal)); + float angleScore = cosAngle; // 角度越接近0度,得分越高 + + // 2. 距离衰减 + float distanceScore = 1.0f / (1.0f + distance * 0.001f); + + // 3. 图像分辨率 + // 计算3D面在图像中的投影面积 + float areaInPixels = ComputeProjectedArea(faceCenter, normal, image.camera); + float resolutionScore = std::min(1.0f, areaInPixels / 100.0f); + + // 4. 图像质量(可选,如果有质量评估的话) + // float qualityScore = image.GetQualityScore(); + + // 综合权重 + float weight = angleScore * 0.4f + distanceScore * 0.3f + resolutionScore * 0.3f; + + return std::max(0.0f, std::min(1.0f, weight)); +} + +float MeshTexture::ComputeProjectedArea(const Vertex& faceCenter, const Vertex& normal, + const Camera& camera) +{ + // 简化的投影面积计算 + // 假设三角面是单位面积,根据相机距离和夹角计算投影面积 + Vertex cameraPos(camera.C.x, camera.C.y, camera.C.z); + Vertex viewDir = cameraPos - faceCenter; + float distance = cv::norm(viewDir); + + if (distance < 1e-6f) return 0.0f; + + viewDir = viewDir / distance; + float cosAngle = std::abs(viewDir.dot(normal)); + + // 投影面积 = 原始面积 * cos(夹角) / 距离² + float projectionArea = cosAngle / (distance * distance); + + return std::max(0.0f, projectionArea); +} + Mesh::Image8U3Arr MeshTexture::GenerateTextureAtlasWith3DBridge( const LabelArr& faceLabels, const IIndexArr& views, @@ -14059,6 +14112,8 @@ Mesh::Image8U3Arr MeshTexture::GenerateTextureAtlasWith3DBridge( // 找出每个面的其他可见视图 std::vector> faceVisibleViews(scene.mesh.faces.size()); + std::vector faceNormals(scene.mesh.faces.size()); + #ifdef _USE_OPENMP #pragma omp parallel for schedule(dynamic) #endif @@ -14076,6 +14131,12 @@ Mesh::Image8U3Arr MeshTexture::GenerateTextureAtlasWith3DBridge( normal = crossProduct / (float)normVal; // 归一化 } + if (normVal > 0) { + faceNormals[idxFace] = crossProduct / (float)normVal; // 归一化 + } else { + faceNormals[idxFace] = Vertex(0, 0, 1); // 默认法向量 + } + // 计算面中心 Vertex faceCenter(0, 0, 0); for (int v = 0; v < 3; ++v) { @@ -14119,8 +14180,11 @@ Mesh::Image8U3Arr MeshTexture::GenerateTextureAtlasWith3DBridge( float resolution = 1.0f / (float)projDist; + const Vertex& faceNormal = faceNormals[idxFace]; + // 综合得分 - float score = viewAngle * resolution; + // float score = viewAngle * resolution; + float score = ComputeViewWeight(images[i], faceCenter, faceNormal); if (score > 0.1f) { // 阈值 viewScores.push_back({score, i});