清晰化

This commit is contained in:
hesuicong committed 2026-10-20 11:24:50 +08:00
1 parent 6b67c75c7e
commit 272d3900d0
1 file changed
+68 -20
+68 -20
View File
@@ -828,6 +828,50 @@ public:
Pixel8U colEmpty, Pixel8U colEmpty,
Mesh::Image8U3Arr& outTextures); Mesh::Image8U3Arr& outTextures);
inline float ComputeLocalVariance(const cv::Mat& image, int patchW, int patchH) {
cv::Mat gray;
if (image.channels() == 3) {
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
} else {
gray = image.clone();
}
// 1. 局部方差
cv::Mat mean, sqrMean;
cv::boxFilter(gray, mean, CV_32F, cv::Size(5, 5));
cv::boxFilter(gray.mul(gray), sqrMean, CV_32F, cv::Size(5, 5));
cv::Mat variance = sqrMean - mean.mul(mean);
float varScore = cv::mean(variance)[0] / 0.08f;
// 2. 梯度幅值
cv::Mat gradX, gradY;
cv::Sobel(gray, gradX, CV_32F, 1, 0, 3);
cv::Sobel(gray, gradY, CV_32F, 0, 1, 3);
cv::Mat magnitude;
cv::magnitude(gradX, gradY, magnitude);
float gradScore = cv::mean(magnitude)[0] * 3.0f;
// 3. 直方图熵(可选,衡量纹理丰富度)
int histSize = 256;
float range[] = {0, 256};
const float* histRange = {range};
cv::Mat hist;
cv::calcHist(&gray, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange);
hist /= gray.total();
float entropy = 0;
for (int i = 0; i < histSize; i++) {
float p = hist.at<float>(i);
if (p > 0) entropy -= p * log2f(p);
}
float entropyScore = entropy / 8.0f; // 8 bits 的最大熵
// 综合评分(可调整权重)
float complexity = 0.4f * varScore + 0.4f * gradScore + 0.2f * entropyScore;
return std::min(complexity, 1.0f);
}
inline bool ComputeBarycentric(float u, float v, inline bool ComputeBarycentric(float u, float v,
const TexCoord& uv0, const TexCoord& uv1, const TexCoord& uv2, const TexCoord& uv0, const TexCoord& uv1, const TexCoord& uv2,
float& b0, float& b1, float& b2) { float& b0, float& b1, float& b2) {
@@ -16664,8 +16708,8 @@ bool MeshTexture::RasterizeVirtualFaces(
mainPatch.convertTo(mainFloat, CV_32FC3, 1.0f / 255.0f); mainPatch.convertTo(mainFloat, CV_32FC3, 1.0f / 255.0f);
cv::Mat mainLowFreq; cv::Mat mainLowFreq;
cv::GaussianBlur(mainFloat, mainLowFreq, cv::Size(31, 31), 10.0); cv::GaussianBlur(mainFloat, mainLowFreq, cv::Size(5, 5), 1.5);
cv::Mat highFreqAccum = (mainFloat - mainLowFreq) * 0.6f; cv::Mat highFreqAccum = (mainFloat - mainLowFreq) * 0.9f;
float highFreqTotalWeight = 0.6f; float highFreqTotalWeight = 0.6f;
if (hasLowFreqViews) { if (hasLowFreqViews) {
@@ -16695,12 +16739,12 @@ bool MeshTexture::RasterizeVirtualFaces(
cv::Mat highFreq = highFreqAccum; cv::Mat highFreq = highFreqAccum;
// ========== 每个顶点独立判断可见性(增强版)========== // ========== 每个顶点独立判断可见性(增强版)==========
bool vertexVisible[3] = {false, false, false}; bool vertexVisible[3] = {false, false, false};
cv::Vec3f vertexBestColor[3] = {cv::Vec3f(0,0,0), cv::Vec3f(0,0,0), cv::Vec3f(0,0,0)}; cv::Vec3f vertexBestColor[3] = {cv::Vec3f(0,0,0), cv::Vec3f(0,0,0), cv::Vec3f(0,0,0)};
// 检查主视图 // 检查主视图
for (int j = 0; j < 3; ++j) { for (int j = 0; j < 3; ++j) {
int vx = (int)(uv[j].x * textureSize) - minX; int vx = (int)(uv[j].x * textureSize) - minX;
int vy = (int)(uv[j].y * textureSize) - minY; int vy = (int)(uv[j].y * textureSize) - minY;
if (vx >= 0 && vx < patchW && vy >= 0 && vy < patchH) { if (vx >= 0 && vx < patchW && vy >= 0 && vy < patchH) {
@@ -16710,10 +16754,10 @@ for (int j = 0; j < 3; ++j) {
vertexBestColor[j] = color; vertexBestColor[j] = color;
} }
} }
} }
// 如果主视图不可见,检查辅助视图 // 如果主视图不可见,检查辅助视图
if (hasLowFreqViews && (!vertexVisible[0] || !vertexVisible[1] || !vertexVisible[2])) { if (hasLowFreqViews && (!vertexVisible[0] || !vertexVisible[1] || !vertexVisible[2])) {
for (const auto& lfv : lowFreqViews) { for (const auto& lfv : lowFreqViews) {
if (lfv.viewId >= (IIndex)images.size() || images[lfv.viewId].image.empty()) continue; if (lfv.viewId >= (IIndex)images.size() || images[lfv.viewId].image.empty()) continue;
@@ -16760,10 +16804,10 @@ if (hasLowFreqViews && (!vertexVisible[0] || !vertexVisible[1] || !vertexVisible
if (vertexVisible[0] && vertexVisible[1] && vertexVisible[2]) if (vertexVisible[0] && vertexVisible[1] && vertexVisible[2])
break; break;
} }
} }
#pragma omp critical (vertex_visibility) #pragma omp critical (vertex_visibility)
{ {
for (int j = 0; j < 3; ++j) { for (int j = 0; j < 3; ++j) {
VIndex vi = face[j]; VIndex vi = face[j];
if (vi < m_vertexColors.size() && vertexVisible[j]) { if (vi < m_vertexColors.size() && vertexVisible[j]) {
@@ -16771,7 +16815,7 @@ if (hasLowFreqViews && (!vertexVisible[0] || !vertexVisible[1] || !vertexVisible
m_vertexColors[vi].mainColor = vertexBestColor[j]; m_vertexColors[vi].mainColor = vertexBestColor[j];
} }
} }
} }
// ========== 空洞填充与合成 ========== // ========== 空洞填充与合成 ==========
cv::Mat filledLowFreq = lowFreqPatch.clone(); cv::Mat filledLowFreq = lowFreqPatch.clone();
@@ -16784,7 +16828,10 @@ if (hasLowFreqViews && (!vertexVisible[0] || !vertexVisible[1] || !vertexVisible
} }
} }
cv::Mat finalPatch = filledLowFreq * 0.7f + mainFloat * 0.3f; // 使用自适应权重,根据纹理复杂度决定
float textureComplexity = ComputeLocalVariance(mainFloat, patchW, patchH);
float lowFreqWeight = 0.3f + 0.4f * (1.0f - textureComplexity);
cv::Mat finalPatch = filledLowFreq * lowFreqWeight + mainFloat * (1.0f - lowFreqWeight);
// 钳制到 [0, 1] // 钳制到 [0, 1]
cv::Mat clampedPatch; cv::Mat clampedPatch;
@@ -16816,7 +16863,8 @@ if (hasLowFreqViews && (!vertexVisible[0] || !vertexVisible[1] || !vertexVisible
if (minDist < pad) { if (minDist < pad) {
weight = minDist / (float)pad; weight = minDist / (float)pad;
weight = weight * weight; // 使用线性衰减而非平方衰减
weight = std::min(minDist / (float)pad, 1.0f); // 原 weight * weight
} }
if (currentScore > m_texelScores[idx].score) { if (currentScore > m_texelScores[idx].score) {
@@ -16920,10 +16968,10 @@ if (hasLowFreqViews && (!vertexVisible[0] || !vertexVisible[1] || !vertexVisible
// 找到这个像素属于哪个面 // 找到这个像素属于哪个面
int patchID = m_texelPatchID[idx]; int patchID = m_texelPatchID[idx];
if (patchID >= (int)virtualFaceMap.size()) if (patchID >= (int)virtualFaceMap.size())
continue; continue;
if (patchID == NO_ID) { if (patchID == NO_ID) {
// 尝试找最近的已填充像素 // 尝试找最近的已填充像素
int bestDist = INT_MAX; int bestDist = INT_MAX;
int bestPatchID = NO_ID; int bestPatchID = NO_ID;
@@ -16947,7 +16995,7 @@ if (patchID == NO_ID) {
} else { } else {
continue; // 实在找不到归属面,跳过 continue; // 实在找不到归属面,跳过
} }
} }
const VirtualFace& vf = virtualFaceMap[patchID]; const VirtualFace& vf = virtualFaceMap[patchID];
if (vf.faces.empty()) continue; if (vf.faces.empty()) continue;
@@ -16993,7 +17041,7 @@ if (patchID == NO_ID) {
fillColor = vertexColors[bestVertex]; fillColor = vertexColors[bestVertex];
} }
// ★★★ 新增:检查 fillColor 是否有效(接近黑色)★★★ // ★★★ 新增:检查 fillColor 是否有效(接近黑色)★★★
bool fillIsBlack = (fillColor[0] < 0.05f && fillColor[1] < 0.05f && fillColor[2] < 0.05f); bool fillIsBlack = (fillColor[0] < 0.05f && fillColor[1] < 0.05f && fillColor[2] < 0.05f);
if (fillIsBlack) { if (fillIsBlack) {
// Fallback:从邻近非空洞像素采样 // Fallback:从邻近非空洞像素采样