std::min,std::max 与 MFC冲突的解决

本文介绍了解决std::min和std::max与MFC冲突的方法。通过在stdafx.h文件中定义NOMINMAX并取消定义max和min,可以有效避免冲突,确保正常使用std::min和std::max。

std::min,std::max 与 MFC冲突的解决
黄国强 2010-3-3

这个问题非常讨厌,时不时会冒出来。综合了网上的多种解决方法,总结了一下。
在项目的 stdafx.h 文件中,确保包含自己写的头文件行放在文件尾部。然后在开头处加上三行,就好了。例子如下:

// 需要加上以下三行
#define NOMINMAX
#undef max
#undef min
// 从这里开始就可以使用 std::min和std::max了
#include "myself1.h"    // 自己写的头文件
#include "myself2.h"    // 自己写的头文件

网上看来的,加个括号写成 (std::max) 也能避免这个问题,而且更方便。

#include "pch.h" #include "Sphere.h" #include <afxwin.h> // 包含 MFC 核心头文件 #include <algorithm> // 为了使用 std::max #include <cmath> // 为了使用 std::round CSphere::CSphere() : m_lightPos(100, 100, 100) { } void CSphere::InitOctahedron(double radius) { m_vertices.clear(); m_triangles.clear(); m_normals.clear(); // 正八面体顶点 (位于球面上) m_vertices.push_back(Point3D(0, 0, radius)); // 0: 上顶点 m_vertices.push_back(Point3D(0, 0, -radius)); // 1: 下顶点 m_vertices.push_back(Point3D(radius, 0, 0)); // 2: 右顶点 m_vertices.push_back(Point3D(-radius, 0, 0)); // 3: 左顶点 m_vertices.push_back(Point3D(0, radius, 0)); // 4: 前顶点 m_vertices.push_back(Point3D(0, -radius, 0)); // 5: 后顶点 // 正八面体三角形面 // 注意:这里存在重复的三角形,应该修正为每个面只定义一次 m_triangles.push_back(Triangle(0, 2, 4)); m_triangles.push_back(Triangle(0, 4, 3)); m_triangles.push_back(Triangle(0, 3, 5)); m_triangles.push_back(Triangle(0, 5, 2)); m_triangles.push_back(Triangle(1, 2, 5)); m_triangles.push_back(Triangle(1, 5, 3)); m_triangles.push_back(Triangle(1, 3, 4)); m_triangles.push_back(Triangle(1, 4, 2)); CalculateNormals(); } void CSphere::CreateRecursiveSphere(double radius, int level) { InitOctahedron(radius); if (level <= 0) return; std::vector<Triangle> newTriangles; for (const auto& tri : m_triangles) { SubdivideTriangle(tri, level, newTriangles); } m_triangles = newTriangles; CalculateNormals(); } void CSphere::SubdivideTriangle(const Triangle& tri, int level, std::vector<Triangle>& result) { if (level == 0) { result.push_back(tri); return; } // 计算各边中点 int v1 = tri.v1; int v2 = tri.v2; int v3 = tri.v3; // 边v1-v2的中点 Point3D mid12 = (m_vertices[v1] + m_vertices[v2]) * 0.5; mid12 = mid12.Normalize() * mid12.Magnitude(); // 拉伸到球面上 // 边v2-v3的中点 Point3D mid23 = (m_vertices[v2] + m_vertices[v3]) * 0.5; mid23 = mid23.Normalize() * mid23.Magnitude(); // 拉伸到球面上 // 边v3-v1的中点 Point3D mid31 = (m_vertices[v3] + m_vertices[v1]) * 0.5; mid31 = mid31.Normalize() * mid31.Magnitude(); // 拉伸到球面上 // 添加新顶点 // 修改:将 int 改为 size_t 避免 C4267 警告 size_t newV1 = m_vertices.size(); m_vertices.push_back(mid12); size_t newV2 = m_vertices.size(); m_vertices.push_back(mid23); size_t newV3 = m_vertices.size(); m_vertices.push_back(mid31); // 递归细分四个小三角形 SubdivideTriangle(Triangle(v1, static_cast<int>(newV1), static_cast<int>(newV3)), level - 1, result); SubdivideTriangle(Triangle(static_cast<int>(newV1), v2, static_cast<int>(newV2)), level - 1, result); SubdivideTriangle(Triangle(static_cast<int>(newV3), static_cast<int>(newV2), v3), level - 1, result); SubdivideTriangle(Triangle(static_cast<int>(newV1), static_cast<int>(newV2), static_cast<int>(newV3)), level - 1, result); } void CSphere::CalculateNormals() { m_normals.resize(m_vertices.size()); for (const auto& tri : m_triangles) { Point3D v1 = m_vertices[tri.v1]; Point3D v2 = m_vertices[tri.v2]; Point3D v3 = m_vertices[tri.v3]; Point3D edge1 = v2 - v1; Point3D edge2 = v3 - v1; Point3D normal = CrossProduct(edge1, edge2).Normalize(); m_normals[tri.v1] = m_normals[tri.v1] + normal; m_normals[tri.v2] = m_normals[tri.v2] + normal; m_normals[tri.v3] = m_normals[tri.v3] + normal; } // 归一化法向量 for (auto& normal : m_normals) { normal = normal.Normalize(); } } Point3D CSphere::CrossProduct(const Point3D& a, const Point3D& b) const { return Point3D( a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x ); } double CSphere::DotProduct(const Point3D& a, const Point3D& b) const { return a.x * b.x + a.y * b.y + a.z * b.z; } void CSphere::DrawWireframe(CDC* pDC) { CPen pen(PS_SOLID, 1, RGB(255, 255, 255)); CPen* pOldPen = pDC->SelectObject(&pen); for (const auto& tri : m_triangles) { Point3D v1 = m_vertices[tri.v1]; Point3D v2 = m_vertices[tri.v2]; Point3D v3 = m_vertices[tri.v3]; pDC->MoveTo(CPoint(v1.x, v1.y)); pDC->LineTo(CPoint(v2.x, v2.y)); pDC->LineTo(CPoint(v3.x, v3.y)); pDC->LineTo(CPoint(v1.x, v1.y)); } pDC->SelectObject(pOldPen); // 恢复旧画笔 } void CSphere::DrawLitWireframe(CDC* pDC) { for (const auto& tri : m_triangles) { Point3D v1 = m_vertices[tri.v1]; Point3D v2 = m_vertices[tri.v2]; Point3D v3 = m_vertices[tri.v3]; // 计算三角形法向量 Point3D edge1 = v2 - v1; Point3D edge2 = v3 - v1; Point3D normal = CrossProduct(edge1, edge2).Normalize(); // 计算光照强度 Point3D lightDir = (m_lightPos - v1).Normalize(); double intensity = DotProduct(normal, lightDir); intensity = std::max(0.1, intensity); // 最小强度 // 根据光照强度计算颜色 // 修改:使用 std::round 避免 C4244 警告 int r = static_cast<int>(std::round(255 * intensity)); int g = static_cast<int>(std::round(255 * intensity)); int b = static_cast<int>(std::round(255 * intensity)); CPen pen(PS_SOLID, 1, RGB(r, g, b)); CPen* pOldPen = pDC->SelectObject(&pen); pDC->MoveTo(CPoint(v1.x, v1.y)); pDC->LineTo(CPoint(v2.x, v2.y)); pDC->LineTo(CPoint(v3.x, v3.y)); pDC->LineTo(CPoint(v1.x, v1.y)); pDC->SelectObject(pOldPen); // 恢复旧画笔 } } void CSphere::DrawSurface(CDC* pDC) { CBrush brush(RGB(255, 255, 255)); CBrush* pOldBrush = pDC->SelectObject(&brush); CPen pen(PS_SOLID, 1, RGB(0, 0, 0)); CPen* pOldPen = pDC->SelectObject(&pen); for (const auto& tri : m_triangles) { Point3D v1 = m_vertices[tri.v1]; Point3D v2 = m_vertices[tri.v2]; Point3D v3 = m_vertices[tri.v3]; CPoint points[3] = { CPoint(v1.x, v1.y), CPoint(v2.x, v2.y), CPoint(v3.x, v3.y) }; pDC->Polygon(points, 3); } pDC->SelectObject(pOldBrush); // 恢复旧画刷 pDC->SelectObject(pOldPen); // 恢复旧画笔 } void CSphere::DrawLitSurface(CDC* pDC) { CPen pen(PS_SOLID, 1, RGB(0, 0, 0)); CPen* pOldPen = pDC->SelectObject(&pen); for (const auto& tri : m_triangles) { Point3D v1 = m_vertices[tri.v1]; Point3D v2 = m_vertices[tri.v2]; Point3D v3 = m_vertices[tri.v3]; // 计算各顶点的光照强度 Point3D normal1 = m_normals[tri.v1]; Point3D normal2 = m_normals[tri.v2]; Point3D normal3 = m_normals[tri.v3]; Point3D lightDir = (m_lightPos - v1).Normalize(); double intensity1 = std::max(0.1, DotProduct(normal1, lightDir)); double intensity2 = std::max(0.1, DotProduct(normal2, lightDir)); double intensity3 = std::max(0.1, DotProduct(normal3, lightDir)); // 计算颜色 // 修改:使用 std::round 避免 C4244 警告 int r1 = static_cast<int>(std::round(255 * intensity1)); int g1 = static_cast<int>(std::round(255 * intensity1)); int b1 = static_cast<int>(std::round(255 * intensity1)); int r2 = static_cast<int>(std::round(255 * intensity2)); int g2 = static_cast<int>(std::round(255 * intensity2)); int b2 = static_cast<int>(std::round(255 * intensity2)); int r3 = static_cast<int>(std::round(255 * intensity3)); int g3 = static_cast<int>(std::round(255 * intensity3)); int b3 = static_cast<int>(std::round(255 * intensity3)); // 使用平均颜色填充三角形(简化实现,真实Gouraud着色需要更复杂的算法) int r = (r1 + r2 + r3) / 3; int g = (g1 + g2 + g3) / 3; int b = (b1 + b2 + b3) / 3; CBrush brush(RGB(r, g, b)); CBrush* pOldBrush = pDC->SelectObject(&brush); CPoint points[3] = { CPoint(v1.x, v1.y), CPoint(v2.x, v2.y), CPoint(v3.x, v3.y) }; pDC->Polygon(points, 3); pDC->SelectObject(pOldBrush); // 恢复旧画刷 } pDC->SelectObject(pOldPen); // 恢复旧画笔 }我的max部分报错,哪里出了问题
06-23
优化下面代码的效果,目前输出结果存在重影明显,图像不完整,失真 cv::Mat COpencv1Dlg::FusionImages(const cv::Mat& m_matImage, const cv::Mat& m_processedImage) { // 确保输入图像不为空 if (m_matImage.empty() || m_processedImage.empty()) { AfxMessageBox(_T("输入图像为空!")); return cv::Mat(); } // 1. 转换为灰度图用于特征提取 cv::Mat gray1, gray2; if (m_matImage.channels() == 3) cv::cvtColor(m_matImage, gray1, cv::COLOR_BGR2GRAY); else gray1 = m_matImage.clone(); if (m_processedImage.channels() == 3) cv::cvtColor(m_processedImage, gray2, cv::COLOR_BGR2GRAY); else gray2 = m_processedImage.clone(); // 2. 特征点检测匹配(使用SIFT算法) cv::Ptr<cv::SIFT> sift = cv::SIFT::create(); std::vector<cv::KeyPoint> keypoints1, keypoints2; cv::Mat descriptors1, descriptors2; sift->detectAndCompute(gray1, cv::Mat(), keypoints1, descriptors1); sift->detectAndCompute(gray2, cv::Mat(), keypoints2, descriptors2); // 匹配特征点(FLANN匹配器) cv::FlannBasedMatcher matcher; std::vector<std::vector<cv::DMatch>> knn_matches; matcher.knnMatch(descriptors1, descriptors2, knn_matches, 2); // 筛选优质匹配点(Lowe's ratio test) const float ratio_thresh = 0.75f; std::vector<cv::DMatch> good_matches; for (auto& m : knn_matches) { if (m[0].distance < ratio_thresh * m[1].distance) { good_matches.push_back(m[0]); } } if (good_matches.size() < 10) { // 匹配点不足,无法配准 AfxMessageBox(_T("匹配点数量不足,无法融合!")); return cv::Mat(); } // 3. 计算变换矩阵(单应性矩阵,用于将第二张图映射到第一张图的坐标系) std::vector<cv::Point2f> src_pts, dst_pts; for (auto& m : good_matches) { src_pts.push_back(keypoints2[m.trainIdx].pt); // 第二张图的点 dst_pts.push_back(keypoints1[m.queryIdx].pt); // 第一张图的对应点 } cv::Mat homography = cv::findHomography(src_pts, dst_pts, cv::RANSAC, 5.0); // 4. 计算融合后图像的大小(包含两张图的所有区域) int h1 = m_matImage.rows, w1 = m_matImage.cols; int h2 = m_processedImage.rows, w2 = m_processedImage.cols; // 计算第二张图四个角映射到第一张图坐标系后的位置 std::vector<cv::Point2f> corners(4); corners[0] = cv::Point2f(0, 0); corners[1] = cv::Point2f(w2, 0); corners[2] = cv::Point2f(w2, h2); corners[3] = cv::Point2f(0, h2); std::vector<cv::Point2f> corners_transformed(4); cv::perspectiveTransform(corners, corners_transformed, homography); // 确定融合图像的边界 int min_x = std::min(0, (int)std::min_element(corners_transformed.begin(), corners_transformed.end(), [](const cv::Point2f& a, const cv::Point2f& b) { return a.x < b.x; })->x); int max_x = std::max(w1, (int)std::max_element(corners_transformed.begin(), corners_transformed.end(), [](const cv::Point2f& a, const cv::Point2f& b) { return a.x < b.x; })->x); int min_y = std::min(0, (int)std::min_element(corners_transformed.begin(), corners_transformed.end(), [](const cv::Point2f& a, const cv::Point2f& b) { return a.y < b.y; })->y); int max_y = std::max(h1, (int)std::max_element(corners_transformed.begin(), corners_transformed.end(), [](const cv::Point2f& a, const cv::Point2f& b) { return a.y < b.y; })->y); int fusion_w = max_x - min_x; int fusion_h = max_y - min_y; // 5. 对第二张图进行透视变换(映射到第一张图坐标系) cv::Mat transformed_img; cv::Mat translate_mat = (cv::Mat_<double>(3, 3) << 1, 0, -min_x, 0, 1, -min_y, 0, 0, 1); // 平移矩阵(消除负坐标) cv::warpPerspective(m_processedImage, transformed_img, translate_mat * homography, cv::Size(fusion_w, fusion_h)); // 6. 将第一张图绘制到融合图像的对应位置 cv::Mat fusion_img = cv::Mat::zeros(fusion_h, fusion_w, m_matImage.type()); m_matImage.copyTo(fusion_img(cv::Rect(-min_x, -min_y, w1, h1))); // 第一张图的位置(平移补偿) // 7. 融合重合区域(加权过渡) for (int y = 0; y < fusion_h; ++y) { for (int x = 0; x < fusion_w; ++x) { // 检查当前像素是否在两张图的重叠区域 bool in_img1 = (x >= -min_x && x < -min_x + w1 && y >= -min_y && y < -min_y + h1); bool in_img2 = (transformed_img.at<cv::Vec3b>(y, x) != cv::Vec3b(0, 0, 0)); // 非黑像素(假设原图无纯黑区域) if (in_img1 && in_img2) { // 重合区域:加权融合 // 计算权重(基于到图像边缘的距离,平滑过渡) cv::Vec3b pix1 = fusion_img.at<cv::Vec3b>(y, x); cv::Vec3b pix2 = transformed_img.at<cv::Vec3b>(y, x); // 简单加权(可根据需求替换为更复杂的融合算法,如拉普拉斯金字塔) float alpha = 0.5f; // 0.5表示平均权重,可动态调整 fusion_img.at<cv::Vec3b>(y, x) = pix1 * alpha + pix2 * (1 - alpha); } else if (in_img2) { // 仅第二张图的区域:直接复制 fusion_img.at<cv::Vec3b>(y, x) = transformed_img.at<cv::Vec3b>(y, x); } // 仅第一张图的区域:保持不变 } } return fusion_img; }
最新发布
10-25
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

acloud_csu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值