解决矩形杂色和色差问题

This commit is contained in:
hesuicong committed 2026-10-16 18:13:21 +08:00
1 parent b106a7976e
commit 351a0a274f
1 file changed
+80 -13
+80 -13
View File
@@ -16503,7 +16503,7 @@ bool MeshTexture::RasterizeVirtualFaces(
continue;
}
// ========== 用重心坐标 + 3D 投影替代 homography ==========
// ========== 用重心坐标 + 3D 投影替代 homography ==========
cv::Mat mapX(patchH, patchW, CV_32FC1), mapY(patchH, patchW, CV_32FC1);
mapX.setTo(-1);
mapY.setTo(-1);
@@ -16513,6 +16513,14 @@ bool MeshTexture::RasterizeVirtualFaces(
FIndex faceIdx = vf.faces[0];
const Face& face = scene.mesh.faces[faceIdx];
// 提取 3D 顶点和 UV
Point3f v[3];
TexCoord uv[3];
for (int j = 0; j < 3; ++j) {
v[j] = scene.mesh.vertices[face[j]];
uv[j] = scene.mesh.faceTexcoords[faceIdx * 3 + j]; // 注意这里的索引方式
}
// 获取相机参数
const Camera& cam = images[mainView].camera;
bool camValid = (cam.K(0,0) > 0 && cam.K(1,1) > 0);
@@ -16529,14 +16537,6 @@ bool MeshTexture::RasterizeVirtualFaces(
}
}
} else {
// 提取 3D 顶点和 UV
Point3f v[3];
TexCoord uv[3];
for (int j = 0; j < 3; ++j) {
v[j] = scene.mesh.vertices[face[j]];
uv[j] = scene.mesh.faceTexcoords[faceIdx * 3 + j]; // 注意这里的索引方式
}
// 对 patch 内每个像素做重心坐标投影
for (int py = minY; py <= maxY; ++py) {
for (int px = minX; px <= maxX; ++px) {
@@ -16570,16 +16570,68 @@ bool MeshTexture::RasterizeVirtualFaces(
cv::Mat mainPatch;
cv::remap(images[mainView].image, mainPatch, mapX, mapY, cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0,0,0));
// ========== 从辅助视图采样(全部用主视图的映射)==========
// ========== 从辅助视图采样(每个视图用自己的 3D 投影)==========
cv::Mat lowFreqPatch(patchH, patchW, CV_32FC3, cv::Scalar(0,0,0));
if (hasLowFreqViews) {
float totalWeight = 0;
for (const auto& lfv : lowFreqViews) {
if (lfv.viewId >= (IIndex)images.size() || images[lfv.viewId].image.empty()) continue;
// ★★★ 所有视图都用主视图的 mapX/mapY,不再各自构建 homography ★★★
// ★★★ 每个辅助视图用自己的相机做 3D 投影 ★★★
const Camera& auxCam = images[lfv.viewId].camera;
bool auxCamValid = (auxCam.K(0,0) > 0 && auxCam.K(1,1) > 0);
cv::Mat auxMapX(patchH, patchW, CV_32FC1), auxMapY(patchH, patchW, CV_32FC1);
auxMapX.setTo(-1);
auxMapY.setTo(-1);
if (!auxCamValid) {
// fallback 到该视图的 homography
const auto& geom = m_virtualFaceGeometries[i];
auto it = geom.viewHomographies.find(lfv.viewId);
if (it == geom.viewHomographies.end()) continue;
const float* H = it->second.ptr<float>();
for (int y = minY; y <= maxY; ++y) {
for (int x = minX; x <= maxX; ++x) {
float u = (float)x / (float)textureSize, v = (float)y / (float)textureSize;
float w = H[6]*u + H[7]*v + H[8];
if (std::abs(w) < 1e-12f) {
auxMapX.at<float>(y-minY,x-minX) = -1;
auxMapY.at<float>(y-minY,x-minX) = -1;
continue;
}
auxMapX.at<float>(y-minY,x-minX) = (H[0]*u+H[1]*v+H[2])/w;
auxMapY.at<float>(y-minY,x-minX) = (H[3]*u+H[4]*v+H[5])/w;
}
}
} else {
// 用辅助视图自己的相机做 3D 投影
for (int py = minY; py <= maxY; ++py) {
for (int px = minX; px <= maxX; ++px) {
float u = (float)px / (float)textureSize;
float v_coord = (float)py / (float)textureSize;
float b0, b1, b2;
if (!ComputeBarycentric(u, v_coord, uv[0], uv[1], uv[2], b0, b1, b2)) {
continue;
}
Point3f P = v[0] * b0 + v[1] * b1 + v[2] * b2;
Point2f imgPt = auxCam.ProjectPointP(P);
if (imgPt.x < 0 || imgPt.x >= images[lfv.viewId].image.cols ||
imgPt.y < 0 || imgPt.y >= images[lfv.viewId].image.rows) {
continue;
}
auxMapX.at<float>(py - minY, px - minX) = imgPt.x;
auxMapY.at<float>(py - minY, px - minX) = imgPt.y;
}
}
}
cv::Mat auxPatch;
cv::remap(images[lfv.viewId].image, auxPatch, mapX, mapY,
cv::remap(images[lfv.viewId].image, auxPatch, auxMapX, auxMapY,
cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0,0,0));
cv::Mat auxFloat;
@@ -16649,10 +16701,25 @@ bool MeshTexture::RasterizeVirtualFaces(
// cv::Mat finalPatch = highFreq.clone();
// finalPatch = cv::Mat::zeros(finalPatch.size(), finalPatch.type());
cv::Mat finalPatch = mainFloat; // 只用主视图
// cv::Mat finalPatch = mainFloat; // 只用主视图
// cv::Mat finalPatch = lowFreqPatch * 0.3f + highFreq * 0.7f;
// 低频只做主视图,不做多视图平均(避免发灰)
// cv::Mat finalPatch = mainFloat * 0.7f + highFreq * 0.3f;
// cv::Mat finalPatch = lowFreqPatch;
// 先填空洞:lowFreqPatch 中黑色空洞用 mainFloat 填充
cv::Mat filledLowFreq = lowFreqPatch.clone();
for (int y = 0; y < patchH; ++y) {
for (int x = 0; x < patchW; ++x) {
cv::Vec3f color = filledLowFreq.at<cv::Vec3f>(y, x);
if (color[0] == 0.0f && color[1] == 0.0f && color[2] == 0.0f) {
filledLowFreq.at<cv::Vec3f>(y, x) = mainFloat.at<cv::Vec3f>(y, x);
}
}
}
// 再与 mainFloat 混合(低频占主导,主视图补充细节)
cv::Mat finalPatch = filledLowFreq * 0.7f + mainFloat * 0.3f;
// 钳制到 [0, 1]
cv::Mat clampedPatch;