OpenCV自学笔记十五:图像轮廓

2023-09-21 19:18:16

目录

1、查找并绘制轮廓

2、矩特征

3、Hu矩

4、轮廓拟合

5、凸包


1、查找并绘制轮廓

在OpenCV中,可以使用`cv2.findContours()`函数来查找图像中的轮廓,并使用`cv2.drawContours()`函数将轮廓绘制到图像上。下面是一个示例代码:

import cv2

# 读取图像并转换为灰度图像

image = cv2.imread('image.jpg')

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 进行边缘检测

edges = cv2.Canny(gray, 50, 150)

# 查找轮廓

contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 绘制轮廓

cv2.drawContours(image, contours, -1, (0, 255, 0), 2)

# 显示结果

cv2.imshow("Contours", image)

cv2.waitKey(0)

cv2.destroyAllWindows()

在这个示例中,我们首先使用`cv2.imread()`函数读取一张图像,并将其转换为灰度图像,以便进行边缘检测。

然后,我们使用`cv2.Canny()`函数对灰度图像进行边缘检测,该函数可以根据指定的阈值自动检测图像中的边缘。

接下来,我们使用`cv2.findContours()`函数查找边缘图像中的轮廓。`cv2.findContours()`函数返回两个值:轮廓列表和层级信息。这里我们选择了`RETR_EXTERNAL`表示只检测最外层的轮廓,以及`CHAIN_APPROX_SIMPLE`表示使用简化的轮廓表示方法。

最后,我们使用`cv2.drawContours()`函数将轮廓绘制到原始图像上。该函数需要传入原始图像、轮廓列表、要绘制的轮廓索引(-1表示绘制所有轮廓)、绘制的颜色和线宽等参数。

最后,使用`cv2.imshow()`函数显示绘制了轮廓的图像。

2、矩特征

在OpenCV中,可以使用`cv::moments()`函数来计算图像的矩特征。该函数接受一个二值化的图像作为输入,并返回一个`Moments`结构体,其中包含了计算得到的各种矩特征。

以下是一个使用OpenCV计算矩特征的简单示例:

#include <opencv2/opencv.hpp>

int main() {

// 读取图像

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

// 对图像进行二值化处理

cv::Mat binaryImage;

cv::threshold(image, binaryImage, 128, 255, cv::THRESH_BINARY);

// 计算图像的矩特征

cv::Moments moments = cv::moments(binaryImage);

// 输出矩特征

std::cout << "M00: " << moments.m00 << std::endl; // 零阶矩

std::cout << "M10: " << moments.m10 << std::endl; // 一阶矩

std::cout << "M01: " << moments.m01 << std::endl; // 一阶矩

std::cout << "M20: " << moments.m20 << std::endl; // 二阶矩

std::cout << "M02: " << moments.m02 << std::endl; // 二阶矩

// 其他高阶矩...

return 0;

}

在上述示例中,首先使用`cv::imread()`函数读取图像,并将其转换为灰度图像。然后,使用`cv::threshold()`函数对图像进行二值化处理,生成一个二值图像。接下来,使用`cv::moments()`函数计算二值图像的矩特征,并将结果保存在`Moments`结构体中。最后,输出一些矩特征的值。

3、Hu矩

Hu矩(Hu Moments)是一种描述图像形状的统计特征,由M. K. Hu在1962年提出。它是基于图像的中心矩计算得到的,具有旋转、平移和缩放不变性。

以下是使用OpenCV在Python中计算图像的Hu矩的示例代码:

import cv2

import numpy as np

# 读取图像

image = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)

# 对图像进行二值化处理

_, binaryImage = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)

# 计算图像的矩特征

moments = cv2.moments(binaryImage)

# 计算Hu矩

huMoments = cv2.HuMoments(moments)

huMoments = -np.sign(huMoments) * np.log10(np.abs(huMoments)) # 转换为对数形式

# 输出Hu矩

for i in range(7):

print("Hu{}: {}".format(i+1, huMoments[i][0]))

在上述示例中,我们首先使用`cv2.imread()`函数读取图像,并将其转换为灰度图像。然后,使用`cv2.threshold()`函数对图像进行二值化处理,生成一个二值图像。接下来,使用`cv2.moments()`函数计算二值图像的矩特征,并将结果保存在`moments`变量中。然后,使用`cv2.HuMoments()`函数计算Hu矩,并将结果保存在`huMoments`变量中。最后,通过遍历数组,输出每个Hu矩的值。

