diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index 73ccd48..012cf50 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -4360,7 +4360,6 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView if (angleDeg <= 45.0f) { // filteredCams.push_back(idxView); - //* float brightnessScore = CalculateBrightnessScore(imageData); // 亮度评分函数 float angleScore = 1.0f - (angleDeg / 45.0f); @@ -4374,9 +4373,7 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView } qualityScore = std::max(0.0f, std::min(1.0f, qualityScore)); float overallScore = 0.5f * angleScore + 0.3f * brightnessScore + 0.2f * qualityScore; - if (overallScore > 0.04f) { - filteredCams.push_back(idxView); } //*/ @@ -4400,9 +4397,7 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView } qualityScore = std::max(0.0f, std::min(1.0f, qualityScore)); float overallScore = 0.5f * angleScore + 0.3f * brightnessScore + 0.2f * qualityScore; - if (overallScore > 0.02f) { - filteredCams.push_back(idxView); } //*/ @@ -4478,6 +4473,7 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView } } while (!currentVirtualFaceQueue.IsEmpty()); + // compute virtual face quality and create virtual face for (IIndex idxView: selectedCams) { FaceData& virtualFaceData = virtualFaceDatas.emplace_back(); virtualFaceData.quality = 0; @@ -4485,30 +4481,218 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA virtualFaceData.color = Point3f::ZERO; #endif + int invalidQuality = 0; + Color invalidColor = Point3f::ZERO; unsigned processedFaces(0); bool bInvalidFacesRelative = false; int invalidCount = 0; for (FIndex fid : virtualFace) { const FaceDataArr& faceDatas = facesDatas[fid]; for (FaceData& faceData: faceDatas) { - if (faceData.idxView == idxView) { - virtualFaceData.quality += faceData.quality; - #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA - virtualFaceData.color += faceData.color; - #endif - ++processedFaces; - if (faceData.bInvalidFacesRelative) - ++invalidCount; - break; + + int nViewCount = 0; + if (faceData.idxView == idxView) + { + for (const FaceData& fd : faceDatas) + { + if ( faceData.bInvalidFacesRelative) + { + ++nViewCount; + } + } + // if (faceData.bInvalidFacesRelative) + if (bHasInvalidView) + { + // invalidQuality += faceData.quality; + // #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA + // invalidColor += faceData.color; + // #endif + + ++processedFaces; + } + else + { + // virtualFaceData.quality += faceData.quality; + #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA + // virtualFaceData.color += faceData.color; + #endif + ++processedFaces; + // break; + } } } } - ASSERT(processedFaces > 0); - virtualFaceData.quality /= processedFaces; - #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA - virtualFaceData.color /= processedFaces; - #endif - virtualFaceData.bInvalidFacesRelative = (invalidCount > processedFaces / 2); + + float maxLuminance = 120.0f; + float minLuminance = 90.0f; + int validViewsSize = validViews.size(); + // bHasInvalidView = true; + if (bHasInvalidView) + { + // 使用鲁棒的统计方法计算颜色和亮度的中心值 + const Color medianColor = ComputeMedianColorAndQuality(sortedViews).color; + const float medianQuality = ComputeMedianColorAndQuality(sortedViews).quality; + const float medianLuminance = ComputeMedianLuminance(sortedViews); + + // 计算颜色和亮度的绝对中位差(MAD)作为偏差阈值 + const float colorMAD = ComputeColorMAD(sortedViews, medianColor); + const float luminanceMAD = ComputeLuminanceMAD(sortedViews, medianLuminance); + + // 基于MAD设置动态阈值(3倍MAD是统计学上常用的异常值阈值) + const float maxColorDeviation = 0.01f * colorMAD; + const float maxLuminanceDeviation = 0.01f * luminanceMAD; + + std::vector validIndices; + for (int n = 0; n < sortedViews.size(); ++n) { + const Color& viewColor = sortedViews[n].second; + const float viewLuminance = MeshTexture::GetLuminance(viewColor); + + const float colorDistance = cv::norm(viewColor - medianColor); + const float luminanceDistance = std::abs(viewLuminance - medianLuminance); + + if (colorDistance <= maxColorDeviation && + luminanceDistance <= maxLuminanceDeviation) + { + validIndices.push_back(n); + } + else + { + const FIndex currentFaceId = currentVirtualFaceQueue.GetHead(); + const Normal& faceNormal = scene.mesh.faceNormals[currentFaceId]; + const float cosFaceToCenter(ComputeAngleN(normalCenter.ptr(), faceNormal.ptr())); + + bool bColorSimilarity = true; + // Check color similarity + const Color& centerColor = faceColors[virtualFaceCenterFaceID]; + const Color& currentColor = faceColors[currentFaceId]; + + float colorDistance = cv::norm(centerColor - currentColor); + // printf("1colorDistance=%f\n", colorDistance); + if (colorDistance > thMaxColorDeviation) { + // printf("2colorDistance=%f\n", colorDistance); + bColorSimilarity = false; + } + + // if ((cosFaceToCenter 0); + // virtualFaceData.quality /= processedFaces; + #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA + // virtualFaceData.color /= processedFaces; + #endif + + virtualFaceData.quality = 0; + #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA + virtualFaceData.color = Point3f::ZERO; + #endif + } + } + else + { + // 使用鲁棒的统计方法计算颜色和亮度的中心值 + const Color medianColor = ComputeMedianColorAndQuality(sortedViews).color; + const float medianQuality = ComputeMedianColorAndQuality(sortedViews).quality; + const float medianLuminance = ComputeMedianLuminance(sortedViews); + + // 计算颜色和亮度的绝对中位差(MAD)作为偏差阈值 + const float colorMAD = ComputeColorMAD(sortedViews, medianColor); + const float luminanceMAD = ComputeLuminanceMAD(sortedViews, medianLuminance); + + // 基于MAD设置动态阈值(3倍MAD是统计学上常用的异常值阈值) + const float maxColorDeviation = 0.01f * colorMAD; + // const float maxLuminanceDeviation = 0.01f * luminanceMAD; + const float maxLuminanceDeviation = 0.05f * luminanceMAD; + + std::vector validIndices; + for (int n = 0; n < sortedViews.size(); ++n) { + const Color& viewColor = sortedViews[n].second; + const float viewLuminance = MeshTexture::GetLuminance(viewColor); + + const float colorDistance = cv::norm(viewColor - medianColor); + const float luminanceDistance = std::abs(viewLuminance - medianLuminance); + + // if (colorDistance <= maxColorDeviation && + // luminanceDistance <= maxLuminanceDeviation) + // if (luminanceDistance <= maxLuminanceDeviation) + { + validIndices.push_back(n); + } + } + + if (validIndices.empty()) { + + virtualFaceData.quality = medianQuality; + virtualFaceData.color = medianColor; + } + else { + // 使用过滤后的视图重新计算平均值 + float totalQuality2 = 0.0f; + Color totalColor2 = Color(0,0,0); + for (int idx : validIndices) { + totalQuality2 += validViews[idx].first; + totalColor2 += validViews[idx].second; + } + virtualFaceData.quality = totalQuality2 / validIndices.size(); + virtualFaceData.color = totalColor2 / validIndices.size(); + } + } + + // virtualFaceData.bInvalidFacesRelative = (invalidCount > 1); + // virtualFaceData.bInvalidFacesRelative = (invalidCount > processedFaces * 2 / 3); } ASSERT(!virtualFaceDatas.empty()); }