当前位置: 首页 > article >正文

OpenCV轮廓相关操作API (C++)

      在OpenCV中,轮廓(contours)是图像处理中的一个重要概念,通常用于形状分析、物体检测等任务。OpenCV提供了多种与轮廓相关的API,可以在C++中使用。

一.常用的与轮廓相关的操作及其对应的API函数

1.查找轮廓

findContours 函数用于在二值图像中查找轮廓。

void findContours(InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point() );

image: 输入的二值图像(通常为灰度图并经过阈值处理)。

contours: 检测到的轮廓,以std::vector<std::vector<Point>>形式存储。

hierarchy: 轮廓的拓扑信息,以std::vector<Vec4i>形式存储。

mode: 轮廓检索模式(如RETR_EXTERNAL, RETR_LIST, RETR_CCOMP, RETR_TREE)。

method: 轮廓逼近方法(如CHAIN_APPROX_SIMPLE, CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS, CHAIN_APPROX_NONE)。

offset: 可选的轮廓偏移量。

2.绘制轮廓

drawContours 函数用于在图像上绘制轮廓。

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness = 1, int lineType = LINE_8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point() );

image: 输出的图像。

contours: 轮廓,以std::vector<std::vector<Point>>形式存储。

contourIdx: 指定要绘制的轮廓索引,-1表示绘制所有轮廓。

color: 轮廓的颜色。

thickness: 轮廓线的厚度。负值表示填充轮廓。

lineType: 轮廓线的类型。

hierarchy: 可选的轮廓拓扑信息,用于指定绘制的轮廓层次。

maxLevel: 绘制轮廓的最大层次深度。

offset: 可选的轮廓偏移量。

3.轮廓近似

approxPolyDP 函数用于对轮廓进行多边形逼近。

void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);

curve: 输入的轮廓。

approxCurve: 输出的逼近多边形。

epsilon: 逼近精度,表示轮廓到逼近多边形的最大距离。

closed: 指示逼近多边形是否闭合。

4.轮廓面积和周长

contourArea 和 arcLength 函数分别用于计算轮廓的面积和周长。

double contourArea(InputArray contour, bool oriented = false);

double arcLength(InputArray curve, bool closed);

contour: 输入的轮廓。

oriented: 当为true时,返回有符号面积(正值表示逆时针方向,负值表示顺时针方向)。

curve: 输入的轮廓或曲线。

closed: 指示曲线是否闭合。

5.轮廓矩

moments 函数用于计算轮廓的矩。

Moments moments(InputArray array, bool binaryImage = false);

array: 输入的轮廓或图像。

binaryImage: 当为true时,假定输入图像为二值图像。

Moments结构体包含各种矩,如m00, m10, m01, m20, m11, m02等,可以用来计算轮廓的几何属性,具体有:

a.空间矩(Spatial Moments)

空间矩是图像像素位置与其灰度值的加权和,它们描述了图像的整体分布。在 cv::Moments 结构体中,空间矩包括:

m00:零阶矩,表示图像的总亮度(或质量)。

m10:一阶矩关于 x 轴的分量,描述了图像在 x 方向上的亮度分布。

m01:一阶矩关于 y 轴的分量,描述了图像在 y 方向上的亮度分布。

m20、m11、m02:二阶矩,分别描述了图像在 x2 方向上的亮度分布。

m30、m21、m12、m03:三阶矩,进一步描述了图像的高阶亮度分布特性。

b.中心矩(Central Moments)

中心矩是相对于图像重心的矩,它们描述了图像形状相对于重心的分布。在 cv::Moments 结构体中,中心矩包括:

mu20、mu11、mu02:二阶中心矩,分别描述了图像形状在 x2 方向上的相对于重心的分布。

mu30、mu21、mu12、mu03:三阶中心矩,进一步描述了图像形状的高阶相对于重心的分布特性。

c.中心归一化矩(Normalized Central Moments)

中心归一化矩是通过将中心矩除以零阶中心矩的适当幂次来得到的,它们具有尺度不变性。在 cv::Moments 结构体中,虽然直接没有列出归一化中心矩的成员变量,

但可以通过中心矩和零阶中心矩(实际上在 cv::Moments 中是 m00,但注意 m00 不是中心矩,这里只是为了说明归一化的概念)来计算得到。

归一化中心矩的一般形式为:

nu_pq = mu_pq / (m00^((p+q)/2 + 1))