需要注意的是,Python中的OpenCV返回的Hu矩是以浮点数形式表示的,如果需要转换为通常的对数形式,可以使用`np.sign()`和`np.log10()`函数进行转换。

4、轮廓拟合

OpenCV中的轮廓拟合是指将检测到的图像轮廓近似地拟合为简单的几何形状,如直线、圆等。该功能可以用于形状分析、对象识别和边缘检测等应用。

在OpenCV中,有多种方法可用于轮廓拟合,常用的方法包括最小包围矩形、最小外接圆和多边形拟合。

1. 最小包围矩形:使用`cv2.minAreaRect()`函数计算轮廓的最小包围矩形,该矩形可以不与轮廓完全重合。

2. 最小外接圆:使用`cv2.minEnclosingCircle()`函数计算轮廓的最小外接圆,该圆将完全包含住轮廓。

3. 多边形拟合:使用`cv2.approxPolyDP()`函数对轮廓进行多边形拟合,可以通过指定一个精度参数来控制拟合精度。

下面是一个示例代码,展示了如何使用OpenCV进行轮廓拟合:

​
import cv2

# 读取图像并灰度化

image = cv2.imread("image.jpg")

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 边缘检测

edges = cv2.Canny(gray, 50, 150)

# 寻找轮廓

contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 遍历每个轮廓

for contour in contours:

# 最小包围矩形

rect = cv2.minAreaRect(contour)

box = cv2.boxPoints(rect)

box = np.int0(box)

cv2.drawContours(image, [box], 0, (0, 255, 0), 2)

# 最小外接圆

(x, y), radius = cv2.minEnclosingCircle(contour)

center = (int(x), int(y))

radius = int(radius)

cv2.circle(image, center, radius, (0, 0, 255), 2)

# 多边形拟合

epsilon = 0.01 * cv2.arcLength(contour, True)

approx = cv2.approxPolyDP(contour, epsilon, True)

cv2.drawContours(image, [approx], 0, (255, 0, 0), 2)

# 显示结果图像

cv2.imshow("Contours", image)

cv2.waitKey(0)

cv2.destroyAllWindows()

​

在上述示例中,首先读取图像并将其转换为灰度图像。然后通过Canny边缘检测算法找到图像的边缘。接下来使用`cv2.findContours()`函数寻找轮廓。

在遍历每个轮廓时,我们分别使用`cv2.minAreaRect()`函数计算最小包围矩形,并使用`cv2.boxPoints()`函数将矩形转换为四个角点。然后使用`cv2.minEnclosingCircle()`函数计算最小外接圆的圆心和半径。最后,通过`cv2.approxPolyDP()`函数对轮廓进行多边形拟合,可以通过调整精度参数来控制拟合的精度。

最后,我们使用`cv2.drawContours()`函数将拟合结果绘制在原始图像上,并显示结果图像。

5、凸包

OpenCV中的凸包(Convex Hull)是指能够完全包围给定点集的最小凸多边形。它可以用于计算点集的外形以及检测图像中的手势、物体边界等应用。

在OpenCV中,可以使用`cv2.convexHull()`函数来计算给定点集的凸包。该函数接受一个点集作为输入,并返回一个表示凸包的点集或轮廓。

下面是一个示例代码,展示了如何使用OpenCV计算凸包:

import cv2

import numpy as np

# 读取图像并灰度化

image = cv2.imread("image.jpg")

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 边缘检测

edges = cv2.Canny(gray, 50, 150)

# 寻找轮廓

contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 遍历每个轮廓

for contour in contours:

# 计算凸包

hull = cv2.convexHull(contour)

# 绘制凸包

cv2.drawContours(image, [hull], 0, (0, 255, 0), 2)

# 显示结果图像

cv2.imshow("Convex Hull", image)

cv2.waitKey(0)

cv2.destroyAllWindows()

在上述示例中,首先读取图像并将其转换为灰度图像。然后通过Canny边缘检测算法找到图像的边缘。接下来使用`cv2.findContours()`函数寻找轮廓。

在遍历每个轮廓时,我们使用`cv2.convexHull()`函数计算凸包。最后,使用`cv2.drawContours()`函数将凸包绘制在原始图像上,并显示结果图像。

需要注意的是,`cv2.convexHull()`函数可以接受不同的参数和标志,用于控制凸包计算的精度和输出形式。根据具体需求,可以使用不同的参数进行调整。

更多推荐

