Compare commits

...

2 Commits

Author SHA1 Message Date
hesuicong 1421d21597 进一步优化 4 weeks ago
hesuicong 3693365bdf 算法优化 4 weeks ago
  1. 309
      libs/MVS/SceneTexture.cpp

309
libs/MVS/SceneTexture.cpp

@ -461,6 +461,7 @@ public: @@ -461,6 +461,7 @@ public:
bool CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewArr& ComputeAverageQuality, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f) const;
bool CreateVirtualFaces61(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f);
bool CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataViewArr& ComputeAverageQuality, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f) const;
bool CreateVirtualFaces63(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f) const;
static std::string GetFileNameWithoutExtension(std::string& strPath);
float CalculateBrightnessScore(const Image& imageData) const;
bool IsFaceVisibleRelaxed(const FaceDataArr& faceDatas, const IIndexArr& selectedCams, float visibleRatioThreshold) const;
@ -4305,6 +4306,313 @@ std::string MeshTexture::GetFileNameWithoutExtension(std::string& strPath) { @@ -4305,6 +4306,313 @@ std::string MeshTexture::GetFileNameWithoutExtension(std::string& strPath) {
}
}
bool MeshTexture::CreateVirtualFaces63(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras, float thMaxNormalDeviation) const
{
if (meshCurvatures.empty()) {
ComputeFaceCurvatures();
}
float thMaxColorDeviation = 130.0f;
const float QUALITY_THRESHOLD = 0.9f; // 质量阈值,可根据实际情况调整
const float ratioAngleToQuality(0.67f);
const float cosMaxNormalDeviation(COS(FD2R(thMaxNormalDeviation)));
Mesh::FaceIdxArr remainingFaces(faces.size());
std::iota(remainingFaces.begin(), remainingFaces.end(), 0);
std::vector<bool> selectedFaces(faces.size(), false);
cQueue<FIndex, FIndex, 0> currentVirtualFaceQueue;
std::unordered_set<FIndex> queuedFaces;
// Precompute average color for each face
Colors faceColors;
faceColors.reserve(faces.size());
for (size_t i = 0; i < faces.size(); ++i) {
faceColors.push_back(Color::ZERO);
}
for (FIndex idxFace = 0; idxFace < faces.size(); ++idxFace) {
const FaceDataArr& faceDatas = facesDatas[idxFace];
if (faceDatas.empty()) continue;
Color sumColor = Color::ZERO;
for (const FaceData& fd : faceDatas) {
sumColor += fd.color;
}
faceColors[idxFace] = sumColor / faceDatas.size();
}
do {
const FIndex startPos = RAND() % remainingFaces.size();
const FIndex virtualFaceCenterFaceID = remainingFaces[startPos];
// 动态法线阈值
const float centerCurvature = meshCurvatures[virtualFaceCenterFaceID];
const float dynamicThreshold = (centerCurvature < 0.2f) ? 18.0f : 10.0f; // 放宽角度阈值
const float dynamicCosTh = COS(FD2R(dynamicThreshold));
ASSERT(currentVirtualFaceQueue.IsEmpty());
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
const FaceDataArr& centerFaceDatas = facesDatas[virtualFaceCenterFaceID];
// 检查中心面片是否包含无效视图
bool bHasInvalidView = false;
int nInvalidViewCount = 0;
int nTotalViewCount = 0;
for (const FaceData& faceData : centerFaceDatas) {
if (faceData.bInvalidFacesRelative) {
bHasInvalidView = true;
++nInvalidViewCount;
}
++nTotalViewCount;
}
// 计算中心面片的质量
float centerFaceQuality = 0.0f;
int validViewCount = 0;
for (const FaceData& fd : centerFaceDatas) {
if (!fd.bInvalidFacesRelative) {
centerFaceQuality += fd.quality;
++validViewCount;
}
}
if (validViewCount > 0) {
centerFaceQuality /= validViewCount;
}
std::vector<std::pair<float, Color>> sortedViews;
std::vector<std::pair<float, Color>> sortedLuminViews;
std::vector<std::pair<float, Color>> validViews;
sortedViews.reserve(centerFaceDatas.size());
for (const FaceData& fd : centerFaceDatas) {
if (fd.bInvalidFacesRelative) {
sortedViews.emplace_back(fd.quality, fd.color);
sortedLuminViews.emplace_back(MeshTexture::GetLuminance(fd.color), fd.color);
} else {
sortedViews.emplace_back(fd.quality, fd.color);
sortedLuminViews.emplace_back(MeshTexture::GetLuminance(fd.color), fd.color);
validViews.emplace_back(fd.quality, fd.color);
}
}
std::sort(sortedViews.begin(), sortedViews.end(),
[](const auto& a, const auto& b) { return a.first > b.first; });
std::sort(validViews.begin(), validViews.end(),
[](const auto& a, const auto& b) { return a.first > b.first; });
int nSize = sortedViews.size();
float totalQuality = 0.0f;
Color totalColor(0,0,0);
for (int n = 0; n < nSize; ++n) {
totalQuality += sortedViews[n].first;
totalColor += sortedViews[n].second;
}
const float avgQuality = totalQuality / nSize;
const Color avgColor = totalColor / nSize;
float totalLuminance = MeshTexture::GetLuminance(totalColor);
float avgLuminance = totalLuminance / nSize;
std::sort(sortedLuminViews.begin(), sortedLuminViews.end(),
[avgLuminance](const auto& a, const auto& b) {
float luminDistA = cv::norm(avgLuminance - a.first);
float luminDistB = cv::norm(avgLuminance - b.first);
return luminDistA < luminDistB; });
// select the common cameras
Mesh::FaceIdxArr virtualFace;
FaceDataArr virtualFaceDatas;
if (centerFaceDatas.empty()) {
virtualFace.emplace_back(virtualFaceCenterFaceID);
selectedFaces[virtualFaceCenterFaceID] = true;
const auto posToErase = remainingFaces.FindFirst(virtualFaceCenterFaceID);
ASSERT(posToErase != Mesh::FaceIdxArr::NO_INDEX);
remainingFaces.RemoveAtMove(posToErase);
} else {
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
std::vector<std::pair<IIndex, float>> cameraAngles; // 存储相机索引和角度
for (IIndex idxView : selectedCams) {
const Image& imageData = images[idxView];
const RMatrix& R = imageData.camera.R;
Point3f localForward(0.0f, 0.0f, -1.0f);
Point3f cameraForward;
cameraForward.x = R(0,0) * localForward.x + R(0,1) * localForward.y + R(0,2) * localForward.z;
cameraForward.y = R(1,0) * localForward.x + R(1,1) * localForward.y + R(1,2) * localForward.z;
cameraForward.z = R(2,0) * localForward.x + R(2,1) * localForward.y + R(2,2) * localForward.z;
float norm = std::sqrt(cameraForward.x * cameraForward.x +
cameraForward.y * cameraForward.y +
cameraForward.z * cameraForward.z);
if (norm > 0.0f) {
cameraForward.x /= norm;
cameraForward.y /= norm;
cameraForward.z /= norm;
} else {
cameraForward = Point3f(0, 0, -1);
}
Point3f normalPoint(normalCenter.x, normalCenter.y, normalCenter.z);
float cosAngle = cameraForward.dot(normalPoint);
float angleDeg = std::acos(cosAngle) * 180.0f / M_PI;
std::string strPath = imageData.name;
std::string strName = MeshTexture::GetFileNameWithoutExtension(strPath);
if (!scene.is_face_delete_edge(strName, virtualFaceCenterFaceID)) {
if (scene.is_face_edge(strName, virtualFaceCenterFaceID)) {
if (angleDeg <= 40.0f) {
cameraAngles.emplace_back(idxView, angleDeg);
}
} else {
cameraAngles.emplace_back(idxView, angleDeg);
}
}
}
// 按angleDeg从小到大排序
std::vector<std::pair<IIndex, float>> sortedCams = cameraAngles;
std::sort(sortedCams.begin(), sortedCams.end(),
[](const std::pair<IIndex, float>& a, const std::pair<IIndex, float>& b) {
return a.second < b.second;
});
IIndexArr filteredCams;
size_t count = std::min(sortedCams.size(), static_cast<size_t>(3));
for (size_t i = 0; i < count; ++i) {
filteredCams.push_back(sortedCams[i].first);
}
if (filteredCams.empty()) {
// 处理空情况
selectedCams = filteredCams;
isVirtualFace[virtualFaceCenterFaceID] = false;
} else {
selectedCams = filteredCams;
isVirtualFace[virtualFaceCenterFaceID] = true;
}
currentVirtualFaceQueue.AddTail(virtualFaceCenterFaceID);
queuedFaces.clear();
do {
const FIndex currentFaceId = currentVirtualFaceQueue.GetHead();
currentVirtualFaceQueue.PopHead();
const Normal& faceNormal = scene.mesh.faceNormals[currentFaceId];
const float cosFaceToCenter(ComputeAngleN(normalCenter.ptr(), faceNormal.ptr()));
if (cosFaceToCenter < dynamicCosTh)
continue;
ASSERT(!selectedCams.empty());
if (!IsFaceVisible(facesDatas[currentFaceId], selectedCams))
continue;
// 修改3:调整颜色差异检查
const Color& centerColor = faceColors[virtualFaceCenterFaceID];
const Color& currentColor = faceColors[currentFaceId];
float colorDistance = cv::norm(centerColor - currentColor);
// 放宽颜色差异条件
if (colorDistance > 250.0f) { // 增加阈值
// 不跳过,继续处理
}
if (colorDistance > thMaxColorDeviation) {
// 保持原有逻辑
}
{
const auto posToErase = remainingFaces.FindFirst(currentFaceId);
ASSERT(posToErase != Mesh::FaceIdxArr::NO_INDEX);
remainingFaces.RemoveAtMove(posToErase);
selectedFaces[currentFaceId] = true;
virtualFace.push_back(currentFaceId);
}
const Mesh::FaceFaces& ffaces = faceFaces[currentFaceId];
for (int i = 0; i < 3; ++i) {
const FIndex fIdx = ffaces[i];
if (fIdx == NO_ID)
continue;
if (!selectedFaces[fIdx] && queuedFaces.find(fIdx) == queuedFaces.end()) {
currentVirtualFaceQueue.AddTail(fIdx);
queuedFaces.emplace(fIdx);
}
}
} while (!currentVirtualFaceQueue.IsEmpty());
// 计算虚拟面质量并创建虚拟面
for (IIndex idxView: selectedCams) {
FaceData& virtualFaceData = virtualFaceDatas.emplace_back();
virtualFaceData.quality = 0;
virtualFaceData.idxView = idxView;
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
virtualFaceData.color = Point3f::ZERO;
#endif
const Image& imageData = images[idxView];
std::string strPath = imageData.name;
std::string strName = MeshTexture::GetFileNameWithoutExtension(strPath);
int invalidQuality = 0;
Color invalidColor = Point3f::ZERO;
unsigned processedFaces(0);
int invalidCount = 0;
for (FIndex fid : virtualFace) {
const FaceDataArr& faceDatas = facesDatas[fid];
for (FaceData& faceData: faceDatas) {
int nViewCount = 0;
if (faceData.idxView == idxView) {
for (const FaceData& fd : faceDatas) {
if (faceData.bInvalidFacesRelative) {
++nViewCount;
}
}
if (bHasInvalidView) {
++processedFaces;
} else {
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
#endif
++processedFaces;
}
}
}
}
int validViewsSize = validViews.size();
if (bHasInvalidView) {
// 使用简化逻辑
const Color medianColor = ComputeMedianColorAndQuality(sortedViews).color;
const float medianQuality = ComputeMedianColorAndQuality(sortedViews).quality;
// 直接使用中位数计算
virtualFaceData.quality = medianQuality;
virtualFaceData.color = medianColor;
} else {
// 使用有效视图计算
if (!validViews.empty()) {
float totalQuality2 = 0.0f;
Color totalColor2 = Color(0,0,0);
for (const auto& v : validViews) {
totalQuality2 += v.first;
totalColor2 += v.second;
}
virtualFaceData.quality = totalQuality2 / validViews.size();
virtualFaceData.color = totalColor2 / validViews.size();
} else {
// 回退到平均值
virtualFaceData.quality = avgQuality;
virtualFaceData.color = avgColor;
}
}
}
ASSERT(!virtualFaceDatas.empty());
}
virtualFacesDatas.emplace_back(std::move(virtualFaceDatas));
virtualFaces.emplace_back(std::move(virtualFace));
} while (!remainingFaces.empty());
return true;
}
bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras, float thMaxNormalDeviation) const
{
if (meshCurvatures.empty()) {
@ -7245,6 +7553,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT @@ -7245,6 +7553,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
// CreateVirtualFaces6(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
// CreateVirtualFaces61(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
CreateVirtualFaces62(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
// CreateVirtualFaces63(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
TD_TIMER_STARTD();
// CreateVirtualFaces7(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
DEBUG_EXTRA("CreateVirtualFaces completed: %s", TD_TIMER_GET_FMT().c_str());

Loading…
Cancel
Save