优化染色版本
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;
|
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 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;
|
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);
|
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
|
// 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
|
// 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
|
// - 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);
|
ASSERT(posToErase != Mesh::FaceIdxArr::NO_INDEX);
|
||||||
remainingFaces.RemoveAtMove(posToErase);
|
remainingFaces.RemoveAtMove(posToErase);
|
||||||
} else {
|
} else {
|
||||||
|
// IIndexArr selectedCams = SelectBestViews2(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality, facesDatas);
|
||||||
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
|
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
|
||||||
|
|
||||||
//*
|
//*
|
||||||
// 获取中心面片的法线 (注意变量名是 normalCenter, 不是 centerNormal)
|
// 获取中心面片的法线 (注意变量名是 normalCenter, 不是 centerNormal)
|
||||||
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
|
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
|
||||||
@@ -4228,6 +4321,16 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|||||||
cQueue<FIndex, FIndex, 0> currentVirtualFaceQueue;
|
cQueue<FIndex, FIndex, 0> currentVirtualFaceQueue;
|
||||||
std::unordered_set<FIndex> queuedFaces;
|
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
|
// Precompute average color for each face
|
||||||
Colors faceColors; // 创建一个空列表
|
Colors faceColors; // 创建一个空列表
|
||||||
faceColors.reserve(faces.size()); // 预分配空间(如果cList有reserve方法且您关心性能)
|
faceColors.reserve(faces.size()); // 预分配空间(如果cList有reserve方法且您关心性能)
|
||||||
@@ -4326,7 +4429,7 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|||||||
remainingFaces.RemoveAtMove(posToErase);
|
remainingFaces.RemoveAtMove(posToErase);
|
||||||
} else {
|
} else {
|
||||||
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
|
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
|
||||||
|
// IIndexArr selectedCams = SelectBestViews2(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality, facesDatas);
|
||||||
//*
|
//*
|
||||||
// 获取中心面片的法线 (注意变量名是 normalCenter, 不是 centerNormal)
|
// 获取中心面片的法线 (注意变量名是 normalCenter, 不是 centerNormal)
|
||||||
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
|
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);
|
// printf("CreateVirtualFace %s, %d, %f\n", strName.c_str(), virtualFaceCenterFaceID, angleLimit);
|
||||||
|
|
||||||
if (angleDeg <= 45.0f)
|
if (angleDeg <= 35.0f)
|
||||||
{
|
{
|
||||||
filteredCams.push_back(idxView);
|
filteredCams.push_back(idxView);
|
||||||
/*
|
/*
|
||||||
@@ -4455,22 +4558,40 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|||||||
do {
|
do {
|
||||||
const FIndex currentFaceId = currentVirtualFaceQueue.GetHead();
|
const FIndex currentFaceId = currentVirtualFaceQueue.GetHead();
|
||||||
currentVirtualFaceQueue.PopHead();
|
currentVirtualFaceQueue.PopHead();
|
||||||
|
|
||||||
// check for condition to add in current virtual face
|
// check for condition to add in current virtual face
|
||||||
// normal angle smaller than thMaxNormalDeviation degrees
|
// normal angle smaller than thMaxNormalDeviation degrees
|
||||||
const Normal& faceNormal = scene.mesh.faceNormals[currentFaceId];
|
const Normal& faceNormal = scene.mesh.faceNormals[currentFaceId];
|
||||||
const float cosFaceToCenter(ComputeAngleN(normalCenter.ptr(), faceNormal.ptr()));
|
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;
|
// continue;
|
||||||
if (cosFaceToCenter < dynamicCosTh) // 使用动态阈值
|
|
||||||
continue;
|
|
||||||
// check if current face is seen by all cameras in selectedCams
|
// check if current face is seen by all cameras in selectedCams
|
||||||
ASSERT(!selectedCams.empty());
|
ASSERT(!selectedCams.empty());
|
||||||
if (!IsFaceVisible(facesDatas[currentFaceId], selectedCams))
|
if (!IsFaceVisible(facesDatas[currentFaceId], selectedCams))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check color similarity
|
// 3. 放宽颜色差异条件
|
||||||
const Color& centerColor = faceColors[virtualFaceCenterFaceID];
|
const Color& centerColor = faceColors[virtualFaceCenterFaceID];
|
||||||
const Color& currentColor = faceColors[currentFaceId];
|
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)
|
// if (cv::norm(centerColor) > 1e-5 && cv::norm(currentColor) > 1e-5)
|
||||||
{
|
{
|
||||||
float colorDistance = cv::norm(centerColor - currentColor);
|
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;
|
// construct and use virtual faces for patch creation instead of actual mesh faces;
|
||||||
// the virtual faces are composed of coplanar triangles sharing same views
|
// the virtual faces are composed of coplanar triangles sharing same views
|
||||||
if (bUseVirtualFaces) {
|
if (bUseVirtualFaces) {
|
||||||
@@ -7058,7 +7179,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
|||||||
CreateVirtualFaces62(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
|
CreateVirtualFaces62(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
|
||||||
TD_TIMER_STARTD();
|
TD_TIMER_STARTD();
|
||||||
// CreateVirtualFaces7(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
|
// 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);
|
size_t controlCounter(0);
|
||||||
FOREACH(idxVF, virtualFaces) {
|
FOREACH(idxVF, virtualFaces) {
|
||||||
|
|||||||
Reference in new issue
Block a user