优化染色版本
This commit is contained in:
1 parent
7d0487ea30
commit
1086eb09c5
1 file changed
+130
-9
+130
-9
@@ -476,6 +476,8 @@ public:
|
||||
|
||||
bool CreateVirtualFaces7(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras=2, float thMaxNormalDeviation=25.f) const;
|
||||
IIndexArr SelectBestViews(const FaceDataArr& faceDatas, FIndex fid, unsigned minCommonCameras, float ratioAngleToQuality) const;
|
||||
IIndexArr SelectBestViews2(const FaceDataArr& faceDatas, FIndex fid, unsigned minCommonCameras, float ratioAngleToQuality, FaceDataViewArr& facesDatas) const;
|
||||
|
||||
IIndexArr SelectBestView(const FaceDataArr& faceDatas, FIndex fid, unsigned minCommonCameras, float ratioAngleToQuality) const;
|
||||
|
||||
bool FaceViewSelection(unsigned minCommonCameras, float fOutlierThreshold, float fRatioDataSmoothness, int nIgnoreMaskLabel, const IIndexArr& views);
|
||||
@@ -1776,6 +1778,97 @@ void MeshTexture::PerformLocalDepthConsistencyCheck(DepthMap& depthMap, FaceMap&
|
||||
}
|
||||
//*/
|
||||
|
||||
IIndexArr MeshTexture::SelectBestViews2(const FaceDataArr& faceDatas, FIndex fid, unsigned minCommonCameras, float ratioAngleToQuality, FaceDataViewArr& facesDatas) const
|
||||
{
|
||||
ASSERT(!faceDatas.empty());
|
||||
|
||||
// 计算每个视图能看到的相邻面片数量
|
||||
std::unordered_map<IIndex, int> viewCoverageCount;
|
||||
for (const FaceData& fd : faceDatas) {
|
||||
if (!fd.bInvalidFacesRelative) {
|
||||
viewCoverageCount[fd.idxView] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 统计每个视图能看到的面片数
|
||||
for (const FaceData& fd : faceDatas) {
|
||||
if (!fd.bInvalidFacesRelative) {
|
||||
// 统计这个视图能看到的所有相邻面片
|
||||
const Mesh::FaceFaces& ffaces = faceFaces[fid];
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const FIndex neighborIdx = ffaces[i];
|
||||
if (neighborIdx != NO_ID) {
|
||||
const FaceDataArr& neighborDatas = facesDatas[neighborIdx];
|
||||
for (const FaceData& neighborFd : neighborDatas) {
|
||||
if (neighborFd.idxView == fd.idxView && !neighborFd.bInvalidFacesRelative) {
|
||||
viewCoverageCount[fd.idxView]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重新计算分数,考虑覆盖范围
|
||||
float maxQuality = 0;
|
||||
for (const FaceData& faceData: faceDatas)
|
||||
maxQuality = MAXF(maxQuality, faceData.quality);
|
||||
const Face& f = faces[fid];
|
||||
const Vertex faceCenter((vertices[f[0]] + vertices[f[1]] + vertices[f[2]]) / 3.f);
|
||||
|
||||
CLISTDEF0IDX(float,IIndex) scores(faceDatas.size());
|
||||
FOREACH(idxFaceData, faceDatas) {
|
||||
const FaceData& faceData = faceDatas[idxFaceData];
|
||||
if (faceData.bInvalidFacesRelative) {
|
||||
scores[idxFaceData] = -1.0f; // 无效视图分数为负
|
||||
continue;
|
||||
}
|
||||
|
||||
const Image& imageData = images[faceData.idxView];
|
||||
const Point3f camDir(Cast<Mesh::Type>(imageData.camera.C) - faceCenter);
|
||||
const Normal& faceNormal = scene.mesh.faceNormals[fid];
|
||||
const float cosFaceCam(ComputeAngle(camDir.ptr(), faceNormal.ptr()));
|
||||
|
||||
// 计算覆盖范围分数(0-1之间)
|
||||
float coverageScore = 0.0f;
|
||||
if (viewCoverageCount.find(faceData.idxView) != viewCoverageCount.end()) {
|
||||
int maxCoverage = 0;
|
||||
for (const auto& pair : viewCoverageCount) {
|
||||
maxCoverage = MAX(maxCoverage, pair.second);
|
||||
}
|
||||
if (maxCoverage > 0) {
|
||||
coverageScore = static_cast<float>(viewCoverageCount[faceData.idxView]) / maxCoverage;
|
||||
}
|
||||
}
|
||||
|
||||
// 综合角度、质量和覆盖范围
|
||||
const float angleScore = ratioAngleToQuality * cosFaceCam;
|
||||
const float qualityScore = (1.0f - ratioAngleToQuality) * faceData.quality / maxQuality;
|
||||
const float coverageWeight = 0.3f; // 覆盖范围权重
|
||||
const float combinedScore = 0.4f * angleScore + 0.3f * qualityScore + coverageWeight * coverageScore;
|
||||
|
||||
scores[idxFaceData] = combinedScore;
|
||||
}
|
||||
|
||||
// 按分数排序
|
||||
IIndexArr scorePodium(faceDatas.size());
|
||||
std::iota(scorePodium.begin(), scorePodium.end(), 0);
|
||||
scorePodium.Sort([&scores](IIndex i, IIndex j) {
|
||||
return scores[i] > scores[j];
|
||||
});
|
||||
|
||||
// 选择最佳视图
|
||||
IIndexArr cameras;
|
||||
for (IIndex i = 0; i < MIN(minCommonCameras, faceDatas.size()); ++i) {
|
||||
if (scores[scorePodium[i]] > 0.1f) { // 分数阈值
|
||||
cameras.push_back(faceDatas[scorePodium[i]].idxView);
|
||||
}
|
||||
}
|
||||
|
||||
return cameras;
|
||||
}
|
||||
|
||||
// order the camera view scores with highest score first and return the list of first <minCommonCameras> cameras
|
||||
// ratioAngleToQuality represents the ratio in witch we combine normal angle to quality for a face to obtain the selection score
|
||||
// - a ratio of 1 means only angle is considered
|
||||
@@ -2962,8 +3055,8 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
|
||||
ASSERT(posToErase != Mesh::FaceIdxArr::NO_INDEX);
|
||||
remainingFaces.RemoveAtMove(posToErase);
|
||||
} else {
|
||||
// IIndexArr selectedCams = SelectBestViews2(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality, facesDatas);
|
||||
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
|
||||
|
||||
//*
|
||||
// 获取中心面片的法线 (注意变量名是 normalCenter, 不是 centerNormal)
|
||||
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
|
||||
@@ -4228,6 +4321,16 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
||||
cQueue<FIndex, FIndex, 0> currentVirtualFaceQueue;
|
||||
std::unordered_set<FIndex> queuedFaces;
|
||||
|
||||
// std::vector<std::unordered_set<IIndex>> faceValidCameras(faces.size());
|
||||
// for (FIndex idxFace = 0; idxFace < faces.size(); ++idxFace) {
|
||||
// const FaceDataArr& faceDatas = facesDatas[idxFace];
|
||||
// for (const FaceData& fd : faceDatas) {
|
||||
// if (!fd.bInvalidFacesRelative) {
|
||||
// faceValidCameras[idxFace].insert(fd.idxView);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Precompute average color for each face
|
||||
Colors faceColors; // 创建一个空列表
|
||||
faceColors.reserve(faces.size()); // 预分配空间(如果cList有reserve方法且您关心性能)
|
||||
@@ -4326,7 +4429,7 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
||||
remainingFaces.RemoveAtMove(posToErase);
|
||||
} else {
|
||||
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
|
||||
|
||||
// IIndexArr selectedCams = SelectBestViews2(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality, facesDatas);
|
||||
//*
|
||||
// 获取中心面片的法线 (注意变量名是 normalCenter, 不是 centerNormal)
|
||||
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
|
||||
@@ -4383,7 +4486,7 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
||||
{
|
||||
// printf("CreateVirtualFace %s, %d, %f\n", strName.c_str(), virtualFaceCenterFaceID, angleLimit);
|
||||
|
||||
if (angleDeg <= 45.0f)
|
||||
if (angleDeg <= 35.0f)
|
||||
{
|
||||
filteredCams.push_back(idxView);
|
||||
/*
|
||||
@@ -4455,22 +4558,40 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
||||
do {
|
||||
const FIndex currentFaceId = currentVirtualFaceQueue.GetHead();
|
||||
currentVirtualFaceQueue.PopHead();
|
||||
|
||||
// check for condition to add in current virtual face
|
||||
// normal angle smaller than thMaxNormalDeviation degrees
|
||||
const Normal& faceNormal = scene.mesh.faceNormals[currentFaceId];
|
||||
const float cosFaceToCenter(ComputeAngleN(normalCenter.ptr(), faceNormal.ptr()));
|
||||
// if (cosFaceToCenter < cosMaxNormalDeviation)
|
||||
if (cosFaceToCenter < dynamicCosTh)
|
||||
continue;
|
||||
// if (cosFaceToCenter < dynamicCosTh) // 使用动态阈值
|
||||
// continue;
|
||||
// printf("dynamicCosTh=%f\n", dynamicCosTh);
|
||||
// if (cosFaceToCenter < 0.99) // 对应60度,比原来的更宽松
|
||||
// continue;
|
||||
if (cosFaceToCenter < dynamicCosTh) // 使用动态阈值
|
||||
continue;
|
||||
|
||||
// check if current face is seen by all cameras in selectedCams
|
||||
ASSERT(!selectedCams.empty());
|
||||
if (!IsFaceVisible(facesDatas[currentFaceId], selectedCams))
|
||||
continue;
|
||||
|
||||
// Check color similarity
|
||||
// 3. 放宽颜色差异条件
|
||||
const Color& centerColor = faceColors[virtualFaceCenterFaceID];
|
||||
const Color& currentColor = faceColors[currentFaceId];
|
||||
float colorDistance = cv::norm(centerColor - currentColor);
|
||||
if (colorDistance > 200.0f) { // 从200.0f放宽到250.0f
|
||||
// continue; // 如果颜色差异太大,跳过
|
||||
}
|
||||
|
||||
// check if current face is seen by all cameras in selectedCams
|
||||
// ASSERT(!selectedCams.empty());
|
||||
// if (!IsFaceVisible(facesDatas[currentFaceId], selectedCams))
|
||||
// continue;
|
||||
|
||||
// // Check color similarity
|
||||
// const Color& centerColor = faceColors[virtualFaceCenterFaceID];
|
||||
// const Color& currentColor = faceColors[currentFaceId];
|
||||
// if (cv::norm(centerColor) > 1e-5 && cv::norm(currentColor) > 1e-5)
|
||||
{
|
||||
float colorDistance = cv::norm(centerColor - currentColor);
|
||||
@@ -7040,7 +7161,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// construct and use virtual faces for patch creation instead of actual mesh faces;
|
||||
// the virtual faces are composed of coplanar triangles sharing same views
|
||||
if (bUseVirtualFaces) {
|
||||
@@ -7058,7 +7179,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
||||
CreateVirtualFaces62(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
|
||||
TD_TIMER_STARTD();
|
||||
// CreateVirtualFaces7(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
|
||||
DEBUG_EXTRA("CreateVirtualFaces7 completed: %s", TD_TIMER_GET_FMT().c_str());
|
||||
DEBUG_EXTRA("CreateVirtualFaces completed: %s", TD_TIMER_GET_FMT().c_str());
|
||||
|
||||
size_t controlCounter(0);
|
||||
FOREACH(idxVF, virtualFaces) {
|
||||
|
||||
Reference in new issue
Block a user