You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于局部曲率的图像边界彩色映射算法(OpenCV C/C++)咨询

刚好做过类似的需求,给你一套完整的OpenCV C++实现方案,分步骤来,每一步都有具体代码和思路:

整体实现流程

核心逻辑是:先从边界图像中提取连续的边界点序列 → 计算每个点的局部曲率 → 将曲率值映射为红-黄渐变的颜色 → 把颜色绘制到图像上可视化。

1. 提取边界点序列

首先假设你的输入是二值边界图(边界为白色,背景黑色),如果不是的话先转成二值图。用OpenCV的findContours提取轮廓,注意用CHAIN_APPROX_NONE保留所有边界点,这样后续计算曲率更准确。

#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace cv;
using namespace std;

int main() {
    // 读取边界图像,转灰度
    Mat src = imread("boundary_image.png", IMREAD_GRAYSCALE);
    if (src.empty()) {
        cerr << "Failed to read image!" << endl;
        return -1;
    }

    // 转二值图(如果原图不是二值的话)
    Mat binary;
    threshold(src, binary, 127, 255, THRESH_BINARY);

    // 提取轮廓
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);

    // 取第一个轮廓(如果是多轮廓,可遍历所有contours处理)
    vector<Point> boundary = contours[0];
    int n = boundary.size();

2. 计算局部曲率

这里给你两种常用的计算方法,按需选择:

方法一:向量夹角法(简单高效,适合快速可视化)

对于每个边界点,取它前后k个点(k=1时就是相邻点),计算相邻向量的夹角,曲率用π - 夹角表示——夹角越小,转弯越急,曲率越高;夹角接近π时,边界接近直线,曲率极低。

// 计算每个点的曲率(向量夹角法)
    vector<double> curvatures(n);
    int k = 1; // 邻域步长,可根据图像调整,k越大越平滑
    for (int i = 0; i < n; ++i) {
        // 处理循环边界(第一个点的前一个点是最后一个,反之亦然)
        int prev_idx = (i - k + n) % n;
        int next_idx = (i + k) % n;

        Point P_prev = boundary[prev_idx];
        Point P_curr = boundary[i];
        Point P_next = boundary[next_idx];

        // 计算向量
        Vec2d v1(P_curr.x - P_prev.x, P_curr.y - P_prev.y);
        Vec2d v2(P_next.x - P_curr.x, P_next.y - P_curr.y);

        // 避免除以0
        double len1 = norm(v1);
        double len2 = norm(v2);
        if (len1 < 1e-6 || len2 < 1e-6) {
            curvatures[i] = 0;
            continue;
        }

        // 计算向量夹角的余弦值
        double dot_product = v1[0] * v2[0] + v1[1] * v2[1];
        double cos_theta = dot_product / (len1 * len2);
        // 限制范围防止数值溢出
        cos_theta = max(min(cos_theta, 1.0), -1.0);
        double theta = acos(cos_theta);

        // 曲率值:π - θ,范围0~π,值越大曲率越高
        curvatures[i] = M_PI - theta;
    }

方法二:三点拟合圆法(更精准,适合需要定量曲率的场景)

通过三个点拟合圆,曲率是圆半径的倒数,半径越小曲率越高,还能区分凹凸方向(保留正负)。

// 辅助函数:三点拟合圆计算曲率
    double fitCircleCurvature(Point p1, Point p2, Point p3) {
        double x1 = p1.x, y1 = p1.y;
        double x2 = p2.x, y2 = p2.y;
        double x3 = p3.x, y3 = p3.y;

        double A = x2 - x1;
        double B = y2 - y1;
        double C = x3 - x1;
        double D = y3 - y1;
        double E = A*(x1+x2) + B*(y1+y2);
        double F = C*(x1+x3) + D*(y1+y3);
        double G = 2*(A*(y3-y2) - B*(x3-x2));

        if (fabs(G) < 1e-6) return 0; // 三点共线,曲率为0

        double cx = (D*E - B*F)/G;
        double cy = (A*F - C*E)/G;
        double r = sqrt(pow(x1 - cx, 2) + pow(y1 - cy, 2));
        if (r < 1e-6) return 0;

        // 曲率值,保留正负可区分凹凸,取绝对值则只看大小
        return 1.0 / r;
    }

    // 计算曲率(圆拟合法)
    vector<double> curvatures(n);
    int k = 3; // 取前后3个点,平滑噪声
    for (int i = 0; i < n; ++i) {
        int prev_idx = (i - k + n) % n;
        int next_idx = (i + k) % n;
        curvatures[i] = fabs(fitCircleCurvature(boundary[prev_idx], boundary[i], boundary[next_idx]));
    }

3. 曲率归一化与颜色映射

把曲率值归一到0~1范围,然后映射到红-黄渐变:黄色对应低曲率(接近直线),红色对应高曲率(急转弯)。这里用BGR通道直接插值,直观易懂。

// 归一化曲率到0~1范围
    double max_curv = *max_element(curvatures.begin(), curvatures.end());
    double min_curv = *min_element(curvatures.begin(), curvatures.end());
    double range = max_curv - min_curv;
    if (range < 1e-6) range = 1; // 防止所有曲率相同导致除以0

    // 创建可视化图像,白色背景
    Mat curvature_vis = Mat::zeros(src.size(), CV_8UC3);
    curvature_vis.setTo(Scalar(255, 255, 255));

    // 遍历每个边界点,绘制对应颜色
    for (int i = 0; i < n; ++i) {
        double t = (curvatures[i] - min_curv) / range; // t=0→低曲率(黄),t=1→高曲率(红)
        uchar green = 255 * (1 - t);
        uchar red = 255;
        // OpenCV是BGR顺序,所以蓝色通道设为0
        Vec3b color(0, green, red);
        // 画实心圆,点更大更明显
        circle(curvature_vis, boundary[i], 2, color, -1);
    }

    // 显示结果
    imshow("Boundary Curvature Color Map", curvature_vis);
    imwrite("curvature_map.png", curvature_vis);
    waitKey(0);

    return 0;
}

4. 优化小技巧

  • 去噪声:如果边界有毛刺,先对原图做高斯滤波(GaussianBlur)再提取轮廓,或者用approxPolyDP对轮廓做平滑(注意参数ε不要太大,避免丢失细节)。
  • 邻域调整:k值越大,曲率结果越平滑,但会损失局部细节;k越小越敏感,噪声也越多,根据你的图像调整。
  • 多轮廓处理:如果输入图像有多个边界,遍历contours数组,逐个计算曲率并绘制即可。

内容的提问来源于stack exchange,提问作者Saania

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:32:26