diff --git a/libs/MVS/SceneTexture.cpp b/libs/MVS/SceneTexture.cpp index e120d10..7b93b1e 100644 --- a/libs/MVS/SceneTexture.cpp +++ b/libs/MVS/SceneTexture.cpp @@ -1002,59 +1002,30 @@ public: return sharedVertices == 2; } - // 修改 mergeContinuousFaces 函数的类型 - static std::map> mergeContinuousFaces( // 返回类型改为 unsigned int - const std::set& testFaces, // 参数类型改为 unsigned int - const Mesh& mesh) { - - std::map> regions; // 返回类型改为 unsigned int - std::set processed; // 类型改为 unsigned int - int regionId = 0; - - // 遍历所有测试面 - for (unsigned int face : testFaces) { // 类型改为 unsigned int - if (processed.find(face) != processed.end()) { - continue; - } - - // 开始新区域 - std::set currentRegion; // 类型改为 unsigned int - std::queue faceQueue; // 类型改为 unsigned int - faceQueue.push(face); - - while (!faceQueue.empty()) { - unsigned int currentFace = faceQueue.front(); // 类型改为 unsigned int - faceQueue.pop(); - - if (processed.find(currentFace) != processed.end()) { - continue; - } - - // 添加到当前区域 - currentRegion.insert(currentFace); - processed.insert(currentFace); - - // 查找相邻的测试面 - for (unsigned int otherFace : testFaces) { // 类型改为 unsigned int - if (processed.find(otherFace) != processed.end()) { - continue; - } - - // 检查是否相邻 - if (areFacesAdjacent(mesh.faces[currentFace], mesh.faces[otherFace])) { - faceQueue.push(otherFace); - } - } - } - - if (!currentRegion.empty()) { - regions[regionId] = currentRegion; - regionId++; - } - } - - return regions; - } +static std::map> mergeContinuousFaces( + const std::set& testFaces, + const Mesh& mesh) { + + std::map> regions; + + // 将所有测试面合并为一个区域(区域ID为0) + regions[0] = testFaces; // 直接将所有面放入区域0 + + printf("将所有测试面合并为一个区域\n"); + printf("区域 0: 包含 %zu 个面\n", testFaces.size()); + + // 输出区域包含的面 + printf("包含的面: {"); + for (auto it = testFaces.begin(); it != testFaces.end(); ++it) { + printf("%u", *it); + if (std::next(it) != testFaces.end()) { + printf(", "); + } + } + printf("}\n"); + + return regions; +} //*/ /* @@ -1328,6 +1299,9 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr g_colorComparisonFace->addContinuousRegionInfo(regionId, regionFaces, avgColor); } } + + // 4. 用于存储每个区域在每个视图中的像素 + std::map>> regionPixelsByView; #endif // create faces octree @@ -1697,7 +1671,7 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr Color imageColor = Color(imageData.image(j,i)); // printf("idxFace(%d) imageColor:%f, %f, %f\n", idxFace, imageColor[0], imageColor[1], imageColor[2]); - Mesh::Color originalColor= Mesh::Color(imageColor[0],imageColor[1],imageColor[2]); + Mesh::Color originalColor= Mesh::Color(imageColor[2],imageColor[1],imageColor[0]); MeshColor gaussianMeshColor(gaussianColor.r, gaussianColor.g, gaussianColor.b); MeshColor originalMeshColor(originalColor.r, originalColor.g, originalColor.b); @@ -1850,460 +1824,174 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr } #ifdef TEST - auto itView = testFacePixelsByView.find(idxView); - if (itView != testFacePixelsByView.end()) { - const auto& facePixelsMap = itView->second; - - printf("=== 处理视图 %d: %s ===\n", idxView, strName.c_str()); - printf("这个视图有 %zu 个测试面\n", facePixelsMap.size()); - - // 遍历这个视图中的所有测试面 - for (const auto& faceEntry : facePixelsMap) { - FIndex idxFace = faceEntry.first; - const std::vector& trianglePixels = faceEntry.second; - - printf(" 处理面 %d: 有 %zu 个像素(三角形精确区域)\n", idxFace, trianglePixels.size()); - - if (trianglePixels.empty()) { - printf(" ⚠️ 面 %d 没有像素,跳过\n", idxFace); - continue; - } - - // 方法2:从faceMap中获取三角形的精确像素 - // 这些像素已经是三角形在图像上的准确投影 - - // 计算三角形区域的边界 - int minX = INT_MAX, minY = INT_MAX; - int maxX = 0, maxY = 0; - - // 计算三角形区域的边界 - for (const auto& pt : trianglePixels) { - if (pt.x < minX) minX = pt.x; - if (pt.x > maxX) maxX = pt.x; - if (pt.y < minY) minY = pt.y; - if (pt.y > maxY) maxY = pt.y; - } - - printf(" 三角形区域边界: (%d,%d) 到 (%d,%d)\n", minX, minY, maxX, maxY); - - // 创建精确的三角形掩码 - int width = maxX - minX + 1; - int height = maxY - minY + 1; - - if (width <= 0 || height <= 0) { - printf(" ⚠️ 面 %d 无效尺寸,跳过\n", idxFace); - continue; - } - - // 创建掩码 - cv::Mat exactMask = cv::Mat::zeros(height, width, CV_8UC1); - - // 填充三角形像素 - for (const auto& pt : trianglePixels) { - int x = pt.x - minX; - int y = pt.y - minY; - if (x >= 0 && x < width && y >= 0 && y < height) { - exactMask.at(y, x) = 255; - } - } - - // 提取图像区域 - cv::Rect roi(minX, minY, width, height); - cv::Mat imageRegion = imageData.image(roi).clone(); - - // 创建带透明通道的图像 - cv::Mat exactTriangleRegionWithAlpha = cv::Mat::zeros(height, width, CV_8UC4); - - // 计算三角形区域的平均颜色 - cv::Scalar meanColor(0, 0, 0); - int pixelCount = 0; - - // 先计算平均颜色 - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - uchar maskVal = exactMask.at(y, x); - if (maskVal > 0) { - cv::Vec3b pixel = imageRegion.at(y, x); - // 注意:OpenCV是BGR顺序 - meanColor[0] += pixel[0]; // B - meanColor[1] += pixel[1]; // G - meanColor[2] += pixel[2]; // R - pixelCount++; - - // 填充带透明通道的图像 - exactTriangleRegionWithAlpha.at(y, x) = - cv::Vec4b(pixel[0], pixel[1], pixel[2], 255); - } else { - // 在三角形区域外:完全透明 - exactTriangleRegionWithAlpha.at(y, x) = - cv::Vec4b(0, 0, 0, 0); - } - } - } - - if (pixelCount > 0) { - meanColor[0] /= pixelCount; // B - meanColor[1] /= pixelCount; // G - meanColor[2] /= pixelCount; // R - } - - // 获取高斯颜色 - if (idxFace < faceColorsGaussian.size()) { - Mesh::Color gaussianColor = faceColorsGaussian[idxFace]; - MeshColor gaussianMeshColor(gaussianColor.r, gaussianColor.g, gaussianColor.b); - - // 注意:meanColor是BGR顺序,需要转换为RGB - MeshColor originalColor(meanColor[2], meanColor[1], meanColor[0]); - - // 计算颜色距离 - float colorDistance = computeColorDifferenceHSV(gaussianMeshColor, originalColor); - float threshold = 0.31f; - bool bFilter = (colorDistance > threshold); - - std::string full_path = imageData.name; - size_t slash_pos = full_path.find_last_of("/\\"); - std::string filename = (slash_pos != std::string::npos) - ? full_path.substr(slash_pos + 1) - : full_path; - size_t dot_pos = filename.find_last_of("."); - if (dot_pos != std::string::npos) { - filename = filename.substr(0, dot_pos); - } - - printf("三角形颜色信息 - Face %d:\n", idxFace); - printf(" 高斯颜色: R=%d, G=%d, B=%d\n", gaussianColor.r, gaussianColor.g, gaussianColor.b); - printf(" 原始颜色: B=%.0f, G=%.0f, R=%.0f\n", meanColor[0], meanColor[1], meanColor[2]); - printf(" 原始颜色(RGB): R=%.0f, G=%.0f, B=%.0f\n", meanColor[2], meanColor[1], meanColor[0]); - printf(" 像素数量: %d\n", pixelCount); - printf(" 颜色距离: %.4f, 阈值: %.4f, 过滤: %s\n", - colorDistance, threshold, bFilter ? "是" : "否"); - - // 添加到批处理器 - if (g_colorComparisonFace) { - // 设置不同的放大因子 - 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); - - // 计算三角形在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) { - cv::Vec3b pixel = imageRegionRGB.at(y, x); - - // 将像素放大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 = 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 + - "_triangle_x" + std::to_string(triangleScaleFactor) + - "_canvas_x" + std::to_string(visualizationScaleFactor) + ".png"; - cv::imwrite(debugPath, visualization); - 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(); - - // 创建三角形轮廓 - std::vector hullPoints; - if (trianglePixels.size() >= 3) { - // 计算凸包以获得三角形轮廓 - 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()) { - // 首先绘制一个粗的蓝色轮廓 - std::vector> contours = {hull}; - // cv::drawContours(visualizationWithContour, contours, 0, - // cv::Scalar(255, 0, 0), 3); - - // 再绘制一个细的白色轮廓,增强对比 - 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); - - // // 添加顶点编号 - // 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], circleRadius, - // cv::Scalar(255, 255, 255), 1); - } - - // 计算三角形中心点 - cv::Point center(0, 0); - for (const auto& p : hull) { - center.x += p.x; - center.y += p.y; - } - center.x /= hull.size(); - center.y /= hull.size(); - - // // 在中心添加面编号 - // 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); - - // // 添加比例信息文本 - // 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; + // 处理这个视图的测试面 + auto itView = testFacePixelsByView.find(idxView); + if (itView != testFacePixelsByView.end()) { + const auto& facePixelsMap = itView->second; + + printf("=== 处理视图 %d: %s ===\n", idxView, strName.c_str()); + printf("这个视图有 %zu 个测试面\n", facePixelsMap.size()); + + // 遍历这个视图中的所有测试面 + for (const auto& faceEntry : facePixelsMap) { + FIndex idxFace = faceEntry.first; + const std::vector& trianglePixels = faceEntry.second; + + if (trianglePixels.empty()) continue; + + // 1. 找到这个面属于哪个区域 + int faceRegionId = -1; + for (const auto& regionEntry : continuousRegions) { + int regionId = regionEntry.first; + const std::set& regionFaces = regionEntry.second; + if (regionFaces.find(idxFace) != regionFaces.end()) { + faceRegionId = regionId; + break; + } + } + + if (faceRegionId == -1) continue; // 不属于任何区域 + + // 2. 将这个面的像素添加到区域 + std::vector& regionPixels = regionPixelsByView[faceRegionId][idxView]; + regionPixels.insert(regionPixels.end(), trianglePixels.begin(), trianglePixels.end()); + } } - 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]; + // 处理每个区域在这个视图中的像素 + for (auto& regionEntry : regionPixelsByView) { + int regionId = regionEntry.first; + auto& viewMap = regionEntry.second; - // 计算这个点对应的原始像素索引 - int pixelGridX = (originalPoint.x - offsetX) / triangleScaleFactor; - int pixelGridY = (originalPoint.y - offsetY) / triangleScaleFactor; + if (viewMap.find(idxView) == viewMap.end()) { + continue; // 这个区域在这个视图中不可见 + } + + std::vector& regionPixels = viewMap[idxView]; + if (regionPixels.empty()) continue; - // 计算像素的四个角点坐标 - int pixelLeft = offsetX + pixelGridX * triangleScaleFactor; - int pixelRight = pixelLeft + triangleScaleFactor; - int pixelTop = offsetY + pixelGridY * triangleScaleFactor; - int pixelBottom = pixelTop + triangleScaleFactor; + // 计算区域的边界 + int minX = INT_MAX, minY = INT_MAX; + int maxX = 0, maxY = 0; - // 计算像素的四个角点 - cv::Point topLeft(pixelLeft, pixelTop); - cv::Point topRight(pixelRight, pixelTop); - cv::Point bottomLeft(pixelLeft, pixelBottom); - cv::Point bottomRight(pixelRight, pixelBottom); + for (const auto& pt : regionPixels) { + if (pt.x < minX) minX = pt.x; + if (pt.x > maxX) maxX = pt.x; + if (pt.y < minY) minY = pt.y; + if (pt.y > maxY) maxY = pt.y; + } - // 根据凸包点相对于中心的位置,选择角点 - cv::Point adjustedPoint = originalPoint; // 默认使用原始点 + int width = maxX - minX + 1; + int height = maxY - minY + 1; - // 判断点在中心点的哪一侧 - bool isRightSide = originalPoint.x > hullCenter.x; - bool isBottomSide = originalPoint.y > hullCenter.y; + if (width <= 0 || height <= 0) continue; - if (isRightSide && !isBottomSide) { - // 右侧上方的点 → 使用右上角 - adjustedPoint = topRight; - } else if (isRightSide && isBottomSide) { - // 右侧下方的点 → 使用右下角 - adjustedPoint = bottomRight; - } else if (!isRightSide && isBottomSide) { - // 左侧下方的点 → 使用左下角 - adjustedPoint = bottomLeft; - } else if (!isRightSide && !isBottomSide) { - // 左侧上方的点 → 使用左上角 - adjustedPoint = topLeft; + // 创建区域掩码 + cv::Mat regionMask = cv::Mat::zeros(height, width, CV_8UC1); + + for (const auto& pt : regionPixels) { + int x = pt.x - minX; + int y = pt.y - minY; + if (x >= 0 && x < width && y >= 0 && y < height) { + regionMask.at(y, x) = 255; + } } - 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); // 线宽 + // 提取图像区域 + cv::Rect roi(minX, minY, width, height); + cv::Mat imageRegion = imageData.image(roi).clone(); + + // 计算区域平均颜色 + cv::Scalar meanColor(0, 0, 0); + int pixelCount = 0; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + uchar maskVal = regionMask.at(y, x); + if (maskVal > 0) { + cv::Vec3b pixel = imageRegion.at(y, x); + meanColor[0] += pixel[0]; // B + meanColor[1] += pixel[1]; // G + meanColor[2] += pixel[2]; // R + pixelCount++; + } + } } - // 标记顶点 - 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); // 实心圆 + if (pixelCount > 0) { + meanColor[0] /= pixelCount; + meanColor[1] /= pixelCount; + meanColor[2] /= pixelCount; } - } 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); + // 创建区域可视化 + int scaleFactor = 20; + int enlargedWidth = width * scaleFactor; + int enlargedHeight = height * scaleFactor; + + cv::Mat visualization = cv::Mat::zeros(enlargedHeight, enlargedWidth, CV_8UC3); + visualization.setTo(cv::Scalar(200, 200, 200)); + + cv::Mat imageRegionRGB; + cv::cvtColor(imageRegion, imageRegionRGB, cv::COLOR_BGR2RGB); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + uchar maskVal = regionMask.at(y, x); + if (maskVal > 0) { + cv::Vec3b pixel = imageRegionRGB.at(y, x); + + for (int sy = 0; sy < scaleFactor; sy++) { + for (int sx = 0; sx < scaleFactor; sx++) { + int enlargedX = x * scaleFactor + sx; + int enlargedY = y * scaleFactor + sy; + if (enlargedX < enlargedWidth && enlargedY < enlargedHeight) { + visualization.at(enlargedY, enlargedX) = pixel; + } + } + } + } + } + } + + // 在可视化图像上添加区域信息 + // std::string regionInfo = cv::format("Region %d: %d faces, %d pixels", + // regionId, continuousRegions[regionId].size(), pixelCount); + // cv::putText(visualization, regionInfo, + // cv::Point(20, 30), + // cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 0), 2); + + // 创建带透明通道的区域图像 + cv::Mat regionWithAlpha = cv::Mat::zeros(height, width, CV_8UC4); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + uchar maskVal = regionMask.at(y, x); + if (maskVal > 0) { + cv::Vec3b pixel = imageRegion.at(y, x); + regionWithAlpha.at(y, x) = + cv::Vec4b(pixel[0], pixel[1], pixel[2], 255); + } + } } + + // 计算颜色距离 + MeshColor regionGaussianColor = regionGaussianColors[regionId]; + MeshColor viewColor(meanColor[2], meanColor[1], meanColor[0]); + float colorDistance = computeColorDifferenceHSV(regionGaussianColor, viewColor); + + // 添加到批处理器 + g_colorComparisonFace->addRegionViewInfo( + regionId, + strName, // 视图文件名 + viewColor, + regionWithAlpha, + visualization, + colorDistance + ); + + printf(" 区域 %d 在视图 %s: %d 像素, 颜色距离=%.4f\n", + regionId, strName.c_str(), pixelCount, colorDistance); } - } -} - - - // 创建放大后的带透明通道的图像(三角形放大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 = 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}; - - // 在BGRA图像上绘制轮廓 - cv::drawContours(exactTriangleRegionWithContour, contours, 0, - cv::Scalar(255, 0, 0, 255), 3); // 蓝色轮廓,不透明 - } - } - - // 传递放大后的带透明通道的三角形区域 - g_colorComparisonFace->addExactTriangleInfo(idxFace, - gaussianMeshColor, - originalColor, - exactTriangleRegionWithContour, // 传递放大后的带轮廓透明通道图像 - visualizationWithContour, // 传递带轮廓的可视化图像 - colorDistance, threshold, filename); - - printf(" ✅ 面 %d 已添加到批处理器(三角形放大%d倍,画布放大%d倍)\n", - idxFace, triangleScaleFactor, visualizationScaleFactor); - } - } - } - - printf("=== 视图 %d 处理完成 ===\n\n", idxView); - } else { - printf("视图 %d: 没有测试面\n", idxView); - } #endif // adjust face quality with camera angle relative to face normal @@ -2346,19 +2034,24 @@ if (!trianglePixels.empty()) { } #endif -#ifdef TEST +#ifdef TEST if (g_colorComparisonFace) { - // 创建实际图像区域对比图 - printf("创建实际图像区域对比图,包含 %d 个face,%d 条记录\n", + printf("创建连续区域跨视图比较图,包含 %d 个区域\n", + g_colorComparisonFace->getTotalRegions()); + + g_colorComparisonFace->createContinuousRegionComparison(6, 20); + + // 原有的单面比较 + printf("创建单面对比图,包含 %d 个face,%d 条记录\n", g_colorComparisonFace->getTotalFaces(), g_colorComparisonFace->getTotalRecords()); - + g_colorComparisonFace->createBatchComparison(10, 500); delete g_colorComparisonFace; g_colorComparisonFace = nullptr; } - - if (g_colorComparisonPixel) { - g_colorComparisonPixel->createBatchComparison(10, 500); // 每行4个,最多20个 + + if (g_colorComparisonPixel) { + g_colorComparisonPixel->createBatchComparison(10, 500); delete g_colorComparisonPixel; g_colorComparisonPixel = nullptr; }