大数据驱动业务增长:数据分析和洞察力的新纪元

文章目录大数据的崛起大数据的特点大数据技术大数据驱动业务增长1.洞察力和决策支持2.个性化营销3.风险管理4.产品创新大数据分析的新纪元1.云计算和大数据示例代码:使用AWS的ElasticMapReduce(EMR)进行大数据分析。2.人工智能和机器学习示例代码:使用Python的Scikit-Learn库进行机器学

外国固定资产管理系统功能有哪些

很多公司都在寻找提高自己资产管理效益的方法。为了满足这一要求,国外的固定资产管理系统已经发展成多种形式。以下是国外一些常见的固定资产管理系统的特点:自动化和智能化:许多现代固定资产管理系统采用自动化和数字化技术,以简化流程,减少错误,提高数据准确性。这些系统通常包括电子库存管理、一键生成报告和实时跟踪资产位置。集成:国

机器学习:在线学习和离线学习区别

机器学习中的在线学习(OnlineLearning)和离线学习(OfflineLearning)是两种不同的学习方式,它们在数据处理和模型更新方面有着明显的区别。以下是它们的主要区别:数据获取方式:在线学习:在在线学习中,模型是不断地从数据流中接收新的样本并进行学习。这意味着模型会随着时间的推移不断更新,以适应新的数据

深度学习:pytorch nn.Embedding详解

目录1nn.Embedding介绍1.1nn.Embedding作用1.2nn.Embedding函数描述1.3nn.Embedding词向量转化2nn.Embedding实战2.1embedding如何处理文本2.2embedding使用示例2.3nn.Embedding的可学习性1nn.Embedding介绍1.1

【SpringMVC】自定义注解

【SpringMVC】自定义注解前言1.什么是注解?2.注解的用处3.注解的原理1.1.@Override1.2.@SuppressWarnings2.JDK元注解2.1.@Retention2.2.@Target2.3.@Inherited2.4.@Documented3.自定义注解3.1.自定义注解的分类注解类结语

Map<K,V>的使用和List学习

MapMap是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。对于静态类型的查找来说,一般直接遍历或者用二分查找【不会对区间进行插入和删除操作】而在现实生活中的查找比如:根据姓名查询考试成绩通讯录,即根据姓名查询联系方式不重复集合,即需要先搜索关键字是否已经在集合中注:Map最重要的特性就

【Redis】深入探索 Redis 的数据类型 —— 列表 List

文章目录一、List类型介绍二、List类型相关命令2.1LPUSH和RPUSH、LPUSHX和RPUSHX2.2LPOP和RPOP、BLPOP和BRPOP2.3LRANGE、LINDEX、LINSERT、LLEN2.4列表相关命令总结三、List类型内部编码3.1压缩列表(ziplist)3.2链表(linkedli

ceph分布式存储

目录一、概述二、组件三、架构图四、搭建一、概述ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能、可靠性和可扩展性。特点:1.统一存储虽然ceph底层是一个分布式文件系统,但由于在上层开发了支持对象和块的接口。所以在开源存储软件中,能够一统江湖。至于能不能千秋万代,就不知了。2.高扩展性扩容方便、容量大。能够

前端Vue3+element-plus表单输入框实现Cron表达式校验

页面如下:本来想手写正则表达式校验,结果发现很麻烦,cron表达式组成如下:开发使用框架为vue3+element-plus,于是选择cron-validator依赖。使用步骤如下:1、通过npminstallcron-validator命令安装:2、可以通过package.json文件中看到,已安装成功。3、在你需要

自动化测试的生命周期是什么?

软件测试发展到今日,已经逐渐标准化且能力更强,其流程每天都在发展。测试人员的技术熟练程度对于整个测试阶段的成功来说至关重要。测试不再意味着仅仅发现错误;它的范围已经扩大,从任何开发项目开始就可以看出它的重要性。当谈论起自动化测试生命周期(AutomationTestingLifeCycle)时,大多数人认为这只是SDL

【vue】vue 中插槽的三种类型:

文章目录一、匿名插槽:``二、具名插槽:``三、作用域插槽一、匿名插槽:<slot></slot>1.没有为插槽指定名称2.通过slot标签可以添加匿名插槽3.在使用组件的时候,组件中的内容会填充到所有匿名插槽的位置,所以在封装组件的时候,匿名插槽一般只有一个4.匿名插槽可以设置默认的内容,如果没有传入内容就使用默认内

热文推荐