其中,nu_pq 表示 p+q 阶归一化中心矩,mu_pq 表示 p+q 阶中心矩,m00 表示零阶矩。

6.获取轮廓的凸包

通过cv::convexHull()获取轮廓的凸包。

void convexHull( InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true );

points即输入的二维点集;

hull为输出的二维点集;

clockwise决定出来的轮廓是否为顺时针方向,为true时为顺时针方向;

returnPoints标志,为true时,hull将返回点集,此时为std::vector<cv::Point>类型,为false时,hull将返回返回对应于外壳点的轮廓点的索引。

二.代码示例

1.打开一个图片

#include <opencv2/opencv.hpp>

#include <iostream>

int main() {

    // 读取图像

    cv::Mat src = cv::imread("path_to_image.jpg", cv::IMREAD_GRAYSCALE);

    if (src.empty()) {

        std::cerr << "Could not open or find the image!" << std::endl;

        return -1;

    }

    // 阈值处理

    cv::Mat binary;

    cv::threshold(src, binary, 127, 255, cv::THRESH_BINARY);

    // 查找轮廓

    std::vector<std::vector<cv::Point>> contours;

    std::vector<cv::Vec4i> hierarchy;

    cv::findContours(binary, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

    // 绘制轮廓

    cv::Mat result;

    cv::cvtColor(src, result, cv::COLOR_GRAY2BGR);

    for (size_t i = 0; i < contours.size(); i++) {

        cv::drawContours(result, contours, (int)i, cv::Scalar(0, 255, 0), 2, cv::LINE_8, hierarchy, 0);

    }

    // 显示结果

    cv::imshow("Contours", result);

    cv::waitKey(0);

    return 0;

}

2.生成一个图像

#include <iostream>

#include <opencv2/opencv.hpp>

int main() {

    // 创建一个空白的图像

    cv::Mat image = cv::Mat::zeros(300, 300, CV_8UC1); // 单通道8位图像

    // 在图像中间画一个白色的圆形作为轮廓

    cv::circle(image, cv::Point(150, 150), 50, cv::Scalar(255), -1);

    // 查找图像中的轮廓

    std::vector<std::vector<cv::Point>> contours;

    cv::findContours(image, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    // 计算轮廓的矩

    cv::Moments moments = cv::moments(contours[0]);

    // 从矩中计算质心

    double cx = moments.m10 / moments.m00;

    double cy = moments.m01 / moments.m00;

    // 计算面积

    double area = moments.m00;

    // 在图像上标记质心

    cv::circle(image, cv::Point(static_cast<int>(cx), static_cast<int>(cy)), 5, cv::Scalar(128), -1);

    // 输出质心坐标和面积

    std::cout << "Centroid at (" << cx << ", " << cy << ")" << std::endl;

    std::cout << "Area: " << area << std::endl;

    // 显示图像

    cv::imshow("Contour with Centroid", image);

    cv::waitKey(0);

    return 0;

}


http://www.kler.cn/a/488425.html

相关文章:

  • 图像处理|腐蚀操作
  • 【华为OD-E卷 - 篮球比赛 100分(python、java、c++、js、c)】
  • 计算机网络之---无线网络的传输介质
  • Vue sm3国密 IE模式报错处理
  • Zookeeper 集群安装
  • (概率论)无偏估计
  • 探索 Docker Desktop:简化开发与部署的利器
  • 4.3.1 树、二叉树基本概念
  • 阿里云直播互动Web
  • R.swift库的详细用法
  • JavaScript系列(18)--异步编程模式
  • 【UI自动化测试】selenium操作补充
  • 【Docker】docker compose 安装 Redis Stack
  • Linux 文件的特殊权限—ACL权限控制
  • JavaScript Chrome 中的运行
  • Android 12.0 mtk平板camera2横屏预览旋转90度横屏保存录像旋转90度功能实现
  • Python对象的序列化和反序列化工具:Joblib与Pickle
  • Linux 系统 PWM 风扇驱动框架学习记录
  • 【比较乱,如果遇到相同问题可以看】Autoware.universe的绕障线路的参数修改
  • CSS——39. 文本修饰(文本属性)
  • 用 Python 绘制可爱的招财猫
  • 新车月交付突破2万辆!小鹏汽车“激活”智驾之困待解
  • Uniapp仿ChatGPT Stream流式输出(非Websocket)
  • UML(统一建模语言)
  • VUE3 VITE项目在 npm 中,关于 Vue 的常用命令有一些基础命令
  • clickhouse 离线包安装(ubuntu)