|
|
|
|
@ -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; |
|
|
|
|
static std::string GetFileNameWithoutExtension(std::string& strPath); |
|
|
|
|
float CalculateBrightnessScore(const Image& imageData) const; |
|
|
|
|
bool IsFaceVisibleRelaxed(const FaceDataArr& faceDatas, const IIndexArr& selectedCams, float visibleRatioThreshold) const; |
|
|
|
|
bool CheckColorConsistency(const FaceDataArr& centerDatas, const FaceDataArr& candidateDatas) const; |
|
|
|
|
@ -801,6 +802,8 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
@@ -801,6 +802,8 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<int> faceViewCount(faces.size(), 0); |
|
|
|
|
std::vector<std::vector<Color>> faceViewColors(faces.size()); // 存储每个面片在各个视图下的颜色
|
|
|
|
|
std::vector<std::vector<float>> faceViewQualities(faces.size()); // 存储每个面片在各个视图下的质量
|
|
|
|
|
|
|
|
|
|
// extract array of faces viewed by each image
|
|
|
|
|
IIndexArr views(_views); |
|
|
|
|
@ -819,8 +822,8 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
@@ -819,8 +822,8 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
|
|
|
|
#ifdef TEXOPT_USE_OPENMP |
|
|
|
|
bool bAbort(false); |
|
|
|
|
#pragma omp parallel for private(imageGradMag, mGrad, faceMap, depthMap) |
|
|
|
|
for (int_t idx=0; idx<(int_t)views.size(); ++idx) { |
|
|
|
|
|
|
|
|
|
for (int_t idx=0; idx<(int_t)views.size(); ++idx) |
|
|
|
|
{ |
|
|
|
|
#pragma omp flush (bAbort) |
|
|
|
|
if (bAbort) { |
|
|
|
|
++progress; |
|
|
|
|
@ -929,160 +932,7 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
@@ -929,160 +932,7 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
|
|
|
|
depthMap.create(imageData.GetSize()); |
|
|
|
|
|
|
|
|
|
std::unordered_set<FIndex> tempFaces; |
|
|
|
|
if (false) |
|
|
|
|
{ |
|
|
|
|
// viewDepthMaps[idxView] = depthMap;
|
|
|
|
|
|
|
|
|
|
for (int r = 0; r < depthMap.rows; ++r) { |
|
|
|
|
for (int c = 0; c < depthMap.cols; ++c) { |
|
|
|
|
// printf("1depthMap(r, c)=%f\n", depthMap(r, c));
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RasterMesh::Triangle triangle; |
|
|
|
|
RasterMesh rasterer1(*this, vertices, imageData.camera, depthMap, faceMap, scene.mesh, false); |
|
|
|
|
|
|
|
|
|
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer1); |
|
|
|
|
if (nIgnoreMaskLabel >= 0) { |
|
|
|
|
// import mask
|
|
|
|
|
BitMatrix bmask; |
|
|
|
|
// std::cout << "nIgnoreMaskLabel is open" << std::endl;
|
|
|
|
|
DepthEstimator::ImportIgnoreMask(imageData, imageData.GetSize(), (uint16_t)OPTDENSE::nIgnoreMaskLabel, bmask, &rasterer1.mask); |
|
|
|
|
} else if (nIgnoreMaskLabel == -1) { |
|
|
|
|
// creating mask to discard invalid regions created during image radial undistortion
|
|
|
|
|
rasterer1.mask = DetectInvalidImageRegions(imageData.image); |
|
|
|
|
#if TD_VERBOSE != TD_VERBOSE_OFF |
|
|
|
|
if (VERBOSITY_LEVEL > 2) |
|
|
|
|
cv::imwrite(String::FormatString("umask%04d.png", idxView), rasterer1.mask); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rasterer1.Clear(); |
|
|
|
|
|
|
|
|
|
#ifdef TEXOPT_USE_OPENMP |
|
|
|
|
#pragma omp critical(invalid_faces_access) |
|
|
|
|
#endif |
|
|
|
|
{ |
|
|
|
|
std::lock_guard<std::mutex> lock(*scene.mesh.invalidFaces.mtx); |
|
|
|
|
scene.mesh.invalidFaces.data.clear(); |
|
|
|
|
} |
|
|
|
|
printf("imageData.name=%s\n", imageData.name.c_str()); |
|
|
|
|
for (FIndex idxFace : cameraFaces) { |
|
|
|
|
if (idxFace >= faces.size()) { |
|
|
|
|
DEBUG_EXTRA("Invalid face index %u (max %u) in view %u", idxFace, faces.size()-1, idxView); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// // 添加临界区保护
|
|
|
|
|
// bool skipFace = false;
|
|
|
|
|
// #ifdef TEXOPT_USE_OPENMP
|
|
|
|
|
// #pragma omp critical(invalid_faces_access)
|
|
|
|
|
// #endif
|
|
|
|
|
// {
|
|
|
|
|
// std::lock_guard<std::mutex> lock(scene.mesh.invalidFacesMutex);
|
|
|
|
|
// skipFace = (scene.mesh.invalidFaces.find(idxFace) != scene.mesh.invalidFaces.end());
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// if (skipFace)
|
|
|
|
|
// {
|
|
|
|
|
// continue;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
rasterer1.validFace = true; |
|
|
|
|
const Face& facet = faces[idxFace]; |
|
|
|
|
rasterer1.idxFace = idxFace; |
|
|
|
|
|
|
|
|
|
if (scene.is_face_visible(strName.c_str(), idxFace)) |
|
|
|
|
{ |
|
|
|
|
rasterer1.Project(facet, triangleRasterizer); |
|
|
|
|
if (!rasterer1.validFace) |
|
|
|
|
rasterer1.Project(facet, triangleRasterizer); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// if (!bUseVirtualFaces)
|
|
|
|
|
// if (bUseVirtualFaces)
|
|
|
|
|
tempFaces = PerformLocalDepthConsistencyCheck(depthMap, faceMap, scene.mesh, idxView, strName); |
|
|
|
|
|
|
|
|
|
// RasterMesh rasterer2(*this, vertices, imageData.camera, depthMap, faceMap, scene.mesh, true);
|
|
|
|
|
RasterMesh rasterer2(*this, vertices, imageData.camera, depthMap, faceMap, std::ref(scene.mesh), true); |
|
|
|
|
|
|
|
|
|
for (int r = 0; r < depthMap.rows; ++r) { |
|
|
|
|
for (int c = 0; c < depthMap.cols; ++c) { |
|
|
|
|
// if (depthMap(r, c)> 999.0f)
|
|
|
|
|
// printf("2depthMap(r, c)=%f\n", depthMap(r, c));
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RasterMesh::TriangleRasterizer triangleRasterizer2(triangle, rasterer2); |
|
|
|
|
if (nIgnoreMaskLabel >= 0) { |
|
|
|
|
// import mask
|
|
|
|
|
BitMatrix bmask; |
|
|
|
|
// std::cout << "nIgnoreMaskLabel is open" << std::endl;
|
|
|
|
|
DepthEstimator::ImportIgnoreMask(imageData, imageData.GetSize(), (uint16_t)OPTDENSE::nIgnoreMaskLabel, bmask, &rasterer2.mask); |
|
|
|
|
} else if (nIgnoreMaskLabel == -1) { |
|
|
|
|
// creating mask to discard invalid regions created during image radial undistortion
|
|
|
|
|
rasterer2.mask = DetectInvalidImageRegions(imageData.image); |
|
|
|
|
#if TD_VERBOSE != TD_VERBOSE_OFF |
|
|
|
|
if (VERBOSITY_LEVEL > 2) |
|
|
|
|
cv::imwrite(String::FormatString("umask%04d.png", idxView), rasterer2.mask); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int r = 0; r < depthMap.rows; ++r) { |
|
|
|
|
for (int c = 0; c < depthMap.cols; ++c) { |
|
|
|
|
// if (depthMap(r, c)> 999.0f)
|
|
|
|
|
// printf("3depthMap(r, c)=%f, r=%d, c=%d, faceMap(r, c)=%d\n", depthMap(r, c), r, c, faceMap(r, c));
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// rasterer2.Clear();
|
|
|
|
|
|
|
|
|
|
for (FIndex idxFace : cameraFaces) { |
|
|
|
|
// 添加面索引有效性检查
|
|
|
|
|
if (idxFace >= faces.size()) { |
|
|
|
|
DEBUG_EXTRA("Invalid face index %u (max %u) in view %u", idxFace, faces.size()-1, idxView); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 添加临界区保护
|
|
|
|
|
bool skipFace = false; |
|
|
|
|
#ifdef TEXOPT_USE_OPENMP |
|
|
|
|
#pragma omp critical(invalid_faces_access) |
|
|
|
|
#endif |
|
|
|
|
{ |
|
|
|
|
std::lock_guard<std::mutex> lock(*scene.mesh.invalidFaces.mtx); |
|
|
|
|
skipFace = (scene.mesh.invalidFaces.data.find(idxFace) != scene.mesh.invalidFaces.data.end()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (skipFace) |
|
|
|
|
{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (tempFaces.find(idxFace) != tempFaces.end()) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rasterer2.validFace = true; |
|
|
|
|
const Face& facet = faces[idxFace]; |
|
|
|
|
rasterer2.idxFace = idxFace; |
|
|
|
|
// rasterer2.Project(facet, triangleRasterizer2);
|
|
|
|
|
// if (!rasterer2.validFace)
|
|
|
|
|
// rasterer2.Project(facet, triangleRasterizer2);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int r = 0; r < depthMap.rows; ++r) { |
|
|
|
|
for (int c = 0; c < depthMap.cols; ++c) { |
|
|
|
|
// if (depthMap(r, c)> 999.0f)
|
|
|
|
|
// printf("4depthMap(r, c)=%f, r=%d, c=%d, faceMap(r, c)=%d\n", depthMap(r, c), r, c, faceMap(r, c));
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// RasterMesh rasterer(vertices, imageData.camera, depthMap, faceMap);
|
|
|
|
|
RasterMesh rasterer(*this, vertices, imageData.camera, depthMap, faceMap, scene.mesh, false); |
|
|
|
|
@ -1115,7 +965,11 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
@@ -1115,7 +965,11 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
|
|
|
|
skipVisibilityCheck = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (scene.is_face_visible(strName.c_str(), idxFace)) |
|
|
|
|
bool is_face_visible = scene.is_face_visible(strName.c_str(), idxFace); |
|
|
|
|
// bool is_face_normal_visible_map = scene.is_face_normal_visible_map(strName.c_str(), idxFace);
|
|
|
|
|
|
|
|
|
|
// if (is_face_visible && is_face_normal_visible_map)
|
|
|
|
|
if (is_face_visible) |
|
|
|
|
// if (skipVisibilityCheck || scene.is_face_visible(strName.c_str(), idxFace))
|
|
|
|
|
{ |
|
|
|
|
rasterer.Project(facet, triangleRasterizer); |
|
|
|
|
@ -1250,6 +1104,13 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
@@ -1250,6 +1104,13 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
|
|
|
|
if (depthMap(j,i)>999.0f) |
|
|
|
|
faceData.bInvalidFacesRelative = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
// 保存视图颜色和质量
|
|
|
|
|
Color pixelColor = imageData.image(j,i); |
|
|
|
|
faceViewColors[idxFace].push_back(pixelColor); |
|
|
|
|
faceViewQualities[idxFace].push_back(imageGradMag(j,i)); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// adjust face quality with camera angle relative to face normal
|
|
|
|
|
@ -1262,8 +1123,15 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
@@ -1262,8 +1123,15 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
|
|
|
|
const Vertex faceCenter((vertices[f[0]] + vertices[f[1]] + vertices[f[2]]) / 3.f); |
|
|
|
|
const Point3f camDir(Cast<Mesh::Type>(imageData.camera.C) - faceCenter); |
|
|
|
|
const Normal& faceNormal = scene.mesh.faceNormals[idxFace]; |
|
|
|
|
|
|
|
|
|
const float cosFaceCam(MAXF(0.001f, ComputeAngle(camDir.ptr(), faceNormal.ptr()))); |
|
|
|
|
// const float MIN_COS_THRESHOLD = 0.1f; // 增大阈值,减少极端倾斜视角的影响
|
|
|
|
|
// const float cosFaceCam(MAXF(MIN_COS_THRESHOLD, ComputeAngle(camDir.ptr(), faceNormal.ptr())));
|
|
|
|
|
|
|
|
|
|
faceDatas.back().quality *= SQUARE(cosFaceCam); |
|
|
|
|
// faceDatas.back().quality *= cosFaceCam; // 线性调整
|
|
|
|
|
// faceDatas.back().quality *= pow(cosFaceCam, 0.5f); // 平方根调整
|
|
|
|
|
// faceDatas.back().quality *= 1.0f - 0.5f * (1.0f - cosFaceCam); // 平滑调整
|
|
|
|
|
} |
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
FOREACH(idxFace, areas) { |
|
|
|
|
@ -1280,223 +1148,89 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
@@ -1280,223 +1148,89 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
|
|
|
|
|
|
|
|
|
// Temp
|
|
|
|
|
/*
|
|
|
|
|
for (int_t idx=0; idx<(int_t)views.size(); ++idx) |
|
|
|
|
{ |
|
|
|
|
#pragma omp flush (bAbort) |
|
|
|
|
if (bAbort) |
|
|
|
|
{ |
|
|
|
|
++progress; |
|
|
|
|
continue; |
|
|
|
|
// 第一步:计算每个面片的最终颜色(基于最接近平均颜色的3个视图)
|
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
Colors faceFinalColors; // 存储每个面片的最终颜色
|
|
|
|
|
std::vector<float> faceFinalQualities(faces.size(), 0.0f); // 存储每个面片的最终质量
|
|
|
|
|
|
|
|
|
|
// 使用循环初始化
|
|
|
|
|
for (size_t i = 0; i < faces.size(); ++i) { |
|
|
|
|
faceFinalColors.push_back(Color::ZERO); |
|
|
|
|
} |
|
|
|
|
const IIndex idxView(views[(IIndex)idx]); |
|
|
|
|
|
|
|
|
|
Image& imageData = images[idxView]; |
|
|
|
|
if (!imageData.IsValid()) { |
|
|
|
|
++progress; |
|
|
|
|
for (FIndex idxFace = 0; idxFace < faces.size(); ++idxFace) { |
|
|
|
|
const std::vector<Color>& colors = faceViewColors[idxFace]; |
|
|
|
|
const std::vector<float>& qualities = faceViewQualities[idxFace]; |
|
|
|
|
|
|
|
|
|
if (colors.empty()) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 1. 计算所有视图颜色的平均值
|
|
|
|
|
Color avgColor = Color::ZERO; |
|
|
|
|
for (const Color& color : colors) { |
|
|
|
|
avgColor += color; |
|
|
|
|
} |
|
|
|
|
avgColor /= (float)colors.size(); |
|
|
|
|
|
|
|
|
|
// 2. 计算每个视图颜色与平均值的差异
|
|
|
|
|
std::vector<std::pair<float, int>> colorDistances; // (距离, 索引)
|
|
|
|
|
colorDistances.reserve(colors.size()); |
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < colors.size(); ++i) { |
|
|
|
|
float distance = cv::norm(colors[i] - avgColor); |
|
|
|
|
colorDistances.emplace_back(distance, i); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3. 按距离排序(从小到大)
|
|
|
|
|
std::sort(colorDistances.begin(), colorDistances.end(), |
|
|
|
|
[](const std::pair<float, int>& a, const std::pair<float, int>& b) { |
|
|
|
|
return a.first < b.first; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const Image& imageData = images[idxView]; |
|
|
|
|
std::string strPath = imageData.name; |
|
|
|
|
size_t lastSlash = strPath.find_last_of("/\\"); |
|
|
|
|
if (lastSlash == std::string::npos) lastSlash = 0; // 若无分隔符,从头开始
|
|
|
|
|
else lastSlash++; // 跳过分隔符
|
|
|
|
|
|
|
|
|
|
// 查找扩展名分隔符 '.' 的位置
|
|
|
|
|
size_t lastDot = strPath.find_last_of('.'); |
|
|
|
|
if (lastDot == std::string::npos) lastDot = strPath.size(); // 若无扩展名,截到末尾
|
|
|
|
|
|
|
|
|
|
// 截取文件名(不含路径和扩展名)
|
|
|
|
|
std::string strName = strPath.substr(lastSlash, lastDot - lastSlash); |
|
|
|
|
bool is_face_normal_visible_map = scene.is_face_normal_visible_map(strName.c_str(), idxFace); |
|
|
|
|
|
|
|
|
|
// load image
|
|
|
|
|
unsigned level(nResolutionLevel); |
|
|
|
|
const unsigned imageSize(imageData.RecomputeMaxResolution(level, nMinResolution)); |
|
|
|
|
if ((imageData.image.empty() || MAXF(imageData.width,imageData.height) != imageSize) && !imageData.ReloadImage(imageSize)) { |
|
|
|
|
#ifdef TEXOPT_USE_OPENMP |
|
|
|
|
bAbort = true; |
|
|
|
|
#pragma omp flush (bAbort) |
|
|
|
|
continue; |
|
|
|
|
#else |
|
|
|
|
return false; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
imageData.UpdateCamera(scene.platforms); |
|
|
|
|
// compute gradient magnitude
|
|
|
|
|
imageData.image.toGray(imageGradMag, cv::COLOR_BGR2GRAY, true); |
|
|
|
|
cv::Mat grad[2]; |
|
|
|
|
mGrad[0].resize(imageGradMag.rows, imageGradMag.cols); |
|
|
|
|
grad[0] = cv::Mat(imageGradMag.rows, imageGradMag.cols, cv::DataType<real>::type, (void*)mGrad[0].data()); |
|
|
|
|
mGrad[1].resize(imageGradMag.rows, imageGradMag.cols); |
|
|
|
|
grad[1] = cv::Mat(imageGradMag.rows, imageGradMag.cols, cv::DataType<real>::type, (void*)mGrad[1].data()); |
|
|
|
|
|
|
|
|
|
cv::Sobel(imageGradMag, grad[0], cv::DataType<real>::type, 1, 0, 3, 1.0/8.0); |
|
|
|
|
cv::Sobel(imageGradMag, grad[1], cv::DataType<real>::type, 0, 1, 3, 1.0/8.0); |
|
|
|
|
|
|
|
|
|
(TImage<real>::EMatMap)imageGradMag = (mGrad[0].cwiseAbs2()+mGrad[1].cwiseAbs2()).cwiseSqrt(); |
|
|
|
|
// apply some blur on the gradient to lower noise/glossiness effects onto face-quality score
|
|
|
|
|
cv::GaussianBlur(imageGradMag, imageGradMag, cv::Size(15, 15), 0, 0, cv::BORDER_DEFAULT); |
|
|
|
|
// select faces inside view frustum
|
|
|
|
|
Mesh::FaceIdxArr cameraFaces; |
|
|
|
|
Mesh::FacesInserter inserter(cameraFaces); |
|
|
|
|
const TFrustum<float,5> frustum(Matrix3x4f(imageData.camera.P), (float)imageData.width, (float)imageData.height); |
|
|
|
|
octree.Traverse(frustum, inserter); |
|
|
|
|
// project all triangles in this view and keep the closest ones
|
|
|
|
|
faceMap.create(imageData.GetSize()); |
|
|
|
|
depthMap.create(imageData.GetSize()); |
|
|
|
|
|
|
|
|
|
std::unordered_set<FIndex> tempFaces; |
|
|
|
|
{ |
|
|
|
|
// RasterMesh rasterer(vertices, imageData.camera, depthMap, faceMap);
|
|
|
|
|
RasterMesh rasterer(*this, vertices, imageData.camera, depthMap, faceMap, scene.mesh, false); |
|
|
|
|
RasterMesh::Triangle triangle; |
|
|
|
|
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer); |
|
|
|
|
if (nIgnoreMaskLabel >= 0) { |
|
|
|
|
// import mask
|
|
|
|
|
BitMatrix bmask; |
|
|
|
|
// std::cout << "nIgnoreMaskLabel is open" << std::endl;
|
|
|
|
|
DepthEstimator::ImportIgnoreMask(imageData, imageData.GetSize(), (uint16_t)OPTDENSE::nIgnoreMaskLabel, bmask, &rasterer.mask); |
|
|
|
|
} else if (nIgnoreMaskLabel == -1) { |
|
|
|
|
// creating mask to discard invalid regions created during image radial undistortion
|
|
|
|
|
rasterer.mask = DetectInvalidImageRegions(imageData.image); |
|
|
|
|
#if TD_VERBOSE != TD_VERBOSE_OFF |
|
|
|
|
if (VERBOSITY_LEVEL > 2) |
|
|
|
|
cv::imwrite(String::FormatString("umask%04d.png", idxView), rasterer.mask); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
rasterer.Clear(); |
|
|
|
|
for (FIndex idxFace : cameraFaces) { |
|
|
|
|
rasterer.validFace = true; |
|
|
|
|
const Face& facet = faces[idxFace]; |
|
|
|
|
rasterer.idxFace = idxFace; |
|
|
|
|
|
|
|
|
|
bool bExistFace = facesDatas[idxFace].empty(); |
|
|
|
|
// 4. 只保留最接近的3个视图
|
|
|
|
|
size_t numToKeep = colorDistances.size(); // std::min((size_t)3, colorDistances.size());
|
|
|
|
|
Color finalColor = Color::ZERO; |
|
|
|
|
float finalQuality = 0.0f; |
|
|
|
|
|
|
|
|
|
if (scene.is_face_visible(strName.c_str(), idxFace) || bExistFace) |
|
|
|
|
{ |
|
|
|
|
rasterer.Project(facet, triangleRasterizer); |
|
|
|
|
if (!rasterer.validFace) |
|
|
|
|
rasterer.Project(facet, triangleRasterizer); |
|
|
|
|
} |
|
|
|
|
for (size_t i = 0; i < numToKeep; ++i) { |
|
|
|
|
int viewIdx = colorDistances[i].second; |
|
|
|
|
finalColor += colors[viewIdx]; |
|
|
|
|
finalQuality += qualities[viewIdx]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tempFaces = PerformLocalDepthConsistencyCheck(depthMap, faceMap, scene.mesh, idxView, strName); |
|
|
|
|
} |
|
|
|
|
// 5. 计算最终颜色和质量
|
|
|
|
|
finalColor /= (float)numToKeep; |
|
|
|
|
finalQuality /= (float)numToKeep; |
|
|
|
|
|
|
|
|
|
// compute the projection area of visible faces
|
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
CLISTDEF0IDX(uint32_t,FIndex) areas(faces.size()); |
|
|
|
|
areas.Memset(0); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef TEXOPT_USE_OPENMP |
|
|
|
|
#pragma omp critical |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
for (int j=0; j<faceMap.rows; ++j) { |
|
|
|
|
for (int i=0; i<faceMap.cols; ++i) { |
|
|
|
|
const FIndex& idxFace = faceMap(j,i); |
|
|
|
|
// ASSERT((idxFace == NO_ID && depthMap(j,i) == 0) || (idxFace != NO_ID && depthMap(j,i) > 0));
|
|
|
|
|
|
|
|
|
|
if (idxFace == NO_ID) |
|
|
|
|
continue; |
|
|
|
|
faceFinalColors[idxFace] = finalColor; |
|
|
|
|
faceFinalQualities[idxFace] = finalQuality; |
|
|
|
|
|
|
|
|
|
// 第二步:更新facesDatas,只保留最终颜色和质量
|
|
|
|
|
FaceDataArr& faceDatas = facesDatas[idxFace]; |
|
|
|
|
|
|
|
|
|
const Pixel8U& pixel = imageData.image(j, i); |
|
|
|
|
// 假设是8位图像,RGB三个通道任一超过250即视为过曝
|
|
|
|
|
if (pixel.r > 250 || pixel.g > 250 || pixel.b > 250) { |
|
|
|
|
// continue;
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float brightnessPerceptual = (0.299f * pixel.r + 0.587f * pixel.g + 0.114f * pixel.b) / 255.0f; |
|
|
|
|
// printf("brightnessPerceptual=%f\n", brightnessPerceptual);
|
|
|
|
|
|
|
|
|
|
if (brightnessPerceptual>0.95f) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
if (depthMap(j,i)>999.0f) |
|
|
|
|
{ |
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
uint32_t& area = areas[idxFace]; |
|
|
|
|
if (area++ == 0) { |
|
|
|
|
#else |
|
|
|
|
if (faceDatas.empty() || faceDatas.back().idxView != idxView) { |
|
|
|
|
#endif |
|
|
|
|
// create new face-data
|
|
|
|
|
FaceData& faceData = faceDatas.emplace_back(); |
|
|
|
|
faceData.idxView = idxView; |
|
|
|
|
faceData.quality = imageGradMag(j,i); |
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
faceData.color = imageData.image(j,i); |
|
|
|
|
#endif |
|
|
|
|
faceData.bInvalidFacesRelative = true; |
|
|
|
|
} else { |
|
|
|
|
// update face-data
|
|
|
|
|
ASSERT(!faceDatas.empty()); |
|
|
|
|
FaceData& faceData = faceDatas.back(); |
|
|
|
|
ASSERT(faceData.idxView == idxView); |
|
|
|
|
faceData.quality = imageGradMag(j,i); |
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
faceData.color = Color(imageData.image(j,i)); |
|
|
|
|
#endif |
|
|
|
|
faceData.bInvalidFacesRelative = true; |
|
|
|
|
} |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t& area = areas[idxFace]; |
|
|
|
|
if (area++ == 0) { |
|
|
|
|
// create new face-data
|
|
|
|
|
FaceData& faceData = faceDatas.emplace_back(); |
|
|
|
|
faceData.idxView = idxView; |
|
|
|
|
faceData.quality = imageGradMag(j,i); |
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
faceData.color = imageData.image(j,i); |
|
|
|
|
#endif |
|
|
|
|
if (depthMap(j,i)>999.0f) |
|
|
|
|
faceData.bInvalidFacesRelative = true; |
|
|
|
|
} else { |
|
|
|
|
// update face-data
|
|
|
|
|
ASSERT(!faceDatas.empty()); |
|
|
|
|
if (!faceDatas.empty()) { |
|
|
|
|
// 只保留第一个FaceData,并用最终颜色和质量更新它
|
|
|
|
|
faceDatas.resize(1); |
|
|
|
|
FaceData& faceData = faceDatas.back(); |
|
|
|
|
ASSERT(faceData.idxView == idxView); |
|
|
|
|
faceData.quality += imageGradMag(j,i); |
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
faceData.color += Color(imageData.image(j,i)); |
|
|
|
|
#endif |
|
|
|
|
if (depthMap(j,i)>999.0f) |
|
|
|
|
faceData.bInvalidFacesRelative = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// adjust face quality with camera angle relative to face normal
|
|
|
|
|
// tries to increase chances of a camera with perpendicular view on the surface (smoothened normals) to be selected
|
|
|
|
|
FOREACH(idxFace, facesDatas) { |
|
|
|
|
FaceDataArr& faceDatas = facesDatas[idxFace]; |
|
|
|
|
if (faceDatas.empty() || faceDatas.back().idxView != idxView) |
|
|
|
|
continue; |
|
|
|
|
const Face& f = faces[idxFace]; |
|
|
|
|
const Vertex faceCenter((vertices[f[0]] + vertices[f[1]] + vertices[f[2]]) / 3.f); |
|
|
|
|
const Point3f camDir(Cast<Mesh::Type>(imageData.camera.C) - faceCenter); |
|
|
|
|
const Normal& faceNormal = scene.mesh.faceNormals[idxFace]; |
|
|
|
|
const float cosFaceCam(MAXF(0.001f, ComputeAngle(camDir.ptr(), faceNormal.ptr()))); |
|
|
|
|
faceDatas.back().quality *= SQUARE(cosFaceCam); |
|
|
|
|
} |
|
|
|
|
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA |
|
|
|
|
FOREACH(idxFace, areas) { |
|
|
|
|
const uint32_t& area = areas[idxFace]; |
|
|
|
|
if (area > 0) { |
|
|
|
|
Color& color = facesDatas[idxFace].back().color; |
|
|
|
|
color = RGB2YCBCR(Color(color * (1.f/(float)area))); |
|
|
|
|
faceData.quality = finalQuality; |
|
|
|
|
faceData.color = finalColor; |
|
|
|
|
// 注意:这里不再保留原始的idxView,因为颜色是多个视图的混合
|
|
|
|
|
// 您可能需要根据需要调整idxView的值
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
++progress; |
|
|
|
|
} |
|
|
|
|
//*/
|
|
|
|
|
// Temp
|
|
|
|
|
|
|
|
|
|
@ -3300,6 +3034,7 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
@@ -3300,6 +3034,7 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
|
|
|
|
|
|
|
|
|
|
if (angleDeg <= 45.0f) |
|
|
|
|
{ |
|
|
|
|
if (scene.is_face_normal_visible_map(strName, virtualFaceCenterFaceID)) |
|
|
|
|
filteredCams.push_back(idxView); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@ -3323,6 +3058,8 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
@@ -3323,6 +3058,8 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
if (scene.is_face_normal_visible_map(strName, virtualFaceCenterFaceID)) |
|
|
|
|
filteredCams.push_back(idxView); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@ -3757,8 +3494,12 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
@@ -3757,8 +3494,12 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
|
|
|
|
|
#endif |
|
|
|
|
// virtualFaceData.quality = avgQuality;
|
|
|
|
|
// virtualFaceData.color = sortedLuminViews[0].second;
|
|
|
|
|
|
|
|
|
|
virtualFaceData.quality = medianQuality; |
|
|
|
|
virtualFaceData.color = medianColor; |
|
|
|
|
|
|
|
|
|
// virtualFaceData.quality = 0;
|
|
|
|
|
// virtualFaceData.color = Point3f::ZERO;
|
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
// 使用过滤后的视图重新计算平均值
|
|
|
|
|
@ -3775,6 +3516,9 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
@@ -3775,6 +3516,9 @@ bool MeshTexture::CreateVirtualFaces6(FaceDataViewArr& facesDatas, FaceDataViewA
|
|
|
|
|
} |
|
|
|
|
virtualFaceData.quality = totalQuality2 / validIndices.size(); |
|
|
|
|
virtualFaceData.color = totalColor2 / validIndices.size(); |
|
|
|
|
|
|
|
|
|
// virtualFaceData.quality = 0;
|
|
|
|
|
// virtualFaceData.color = Point3f::ZERO;
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (validViewsSize>0&&validViewsSize<=2&&false) |
|
|
|
|
@ -4450,6 +4194,35 @@ MeshTexture::FaceDataArr MeshTexture::MergeFaceData(const FaceDataArr& data1, co
@@ -4450,6 +4194,35 @@ MeshTexture::FaceDataArr MeshTexture::MergeFaceData(const FaceDataArr& data1, co
|
|
|
|
|
return mergedData; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string MeshTexture::GetFileNameWithoutExtension(std::string& strPath) { |
|
|
|
|
// 查找最后一个路径分隔符(支持'/'和'\')
|
|
|
|
|
size_t lastSlash = strPath.find_last_of("/\\"); |
|
|
|
|
|
|
|
|
|
// 确定文件名的起始位置
|
|
|
|
|
if (lastSlash == std::string::npos) { |
|
|
|
|
lastSlash = 0; // 没有路径分隔符,从字符串开头开始
|
|
|
|
|
} else { |
|
|
|
|
lastSlash++; // 跳过分隔符
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 查找最后一个扩展名分隔符'.'的位置
|
|
|
|
|
size_t lastDot = strPath.find_last_of('.'); |
|
|
|
|
|
|
|
|
|
// 如果没有扩展名分隔符,则截取到字符串末尾
|
|
|
|
|
if (lastDot == std::string::npos) { |
|
|
|
|
lastDot = strPath.length(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 截取文件名(不含路径和扩展名)
|
|
|
|
|
// 注意:如果lastDot <= lastSlash,说明点号在路径中,而不是在文件名中
|
|
|
|
|
if (lastDot <= lastSlash) { |
|
|
|
|
// 点号在路径中,没有扩展名
|
|
|
|
|
return strPath.substr(lastSlash); |
|
|
|
|
} else { |
|
|
|
|
// 有扩展名,去掉扩展名
|
|
|
|
|
return strPath.substr(lastSlash, lastDot - lastSlash); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataViewArr& virtualFacesDatas, VirtualFaceIdxsArr& virtualFaces, std::vector<bool>& isVirtualFace, unsigned minCommonCameras, float thMaxNormalDeviation) const |
|
|
|
|
{ |
|
|
|
|
@ -4646,8 +4419,11 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
@@ -4646,8 +4419,11 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// if (angleDeg <= 30.0f)
|
|
|
|
|
{ |
|
|
|
|
filteredCams.push_back(idxView); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
float brightnessScore = CalculateBrightnessScore(imageData); // 亮度评分函数
|
|
|
|
|
@ -4746,6 +4522,10 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
@@ -4746,6 +4522,10 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|
|
|
|
#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); |
|
|
|
|
@ -4818,6 +4598,8 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
@@ -4818,6 +4598,8 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|
|
|
|
if (colorDistance <= maxColorDeviation && |
|
|
|
|
luminanceDistance <= maxLuminanceDeviation) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
if (scene.is_face_normal_visible_map(strName, virtualFaceCenterFaceID)) |
|
|
|
|
validIndices.push_back(n); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
@ -4842,7 +4624,9 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
@@ -4842,7 +4624,9 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|
|
|
|
if (cosFaceToCenter<dynamicCosTh) |
|
|
|
|
{ |
|
|
|
|
if (nInvalidViewCount<=2) |
|
|
|
|
{ |
|
|
|
|
validIndices.push_back(n); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// if ((colorDistance <= 350.0f))
|
|
|
|
|
@ -4852,7 +4636,9 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
@@ -4852,7 +4636,9 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
if (nInvalidViewCount<=2) |
|
|
|
|
{ |
|
|
|
|
validIndices.push_back(n); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// if (bColorSimilarity)
|
|
|
|
|
@ -4942,6 +4728,11 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
@@ -4942,6 +4728,11 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|
|
|
|
|
|
|
|
|
virtualFaceData.quality = medianQuality; |
|
|
|
|
virtualFaceData.color = medianColor; |
|
|
|
|
|
|
|
|
|
// virtualFaceData.quality = 0;
|
|
|
|
|
// #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
|
|
|
|
// virtualFaceData.color = Point3f::ZERO;
|
|
|
|
|
// #endif
|
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
// 使用过滤后的视图重新计算平均值
|
|
|
|
|
@ -4953,6 +4744,11 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
@@ -4953,6 +4744,11 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
|
|
|
|
} |
|
|
|
|
virtualFaceData.quality = totalQuality2 / validIndices.size(); |
|
|
|
|
virtualFaceData.color = totalColor2 / validIndices.size(); |
|
|
|
|
|
|
|
|
|
// virtualFaceData.quality = 0;
|
|
|
|
|
// #if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
|
|
|
|
// virtualFaceData.color = Point3f::ZERO;
|
|
|
|
|
// #endif
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -7630,12 +7426,16 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
@@ -7630,12 +7426,16 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
|
|
|
|
} |
|
|
|
|
//*/
|
|
|
|
|
//*
|
|
|
|
|
// int n = 0;
|
|
|
|
|
// 修改后安全版本
|
|
|
|
|
FOREACH(l, labels) { |
|
|
|
|
if (l < mapFaceToVirtualFace.size()) { |
|
|
|
|
const size_t virtualIdx = mapFaceToVirtualFace[l]; |
|
|
|
|
if (virtualIdx < virtualLabels.size()) { |
|
|
|
|
// if (n < 100)
|
|
|
|
|
labels[l] = virtualLabels[virtualIdx]; |
|
|
|
|
// else
|
|
|
|
|
// labels[l] = NO_ID;
|
|
|
|
|
} else { |
|
|
|
|
labels[l] = NO_ID; |
|
|
|
|
DEBUG_EXTRA("Warning: Invalid virtual face index for face %u: %u (max: %u)", |
|
|
|
|
@ -7646,6 +7446,8 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
@@ -7646,6 +7446,8 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
|
|
|
|
DEBUG_EXTRA("Warning: Face index out of bounds: %u (max: %u)", |
|
|
|
|
l, mapFaceToVirtualFace.size()-1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ++n;
|
|
|
|
|
} |
|
|
|
|
//*/
|
|
|
|
|
// 修改后安全版本
|
|
|
|
|
@ -10600,6 +10402,7 @@ bool Scene::LoadVisibleFacesData(std::map<std::string, std::unordered_set<int>>&
@@ -10600,6 +10402,7 @@ bool Scene::LoadVisibleFacesData(std::map<std::string, std::unordered_set<int>>&
|
|
|
|
|
std::unordered_set<int>& face_visible_relative, |
|
|
|
|
std::map<std::string, std::unordered_set<int>>& edge_faces_map, |
|
|
|
|
std::map<std::string, std::unordered_set<int>>& delete_edge_faces_map, |
|
|
|
|
std::map<std::string, std::unordered_set<int>>& face_normal_visible_map, |
|
|
|
|
std::string& basePath) { |
|
|
|
|
printf("LoadVisibleFacesData %s\n", basePath.c_str()); |
|
|
|
|
std::ifstream mapFile(basePath + "_visible_faces_map.txt"); |
|
|
|
|
@ -10668,6 +10471,24 @@ bool Scene::LoadVisibleFacesData(std::map<std::string, std::unordered_set<int>>&
@@ -10668,6 +10471,24 @@ bool Scene::LoadVisibleFacesData(std::map<std::string, std::unordered_set<int>>&
|
|
|
|
|
} |
|
|
|
|
mapFile3.close(); |
|
|
|
|
|
|
|
|
|
std::ifstream mapFile4(basePath + "_face_normal_visible_map.txt"); |
|
|
|
|
if (!mapFile4.is_open()) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (std::getline(mapFile4, line)) { |
|
|
|
|
std::istringstream iss(line); |
|
|
|
|
std::string image_name; |
|
|
|
|
iss >> image_name; |
|
|
|
|
std::unordered_set<int> faces; |
|
|
|
|
int face_index; |
|
|
|
|
while (iss >> face_index) { |
|
|
|
|
faces.insert(face_index); |
|
|
|
|
} |
|
|
|
|
face_normal_visible_map[image_name] = faces; |
|
|
|
|
} |
|
|
|
|
mapFile4.close(); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -10766,7 +10587,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi
@@ -10766,7 +10587,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi
|
|
|
|
|
|
|
|
|
|
// printf("basePath=%s\n", basePath.c_str());
|
|
|
|
|
|
|
|
|
|
if (!LoadVisibleFacesData(visible_faces_map, face_visible_relative, edge_faces_map, delete_edge_faces_map, basePath)) |
|
|
|
|
if (!LoadVisibleFacesData(visible_faces_map, face_visible_relative, edge_faces_map, delete_edge_faces_map, face_normal_visible_map, basePath)) |
|
|
|
|
{ |
|
|
|
|
printf("LoadVisibleFacesData error\n"); |
|
|
|
|
} |
|
|
|
|
@ -10920,6 +10741,20 @@ bool Scene::is_face_delete_edge(const std::string& image_name, int face_index) {
@@ -10920,6 +10741,20 @@ bool Scene::is_face_delete_edge(const std::string& image_name, int face_index) {
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Scene::is_face_normal_visible_map(const std::string& image_name, int face_index) { |
|
|
|
|
|
|
|
|
|
#ifndef MASK_FACE_OCCLUSION |
|
|
|
|
return true; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
auto it = face_normal_visible_map.find(image_name); |
|
|
|
|
if (it != face_normal_visible_map.end()) { |
|
|
|
|
return it->second.find(face_index) != it->second.end(); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Scene::SegmentMeshBasedOnCurvature(Mesh::FaceIdxArr& regionMap, float curvatureThreshold) { |
|
|
|
|
// 确保网格数据有效
|
|
|
|
|
if (mesh.faces.empty() || mesh.vertices.empty() || |
|
|
|
|
|