From 8938f36c65a268ca4ed5be7098e01938c56e17b0 Mon Sep 17 00:00:00 2001 From: hesuicong Date: Mon, 23 Feb 2026 16:22:48 +0800 Subject: [PATCH] Test --- libs/MVS/Scene.h | 2 + libs/MVS/SceneTexture.cpp | 322 ++++++++++++++++++++++++++++---------- 2 files changed, 237 insertions(+), 87 deletions(-) diff --git a/libs/MVS/Scene.h b/libs/MVS/Scene.h index d7ec610..9a9a5f3 100644 --- a/libs/MVS/Scene.h +++ b/libs/MVS/Scene.h @@ -68,6 +68,8 @@ public: std::unordered_set face_visible_relative; std::unordered_set face_test; + std::string base_path; + public: inline Scene(unsigned _nMaxThreads=0) : obb(true), nMaxThreads(Thread::getMaxThreads(_nMaxThreads)) {} diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index bca5a4c..b8df367 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -78,7 +78,7 @@ using namespace MVS; #define TEXOPT_INFERENCE_TRWS 2 #define TEXOPT_INFERENCE TEXOPT_INFERENCE_LBP #define MASK_FACE_OCCLUSION -#define TEST +// #define TEST // #define USE_CUDA @@ -1200,7 +1200,8 @@ static ColorComparisonPixel* g_colorComparisonPixel = nullptr; bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThreshold, int nIgnoreMaskLabel, const IIndexArr& _views, bool bUseVirtualFaces) { #ifdef TEST - std::string outputDir = "/home/algo/Documents/openMVS/data/446442/color_comparison/"; + std::string outputDir = scene.base_path + std::string("/color_comparison/"); + printf("ListCameraFaces outputDir=%s\n", outputDir.c_str()); g_colorComparisonFace = new ColorComparisonFace(outputDir); std::map>> testFacePixelsByView; @@ -1858,47 +1859,67 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr // 添加到批处理器 if (g_colorComparisonFace) { - // 创建可视化图像(转换为RGB用于显示) - cv::Mat visualization = cv::Mat::zeros(height, width, CV_8UC3); + // 设置不同的放大因子 + int triangleScaleFactor = 30; + int visualizationScaleFactor = 40; + + int triangleWidth = width * triangleScaleFactor; + int triangleHeight = height * triangleScaleFactor; + int enlargedWidth = width * visualizationScaleFactor; + int enlargedHeight = height * visualizationScaleFactor; + + // 创建放大20倍的可视化图像(灰色背景) + cv::Mat visualization = cv::Mat::zeros(enlargedHeight, enlargedWidth, CV_8UC3); + visualization.setTo(cv::Scalar(200, 200, 200)); // 浅灰色背景 // 创建RGB版本的图像区域用于显示 cv::Mat imageRegionRGB; cv::cvtColor(imageRegion, imageRegionRGB, cv::COLOR_BGR2RGB); - bool b = false; - if (filename=="106_8") - b = true; + // 计算三角形在20倍图像中的居中位置 + int offsetX = (enlargedWidth - triangleWidth) / 2; + int offsetY = (enlargedHeight - triangleHeight) / 2; - // 将三角形区域绘制到可视化图像上 + // 将三角形区域绘制到放大后的可视化图像上(居中放置) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uchar maskVal = exactMask.at(y, x); if (maskVal > 0) { - // 在三角形区域内:使用RGB颜色 cv::Vec3b pixel = imageRegionRGB.at(y, x); - visualization.at(y, x) = pixel; - } else { - // 在三角形区域外:使用浅灰色背景 - visualization.at(y, x) = cv::Vec3b(200, 200, 200); + + // 将像素放大4倍,并放置在20倍图像的中央 + for (int sy = 0; sy < triangleScaleFactor; sy++) { + for (int sx = 0; sx < triangleScaleFactor; sx++) { + int enlargedX = offsetX + x * triangleScaleFactor + sx; + int enlargedY = offsetY + y * triangleScaleFactor + sy; + if (enlargedX < enlargedWidth && enlargedY < enlargedHeight) { + visualization.at(enlargedY, enlargedX) = pixel; + } + } + } } } } { - // 立即保存visualization用于调试 - std::string debugDir = "debug_visualization/"; + // 立即保存放大后的visualization用于调试 + std::string debugDir = scene.base_path + std::string("/debug_visualization/"); std::filesystem::create_directories(debugDir); std::string debugPath = debugDir + "face_" + std::to_string(idxFace) + - "_view" + std::to_string(idxView) + "_" + filename + "_raw_visualization.png"; + "_view" + std::to_string(idxView) + "_" + filename + + "_triangle_x" + std::to_string(triangleScaleFactor) + + "_canvas_x" + std::to_string(visualizationScaleFactor) + ".png"; cv::imwrite(debugPath, visualization); - printf(" ✅ 保存原始visualization: %s\n", debugPath.c_str()); + printf(" ✅ 保存可视化图像: 三角形放大%d倍, 画布放大%d倍: %s\n", + triangleScaleFactor, visualizationScaleFactor, debugPath.c_str()); // 同时保存掩码和原始图像用于对比 cv::imwrite(debugDir + "face_" + std::to_string(idxFace) + "_mask.png", exactMask); cv::imwrite(debugDir + "face_" + std::to_string(idxFace) + "_original.png", imageRegion); } - // 增强三角形轮廓可见性 + /* + // 增强三角形轮廓可见性(在放大图像上) cv::Mat visualizationWithContour = visualization.clone(); // 创建三角形轮廓 @@ -1907,38 +1928,45 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr // 计算凸包以获得三角形轮廓 std::vector allPoints = trianglePixels; - // 调整坐标到ROI + // 调整坐标到ROI并应用三角形放大因子,然后加上偏移量 for (auto& pt : allPoints) { - pt.x -= minX; - pt.y -= minY; + pt.x = offsetX + (pt.x - minX) * triangleScaleFactor; + pt.y = offsetY + (pt.y - minY) * triangleScaleFactor; } // 计算凸包 std::vector hull; cv::convexHull(allPoints, hull); - // 绘制三角形轮廓 - 增强版本 + // 绘制三角形轮廓 - 增强版本(在放大图像上) if (!hull.empty()) { // 首先绘制一个粗的蓝色轮廓 std::vector> contours = {hull}; - cv::drawContours(visualizationWithContour, contours, 0, cv::Scalar(255, 0, 0), 3); + // cv::drawContours(visualizationWithContour, contours, 0, + // cv::Scalar(255, 0, 0), 3); // 再绘制一个细的白色轮廓,增强对比 - cv::drawContours(visualizationWithContour, contours, 0, cv::Scalar(255, 255, 255), 1); + cv::drawContours(visualizationWithContour, contours, 0, + cv::Scalar(255, 255, 255), 1); // 标记顶点 for (size_t i = 0; i < hull.size(); i++) { // 绘制大圆点 - cv::circle(visualizationWithContour, hull[i], 6, cv::Scalar(0, 255, 0), -1); + int circleRadius = 2; + cv::circle(visualizationWithContour, hull[i], circleRadius, + cv::Scalar(0, 255, 0), -1); - // 添加顶点编号 - cv::putText(visualizationWithContour, std::to_string(i), - cv::Point(hull[i].x + 8, hull[i].y - 8), - cv::FONT_HERSHEY_SIMPLEX, 0.7, - cv::Scalar(0, 0, 0), 2); + // // 添加顶点编号 + // double fontScale = 0.8; + // int thickness = 2; + // cv::putText(visualizationWithContour, std::to_string(i), + // cv::Point(hull[i].x + 10, hull[i].y - 10), + // cv::FONT_HERSHEY_SIMPLEX, fontScale, + // cv::Scalar(0, 0, 0), thickness); - // 在顶点周围添加白色边框 - cv::circle(visualizationWithContour, hull[i], 6, cv::Scalar(255, 255, 255), 1); + // // 在顶点周围添加白色边框 + // cv::circle(visualizationWithContour, hull[i], circleRadius, + // cv::Scalar(255, 255, 255), 1); } // 计算三角形中心点 @@ -1950,28 +1978,179 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr center.x /= hull.size(); center.y /= hull.size(); - // 在中心添加面编号 - std::string faceLabel = "Face:" + std::to_string(idxFace); - cv::putText(visualizationWithContour, faceLabel, - cv::Point(center.x - 30, center.y), - cv::FONT_HERSHEY_SIMPLEX, 0.5, - cv::Scalar(0, 0, 0), 2); + // // 在中心添加面编号 + // std::string faceLabel = "Face:" + std::to_string(idxFace); + // double fontScale = 0.7; + // int thickness = 2; + // cv::putText(visualizationWithContour, faceLabel, + // cv::Point(center.x - 40, center.y), + // cv::FONT_HERSHEY_SIMPLEX, fontScale, + // cv::Scalar(0, 0, 0), thickness); + + // // 在三角形周围添加边框 + // cv::Rect boundingRect = cv::boundingRect(hull); + // cv::rectangle(visualizationWithContour, boundingRect, + // cv::Scalar(0, 0, 255), 2); - // 在三角形周围添加边框 - cv::Rect boundingRect = cv::boundingRect(hull); - cv::rectangle(visualizationWithContour, boundingRect, cv::Scalar(0, 0, 255), 2); + // // 添加比例信息文本 + // std::string scaleInfo = "Triangle:x" + std::to_string(triangleScaleFactor) + + // " Canvas:x" + std::to_string(visualizationScaleFactor); + // cv::putText(visualizationWithContour, scaleInfo, + // cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 0.6, + // cv::Scalar(0, 0, 255), 2); } } + */ +// 增强三角形轮廓可见性(在放大图像上) +cv::Mat visualizationWithContour = visualization.clone(); + +if (!trianglePixels.empty()) { + // 创建三角形轮廓 + std::vector hullPoints; + + // 计算凸包以获得多边形轮廓 + std::vector allPoints = trianglePixels; + + // 调整坐标到ROI并应用三角形放大因子,然后加上偏移量 + for (auto& pt : allPoints) { + pt.x = offsetX + (pt.x - minX) * triangleScaleFactor; + pt.y = offsetY + (pt.y - minY) * triangleScaleFactor; + } + + // 计算凸包 + std::vector hull; + cv::convexHull(allPoints, hull); + + // 绘制三角形轮廓 - 增强版本(在放大图像上) + if (!hull.empty()) { + // 计算凸包的中心点 + cv::Point hullCenter(0, 0); + for (const auto& p : hull) { + hullCenter.x += p.x; + hullCenter.y += p.y; + } + hullCenter.x /= hull.size(); + hullCenter.y /= hull.size(); + + // 创建调整后的凸包点(移动到像素角点) + std::vector adjustedHull; + + for (size_t i = 0; i < hull.size(); i++) { + // 获取原始凸包点 + cv::Point originalPoint = hull[i]; + + // 计算这个点对应的原始像素索引 + int pixelGridX = (originalPoint.x - offsetX) / triangleScaleFactor; + int pixelGridY = (originalPoint.y - offsetY) / triangleScaleFactor; + + // 计算像素的四个角点坐标 + int pixelLeft = offsetX + pixelGridX * triangleScaleFactor; + int pixelRight = pixelLeft + triangleScaleFactor; + int pixelTop = offsetY + pixelGridY * triangleScaleFactor; + int pixelBottom = pixelTop + triangleScaleFactor; + + // 计算像素的四个角点 + cv::Point topLeft(pixelLeft, pixelTop); + cv::Point topRight(pixelRight, pixelTop); + cv::Point bottomLeft(pixelLeft, pixelBottom); + cv::Point bottomRight(pixelRight, pixelBottom); + + // 根据凸包点相对于中心的位置,选择角点 + cv::Point adjustedPoint = originalPoint; // 默认使用原始点 + + // 判断点在中心点的哪一侧 + bool isRightSide = originalPoint.x > hullCenter.x; + bool isBottomSide = originalPoint.y > hullCenter.y; + + if (isRightSide && !isBottomSide) { + // 右侧上方的点 → 使用右上角 + adjustedPoint = topRight; + } else if (isRightSide && isBottomSide) { + // 右侧下方的点 → 使用右下角 + adjustedPoint = bottomRight; + } else if (!isRightSide && isBottomSide) { + // 左侧下方的点 → 使用左下角 + adjustedPoint = bottomLeft; + } else if (!isRightSide && !isBottomSide) { + // 左侧上方的点 → 使用左上角 + adjustedPoint = topLeft; + } + + adjustedHull.push_back(adjustedPoint); + } + + // 确保adjustedHull是闭合的(首尾相连) + if (!adjustedHull.empty() && adjustedHull[0] != adjustedHull.back()) { + adjustedHull.push_back(adjustedHull[0]); + } + + // 使用调整后的点绘制多边形轮廓 + if (adjustedHull.size() >= 2) { + // 绘制白色轮廓线 + for (size_t i = 0; i < adjustedHull.size() - 1; i++) { + cv::line(visualizationWithContour, + adjustedHull[i], + adjustedHull[i + 1], + cv::Scalar(255, 255, 255), // 白色 + 1); // 线宽 + } + + // 标记顶点 + for (size_t i = 0; i < adjustedHull.size() - 1; i++) { + int circleRadius = 3; + cv::circle(visualizationWithContour, + adjustedHull[i], + circleRadius, + cv::Scalar(0, 255, 0), // 绿色 + -1); // 实心圆 + } + } else { + // 如果调整后的点集有问题,回退到原始凸包 + std::vector> contours = {hull}; + cv::drawContours(visualizationWithContour, contours, 0, + cv::Scalar(255, 255, 255), 1); + + // 标记顶点 + for (size_t i = 0; i < hull.size(); i++) { + int circleRadius = 2; + cv::circle(visualizationWithContour, hull[i], circleRadius, + cv::Scalar(0, 255, 0), -1); + } + } + } +} + - // 创建增强版本的带透明通道的图像,包含轮廓 - cv::Mat exactTriangleRegionWithContour = exactTriangleRegionWithAlpha.clone(); + // 创建放大后的带透明通道的图像(三角形放大4倍,画布放大20倍) + cv::Mat exactTriangleRegionWithContour = cv::Mat::zeros(enlargedHeight, enlargedWidth, CV_8UC4); + + // 将原始透明图像放大,三角形区域放大4倍并居中 + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + cv::Vec4b pixel = exactTriangleRegionWithAlpha.at(y, x); + + // 只复制三角形区域(非透明部分) + if (pixel[3] > 0) { + // 将像素放大4倍,并放置在20倍图像的中央 + for (int sy = 0; sy < triangleScaleFactor; sy++) { + for (int sx = 0; sx < triangleScaleFactor; sx++) { + int enlargedX = offsetX + x * triangleScaleFactor + sx; + int enlargedY = offsetY + y * triangleScaleFactor + sy; + if (enlargedX < enlargedWidth && enlargedY < enlargedHeight) { + exactTriangleRegionWithContour.at(enlargedY, enlargedX) = pixel; + } + } + } + } + } + } - // 在透明图像上也绘制轮廓 + // 在放大的透明图像上也绘制轮廓 if (trianglePixels.size() >= 3) { std::vector allPoints = trianglePixels; for (auto& pt : allPoints) { - pt.x -= minX; - pt.y -= minY; + pt.x = offsetX + (pt.x - minX) * triangleScaleFactor; + pt.y = offsetY + (pt.y - minY) * triangleScaleFactor; } std::vector hull; @@ -1982,53 +2161,20 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr // 在BGRA图像上绘制轮廓 cv::drawContours(exactTriangleRegionWithContour, contours, 0, - cv::Scalar(255, 0, 0, 255), 3); // 蓝色轮廓,不透明 + cv::Scalar(255, 0, 0, 255), 3); // 蓝色轮廓,不透明 } } - // 修复3:传递带透明通道的三角形区域 + // 传递放大后的带透明通道的三角形区域 g_colorComparisonFace->addExactTriangleInfo(idxFace, gaussianMeshColor, originalColor, - exactTriangleRegionWithContour, // 传递带轮廓的透明通道图像 - visualization, // 传递带轮廓的可视化图像 + exactTriangleRegionWithContour, // 传递放大后的带轮廓透明通道图像 + visualizationWithContour, // 传递带轮廓的可视化图像 colorDistance, threshold, filename); - printf(" ✅ 面 %d 已添加到批处理器(增强轮廓可见性)\n", idxFace); - - // 调试:保存带透明通道的图像 - #ifdef DEBUG_SAVE_TRIANGLES - static int saveCount = 0; - std::string saveDir = "debug_triangles/"; - std::filesystem::create_directories(saveDir); - - std::string trianglePath = saveDir + "face_" + std::to_string(idxFace) + - "_view" + std::to_string(idxView) + "_" + filename + ".png"; - std::string maskPath = saveDir + "face_" + std::to_string(idxFace) + - "_view" + std::to_string(idxView) + "_" + filename + "_mask.png"; - std::string visPath = saveDir + "face_" + std::to_string(idxFace) + - "_view" + std::to_string(idxView) + "_" + filename + "_vis.png"; - std::string rgbPath = saveDir + "face_" + std::to_string(idxFace) + - "_view" + std::to_string(idxView) + "_" + filename + "_rgb.png"; - std::string contourPath = saveDir + "face_" + std::to_string(idxFace) + - "_view" + std::to_string(idxView) + "_" + filename + "_contour.png"; - - // 保存带透明通道的三角形区域 - cv::imwrite(trianglePath, exactTriangleRegionWithContour); - - // 保存掩码 - cv::imwrite(maskPath, exactMask); - - // 保存可视化图像 - cv::imwrite(visPath, visualizationWithContour); - - // 保存RGB版本的图像区域 - cv::imwrite(rgbPath, imageRegionRGB); - - printf(" 已保存三角形图像到: %s\n", trianglePath.c_str()); - printf(" 已保存掩码到: %s\n", maskPath.c_str()); - printf(" 已保存可视化到: %s\n", visPath.c_str()); - #endif + printf(" ✅ 面 %d 已添加到批处理器(三角形放大%d倍,画布放大%d倍)\n", + idxFace, triangleScaleFactor, visualizationScaleFactor); } } } @@ -11419,10 +11565,12 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi MeshTexture texture(*this, nResolutionLevel, nMinResolution); - // printf("baseFileName=%s\n", baseFileName.c_str()); + std::filesystem::path path(baseFileName.c_str()); + base_path = path.parent_path().parent_path().string(); // 获取父目录 + + printf("base_path=%s\n", base_path.c_str()); /* - std::filesystem::path path(baseFileName.c_str()); std::string parentPath = path.parent_path().string(); // 获取父目录 String altTexPath = String(parentPath) + "/mesh_material_0_map_Kd2.png";