解决矩形杂色和色差问题
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;
|
||||
}
|
||||
|
||||
// ========== 用重心坐标 + 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;
|
||||
|
||||
Reference in new issue
Block a user