|
|
|
|
@ -677,6 +677,10 @@ public:
@@ -677,6 +677,10 @@ public:
|
|
|
|
|
Pixel8U colEmpty, |
|
|
|
|
Mesh::Image8U3Arr& outTextures); |
|
|
|
|
|
|
|
|
|
float ComputeComprehensiveScore(const FaceData& data, const Normal& faceNormal, |
|
|
|
|
const Point3f& faceCenter, const Image& image); |
|
|
|
|
float EstimatePixelSize(const Point3f& faceCenter, const Normal& faceNormal, |
|
|
|
|
const Image& image); |
|
|
|
|
bool TextureWithExistingUVVirtualFaces(const IIndexArr& views, int nIgnoreMaskLabel, |
|
|
|
|
float fOutlierThreshold, unsigned nTextureSizeMultiple, |
|
|
|
|
Pixel8U colEmpty, float fSharpnessWeight); |
|
|
|
|
@ -14211,6 +14215,91 @@ bool MeshTexture::RasterizeVirtualFaces(
@@ -14211,6 +14215,91 @@ bool MeshTexture::RasterizeVirtualFaces(
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float MeshTexture::EstimatePixelSize(const Point3f& faceCenter, const Normal& faceNormal, |
|
|
|
|
const Image& image) { |
|
|
|
|
// 获取面片的近似面积(使用网格中存储的面片面积,如果有的话)
|
|
|
|
|
// 如果没有,我们可以通过三角形面积公式计算
|
|
|
|
|
// 这里假设我们有一个方法获取面片面积,或者通过顶点计算
|
|
|
|
|
|
|
|
|
|
// 简化版本:使用面片到相机的距离和相机焦距来估算像素大小
|
|
|
|
|
const Camera& cam = image.camera; |
|
|
|
|
// ✅ 转换为 cv::Point3d 进行计算
|
|
|
|
|
cv::Point3d fc_d(faceCenter.x, faceCenter.y, faceCenter.z); |
|
|
|
|
cv::Point3d camC = cam.C; |
|
|
|
|
|
|
|
|
|
// 计算视线方向
|
|
|
|
|
cv::Point3d viewDir_d = camC - fc_d; |
|
|
|
|
double norm = cv::norm(viewDir_d); |
|
|
|
|
if (norm > 1e-6) { |
|
|
|
|
viewDir_d /= norm; // 手动归一化
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 转回 Point3f(如果需要)
|
|
|
|
|
Point3f viewDir( |
|
|
|
|
static_cast<float>(viewDir_d.x), |
|
|
|
|
static_cast<float>(viewDir_d.y), |
|
|
|
|
static_cast<float>(viewDir_d.z) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// 计算面片在图像平面上的投影面积
|
|
|
|
|
// 使用一个近似的正方形面片模型
|
|
|
|
|
float dist = (float)cv::norm(faceCenter - (Point3f)cam.C); |
|
|
|
|
if (dist < 1e-6f) return 0.0f; |
|
|
|
|
|
|
|
|
|
// 估算面片在图像平面上的大小(像素)
|
|
|
|
|
// 假设面片是边长为1米的正方形(实际应根据面片真实面积调整)
|
|
|
|
|
float approxFaceSize = 1.0f; // 米
|
|
|
|
|
|
|
|
|
|
// 计算像素大小:focal_length * (object_size / distance)
|
|
|
|
|
float pixelSize = cam.GetFocalLength() * (approxFaceSize / dist); |
|
|
|
|
|
|
|
|
|
// 转换为像素单位(考虑传感器尺寸和图像分辨率)
|
|
|
|
|
// 这里假设相机内参已经考虑了这些因素
|
|
|
|
|
return pixelSize; |
|
|
|
|
} |
|
|
|
|
// 综合评分函数(完全修正版)
|
|
|
|
|
float MeshTexture::ComputeComprehensiveScore(const FaceData& data, const Normal& faceNormal, |
|
|
|
|
const Point3f& faceCenter, const Image& image) { |
|
|
|
|
// ✅ 全部使用 OpenCV 的 double 类型进行计算
|
|
|
|
|
cv::Point3d fc_d(faceCenter.x, faceCenter.y, faceCenter.z); |
|
|
|
|
cv::Point3d camC = image.camera.C; |
|
|
|
|
|
|
|
|
|
// ---------- 正对程度(最重要)----------
|
|
|
|
|
// 计算视线方向(从面片指向相机)
|
|
|
|
|
cv::Point3d viewDir = camC - fc_d; |
|
|
|
|
double viewDirLen = cv::norm(viewDir); |
|
|
|
|
if (viewDirLen > 1e-6) { |
|
|
|
|
viewDir /= viewDirLen; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 法线转 double
|
|
|
|
|
cv::Point3d normal_d(faceNormal.x, faceNormal.y, faceNormal.z); |
|
|
|
|
|
|
|
|
|
// 计算正面度
|
|
|
|
|
double dot = normal_d.dot(viewDir); |
|
|
|
|
float frontalness = static_cast<float>((dot + 1.0) * 0.5); |
|
|
|
|
|
|
|
|
|
// 基础质量
|
|
|
|
|
float score = data.quality; |
|
|
|
|
score *= frontalness * frontalness; // 平方增强正面偏好
|
|
|
|
|
|
|
|
|
|
// ---------- 距离因子 ----------
|
|
|
|
|
double dist = cv::norm(fc_d - camC); |
|
|
|
|
double focal = image.camera.GetFocalLength(); |
|
|
|
|
|
|
|
|
|
// ✅ 使用 RC 风格的高斯衰减(比线性衰减更好)
|
|
|
|
|
double idealDist = 8.0 * focal; // 经验值
|
|
|
|
|
double relDist = dist / idealDist; |
|
|
|
|
double distScore = std::exp(-0.5 * relDist * relDist); |
|
|
|
|
score *= static_cast<float>(distScore); |
|
|
|
|
|
|
|
|
|
// ---------- 分辨率因子 ----------
|
|
|
|
|
float pixelSize = EstimatePixelSize(faceCenter, faceNormal, image); |
|
|
|
|
float resolutionScore = std::min(1.0f, pixelSize / 50.0f); // 至少50像素
|
|
|
|
|
score *= resolutionScore; |
|
|
|
|
|
|
|
|
|
return score; |
|
|
|
|
} |
|
|
|
|
bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int nIgnoreMaskLabel, |
|
|
|
|
float fOutlierThreshold, unsigned nTextureSizeMultiple, |
|
|
|
|
Pixel8U colEmpty, float fSharpnessWeight) |
|
|
|
|
@ -14267,50 +14356,34 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int
@@ -14267,50 +14356,34 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int
|
|
|
|
|
const FIndex fid = virtualFaceMap[idxVF].faces[0]; |
|
|
|
|
const FaceDataArr& vfDatas = virtualFaceDatas[idxVF]; |
|
|
|
|
|
|
|
|
|
float bestWeight = -1.0f; |
|
|
|
|
float bestScore = -1.0f; |
|
|
|
|
IIndex bestViewID = IIndex(-1); |
|
|
|
|
|
|
|
|
|
// 获取面片中心(用于计算距离和视角)
|
|
|
|
|
const Face& face = scene.mesh.faces[fid]; |
|
|
|
|
Point3f faceCenter = (scene.mesh.vertices[face[0]] + |
|
|
|
|
scene.mesh.vertices[face[1]] + |
|
|
|
|
scene.mesh.vertices[face[2]]) / 3.0f; |
|
|
|
|
|
|
|
|
|
const Normal& faceNormal = scene.mesh.faceNormals[fid]; |
|
|
|
|
|
|
|
|
|
// 遍历能看到这个面片的所有相机
|
|
|
|
|
for (const FaceData& data : vfDatas) { |
|
|
|
|
if (data.bInvalidFacesRelative) continue; |
|
|
|
|
|
|
|
|
|
// 基础质量分数
|
|
|
|
|
float weight = data.quality; |
|
|
|
|
|
|
|
|
|
// 加上法线夹角权重(正对相机的权重更高)
|
|
|
|
|
const Image& image = images[data.idxView]; |
|
|
|
|
Point3d camDir(0, 0, -1); |
|
|
|
|
camDir = image.camera.R * camDir; |
|
|
|
|
|
|
|
|
|
const double len = sqrt(camDir.x*camDir.x + camDir.y*camDir.y + camDir.z*camDir.z); |
|
|
|
|
if (len > 0.0) { |
|
|
|
|
camDir.x /= len; |
|
|
|
|
camDir.y /= len; |
|
|
|
|
camDir.z /= len; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Point3f cameraForward(static_cast<float>(camDir.x), |
|
|
|
|
static_cast<float>(camDir.y), |
|
|
|
|
static_cast<float>(camDir.z)); |
|
|
|
|
|
|
|
|
|
const Normal& faceNormal = scene.mesh.faceNormals[fid]; |
|
|
|
|
float dotProduct = faceNormal.dot(cameraForward); |
|
|
|
|
dotProduct = std::clamp(dotProduct, -1.f, 1.f); |
|
|
|
|
float angleWeight = (dotProduct + 1.0f) * 0.5f; |
|
|
|
|
|
|
|
|
|
// 综合权重
|
|
|
|
|
const float wQuality = 0.7f; |
|
|
|
|
const float wAngle = 0.3f; |
|
|
|
|
float finalWeight = weight * wQuality + angleWeight * wAngle; |
|
|
|
|
// 使用综合评分函数
|
|
|
|
|
float score = ComputeComprehensiveScore(data, faceNormal, faceCenter, image); |
|
|
|
|
|
|
|
|
|
if (finalWeight > bestWeight) { |
|
|
|
|
bestWeight = finalWeight; |
|
|
|
|
if (score > bestScore) { |
|
|
|
|
bestScore = score; |
|
|
|
|
bestViewID = data.idxView; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 如果找到了有效的视图
|
|
|
|
|
if (bestViewID != IIndex(-1) && bestWeight > 0.1f) { |
|
|
|
|
if (bestViewID != IIndex(-1) && bestScore > 0.1f) { |
|
|
|
|
virtualFaceViews[idxVF] = { bestViewID }; |
|
|
|
|
virtualFaceViewWeights[idxVF] = { 1.0f }; // 单视图权重设为1
|
|
|
|
|
} else { |
|
|
|
|
@ -14355,10 +14428,15 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int
@@ -14355,10 +14428,15 @@ bool MeshTexture::TextureWithExistingUVVirtualFaces(const IIndexArr& views, int
|
|
|
|
|
scene.mesh.faceTexindices[i] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 6.3 可选的锐化处理
|
|
|
|
|
// 6.3 可选的锐化处理(使用更强的锐化)
|
|
|
|
|
if (fSharpnessWeight > 0) { |
|
|
|
|
DEBUG_EXTRA("Applying sharpness filter (weight: %.2f)", fSharpnessWeight); |
|
|
|
|
// ApplySharpening(scene.mesh.texturesDiffuse[0], fSharpnessWeight);
|
|
|
|
|
// 使用Unsharp Mask锐化
|
|
|
|
|
cv::Mat textureMat = scene.mesh.texturesDiffuse[0]; |
|
|
|
|
cv::Mat blurred; |
|
|
|
|
cv::GaussianBlur(textureMat, blurred, cv::Size(0, 0), 1.0); |
|
|
|
|
cv::addWeighted(textureMat, 1.0 + fSharpnessWeight, |
|
|
|
|
blurred, -fSharpnessWeight, 0, textureMat); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 6.4 保存纹理
|
|
|
|
|
|