解决矩形杂色和色差问题
This commit is contained in:
1 parent
b106a7976e
commit
351a0a274f
1 file changed
+80
-13
+80
-13
@@ -16503,7 +16503,7 @@ bool MeshTexture::RasterizeVirtualFaces(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 用重心坐标 + 3D 投影替代 homography ==========
|
// ========== 用重心坐标 + 3D 投影替代 homography ==========
|
||||||
cv::Mat mapX(patchH, patchW, CV_32FC1), mapY(patchH, patchW, CV_32FC1);
|
cv::Mat mapX(patchH, patchW, CV_32FC1), mapY(patchH, patchW, CV_32FC1);
|
||||||
mapX.setTo(-1);
|
mapX.setTo(-1);
|
||||||
mapY.setTo(-1);
|
mapY.setTo(-1);
|
||||||
@@ -16513,6 +16513,14 @@ bool MeshTexture::RasterizeVirtualFaces(
|
|||||||
FIndex faceIdx = vf.faces[0];
|
FIndex faceIdx = vf.faces[0];
|
||||||
const Face& face = scene.mesh.faces[faceIdx];
|
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;
|
const Camera& cam = images[mainView].camera;
|
||||||
bool camValid = (cam.K(0,0) > 0 && cam.K(1,1) > 0);
|
bool camValid = (cam.K(0,0) > 0 && cam.K(1,1) > 0);
|
||||||
@@ -16529,14 +16537,6 @@ bool MeshTexture::RasterizeVirtualFaces(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 内每个像素做重心坐标投影
|
// 对 patch 内每个像素做重心坐标投影
|
||||||
for (int py = minY; py <= maxY; ++py) {
|
for (int py = minY; py <= maxY; ++py) {
|
||||||
for (int px = minX; px <= maxX; ++px) {
|
for (int px = minX; px <= maxX; ++px) {
|
||||||
@@ -16570,16 +16570,68 @@ bool MeshTexture::RasterizeVirtualFaces(
|
|||||||
cv::Mat mainPatch;
|
cv::Mat mainPatch;
|
||||||
cv::remap(images[mainView].image, mainPatch, mapX, mapY, cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0,0,0));
|
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));
|
cv::Mat lowFreqPatch(patchH, patchW, CV_32FC3, cv::Scalar(0,0,0));
|
||||||
if (hasLowFreqViews) {
|
if (hasLowFreqViews) {
|
||||||
float totalWeight = 0;
|
float totalWeight = 0;
|
||||||
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;
|
||||||
|
|
||||||
// ★★★ 所有视图都用主视图的 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::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::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0,0,0));
|
||||||
|
|
||||||
cv::Mat auxFloat;
|
cv::Mat auxFloat;
|
||||||
@@ -16649,10 +16701,25 @@ bool MeshTexture::RasterizeVirtualFaces(
|
|||||||
// cv::Mat finalPatch = highFreq.clone();
|
// cv::Mat finalPatch = highFreq.clone();
|
||||||
// finalPatch = cv::Mat::zeros(finalPatch.size(), finalPatch.type());
|
// 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 = lowFreqPatch * 0.3f + highFreq * 0.7f;
|
||||||
// 低频只做主视图,不做多视图平均(避免发灰)
|
// 低频只做主视图,不做多视图平均(避免发灰)
|
||||||
// cv::Mat finalPatch = mainFloat * 0.7f + highFreq * 0.3f;
|
// 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]
|
// 钳制到 [0, 1]
|
||||||
cv::Mat clampedPatch;
|
cv::Mat clampedPatch;
|
||||||
|
|||||||
Reference in new issue
Block a user