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;

}

相关推荐
Ven%2 小时前
如何让后台运行llamafactory-cli webui 即使关掉了ssh远程连接 也在运行
运维·人工智能·chrome·python·ssh·aigc
Jeo_dmy2 小时前
(七)人工智能进阶之人脸识别:从刷脸支付到智能安防的奥秘,小白都可以入手的MTCNN+Arcface网络
人工智能·计算机视觉·人脸识别·猪脸识别
睡觉狂魔er4 小时前
自动驾驶控制与规划——Project 5: Lattice Planner
人工智能·机器学习·自动驾驶
xm一点不soso4 小时前
ROS2+OpenCV综合应用--11. AprilTag标签码跟随
人工智能·opencv·计算机视觉
陌然。。5 小时前
【701. 二叉搜索树中的插入操作 中等】
数据结构·c++·算法·leetcode·深度优先
Ritsu栗子5 小时前
代码随想录算法训练营day25
c++·算法
云卓SKYDROID5 小时前
无人机+Ai应用场景!
人工智能·无人机·科普·高科技·云卓科技
是十一月末5 小时前
机器学习之过采样和下采样调整不均衡样本的逻辑回归模型
人工智能·python·算法·机器学习·逻辑回归
小禾家的5 小时前
.NET AI 开发人员库 --AI Dev Gallery简单示例--问答机器人
人工智能·c#·.net
生信碱移5 小时前
万字长文:机器学习的数学基础(易读)
大数据·人工智能·深度学习·线性代数·算法·数学建模·数据分析