OpenCV入门11:轮廓提取和形状识别
轮廓分析主要用于轮廓提取和形状识别等任务。在OpenCV中,轮廓提取和形状识别是图像处理和计算机视觉中常见的任务。下面是关于这两个知识点的一些基本内容:
-
轮廓提取:
轮廓提取是指从图像中提取出物体轮廓的过程。在OpenCV中,可以使用cv::findContours()
函数来实现轮廓提取。以下是一个简单的示例:
cv::Mat image = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE); // 读取灰度图像
cv::Mat binaryImage;
cv::threshold(image, binaryImage, 128, 255, cv::THRESH_BINARY); // 二值化分割,大于阈值为255,小于阈值为0
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
// 遍历轮廓并绘制
cv::findContours(binaryImage, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
cv::Mat contoursImage = cv::Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); ++i)
{ cv::drawContours(contoursImage, contours, i, cv::Scalar(0, 0, 255), 2, cv::LINE_8, hierarchy, 0);
}
cv::imshow("Contours Image", contoursImage);
cv::waitKey(0);
在示例中,首先通过阈值分割将图像二值化,然后使用cv::findContours()
函数找到图像中的轮廓,最后通过cv::drawContours()
函数绘制轮廓。
-
轮廓面积与周长:
可以使用cv::contourArea()
函数计算轮廓的面积,并使用cv::arcLength()
函数计算轮廓的周长。这些特征可以用于识别不同形状的轮廓。例如,可以通过设定面积和周长的阈值来筛选特定大小的轮廓。
-
轮廓凸包:
凸包是将轮廓包围在一个最小凸多边形内的过程。OpenCV提供了cv::convexHull()
函数用于计算轮廓的凸包。通过比较凸包的顶点数量和轮廓的顶点数量,可以判断轮廓是否是凸形状。
-
轮廓形心:
形心是轮廓表示的几何中心,可以使用cv::moments()
函数计算轮廓的形心。形心坐标可以用于进一步的形状识别。
-
轮廓外接圆:
可以使用cv::minEnclosingCircle()
函数计算轮廓的外接圆。通过比较外接圆的半径和轮廓的尺寸,可以判断轮廓是否是圆形状。
-
轮廓外接矩形:
使用cv::boundingRect()
函数可以计算轮廓的外接矩形,其由矩形的左上角坐标和宽度、高度组成。外接矩形的宽高比可以用于识别特定宽高比的轮廓。
-
轮廓最小面积矩形:
可以使用cv::minAreaRect()
函数计算轮廓的最小面积矩形,该矩形是能够包围轮廓的最小面积矩形框。可以通过比较矩形的宽高比、角度等特征来识别轮廓的形状。
- 形状识别:
以上这些算法和特征可以进行轮廓形状识别的补充。通过结合多个特征和算法,可以更准确地识别不同形状的轮廓。
对于圆形识别和直线识别,OpenCV提供了相应的函数和算法。以下是一些常用的方法:
- 圆形识别:
使用霍夫圆变换(Hough Circle Transform)cv::HoughCircles()
函数来检测图像中的圆。该函数可以帮助你找到图像中的圆形轮廓,并返回识别到的圆形的圆心和半径。
cv::Mat image = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE); // 读取灰度图像
cv::Mat blurredImage;
cv::GaussianBlur(image, blurredImage, cv::Size(5, 5), 0); // 高斯模糊
std::vector<cv::Vec3f> circles;
cv::HoughCircles(blurredImage, circles, cv::HOUGH_GRADIENT, 1, 100, 50, 30, 0, 0);
// 霍夫圆变换
// 绘制识别到的圆形
cv::Mat circlesImage = cv::Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < circles.size(); ++i)
{ cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); int radius = cvRound(circles[i][2]); cv::circle(circlesImage, center, radius, cv::Scalar(0, 0, 255), 2, cv::LINE_8);
}
cv::imshow("Circles Image", circlesImage);
cv::waitKey(0);
- 直线识别:
使用霍夫直线变换(Hough Line Transform)cv::HoughLines()
函数来检测图像中的直线。该函数可以检测图像中的直线轮廓,并返回检测到的直线的参数。
cv::Mat image = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE); // 读取灰度图像
cv::Mat blurredImage; cv::GaussianBlur(image, blurredImage, cv::Size(5, 5), 0); // 高斯模糊
cv::Canny(blurredImage, blurredImage, 50, 150); // 边缘检测
std::vector<cv::Vec2f> lines;
cv::HoughLines(blurredImage, lines, 1, CV_PI / 180, 100); // 霍夫直线变换
// 绘制识别到的直线
cv::Mat linesImage = cv::Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < lines.size(); ++i)
{ float rho = lines[i][0]; float theta = lines[i][1]; double a = cos(theta); double b = sin(theta); double x0 = a * rho; double y0 = b * rho; cv::Point pt1(cvRound(x0 + 1000 * (-b)), cvRound(y0 + 1000 * (a))); cv::Point pt2(cvRound(x0 - 1000 * (-b)), cvRound(y0 - 1000 * (a))); cv::line(linesImage, pt1, pt2, cv::Scalar(0, 0, 255), 2, cv::LINE_8);
}
cv::imshow("Lines Image", linesImage);
cv::waitKey(0);
这些示例展示了如何使用OpenCV进行圆形和直线的识别。对于圆形识别,使用霍夫圆变换来检测图像中的圆;对于直线识别,使用霍夫直线变换来检测图像中的直线。
除了圆形和直线识别,OpenCV还提供了其他形状识别的方法。以下是一些常见的形状识别方法:
-
多边形识别:
通过多边形逼近方法,可以识别各种多边形形状,如三角形、四边形等。OpenCV提供了cv::approxPolyDP()
用于多边形逼近、cv::minAreaRect()
用于最小外接矩形等。以下是一个示例,演示如何识别并绘制矩形轮廓:
cv::Mat image = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE); // 读取灰度图像
cv::Mat binaryImage;
cv::threshold(image, binaryImage, 128, 255, cv::THRESH_BINARY); // 二值化分割,大于阈值为255,小于阈值为0
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(binaryImage, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
cv::Mat contoursImage = cv::Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); ++i)
{ // 对轮廓进行多边形逼近 std::vector<cv::Point> approx; cv::approxPolyDP(contours[i], approx, cv::arcLength(contours[i], true) * 0.02, true); // 如果逼近结果是一个四边形,则认为是矩形 if (approx.size() == 4) { cv::Scalar color(0, 0, 255); cv::polylines(contoursImage, approx, true, color, 2, cv::LINE_8); }
}
cv::imshow("Contours Image", contoursImage);
cv::waitKey(0);
在示例中,先计算轮廓的多边形逼近,然后通过判断逼近结果的顶点个数来识别是否是矩形。
除了前面提到的基于多边形逼近的方法外,还有一些常用的形状识别算法可以应用于轮廓识别。
-
椭圆识别:
通过椭圆拟合方法,可以识别椭圆形状。使用cv::fitEllipse()
函数对轮廓进行椭圆拟合,然后判断拟合程度以确定形状是否为椭圆。
cv::Mat image = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE); // 读取灰度图像
cv::Mat blurredImage;
cv::GaussianBlur(image, blurredImage, cv::Size(5, 5), 0); // 高斯模糊
cv::Canny(blurredImage, blurredImage, 50, 150); // 边缘检测
std::vector<std::vector<cv::Point>> contours;
cv::findContours(blurredImage, contours, cv::RETR_EXTERNAL,
cv::CHAIN_APPROX_SIMPLE); // 查找轮廓
cv::Mat ellipseImage = cv::Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); ++i)
{ cv::RotatedRect ellipse = cv::fitEllipse(contours[i]); // 椭圆拟合 cv::ellipse(ellipseImage, ellipse, cv::Scalar(0, 255, 0), 2);
}
cv::imshow("Ellipses Image", ellipseImage);
cv::waitKey(0);
-
几何矩识别:
使用几何矩方法可以计算轮廓的矩,并利用矩的特征来识别不同的形状,如面积、宽高比、中心距等。
cv::Mat image = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE); // 读取灰度图像
cv::Mat blurredImage;
cv::GaussianBlur(image, blurredImage, cv::Size(5, 5), 0); // 高斯模糊
cv::threshold(blurredImage, blurredImage, 100, 255, cv::THRESH_BINARY); // 二值化
std::vector<std::vector<cv::Point>> contours;
cv::findContours(blurredImage, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // 查找轮廓
cv::Moments moments;
cv::Mat momentsImage = cv::Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); ++i)
{ moments = cv::moments(contours[i]); // 计算几何矩 cv::Point centroid(moments.m10 / moments.m00, moments.m01 / moments.m00); // 形心坐标 cv::circle(momentsImage, centroid, 4, cv::Scalar(0, 255, 0), -1); double area = moments.m00; // 面积 double aspect_ratio = moments.m20 / moments.m02; // 宽高比 // 可根据需要判断其他矩的特征
}
cv::imshow("Moments Image", momentsImage);
cv::waitKey(0);
-
形状匹配:
通过形状匹配方法,可以将待识别的形状与已知形状进行比较,来确定形状的类别。常见的形状匹配方法包括轮廓匹配和模板匹配。
这些方法可以根据实际需求和具体应用选用。需要根据图像特征和形状的具体定义来选择适合的方法。可以结合多个特征和算法,进行更准确的形状识别。根据不同形状的特征,使用适当的函数和算法进行识别,并可针对需要的特征进行进一步的处理和分析。
相关文章:
OpenCV入门11:轮廓提取和形状识别
轮廓分析主要用于轮廓提取和形状识别等任务。在OpenCV中,轮廓提取和形状识别是图像处理和计算机视觉中常见的任务。下面是关于这两个知识点的一些基本内容: 轮廓提取: 轮廓提取是指从图像中提取出物体轮廓的过程。在OpenCV中,可…...

竞赛选题 深度学习疲劳检测 驾驶行为检测 - python opencv cnn
文章目录 0 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习加…...

Java编程--定时器/线程池/工厂模式/ ThreadPoolExecutor
前言 逆水行舟,不进则退!!! 目录 什么是定时器 实现一个定时器 自己实现一个定时器 什么是线程池 线程池的使用: 什么是工厂模式? 自己实现一个线程池: ThreadPoolExecutor 类…...

【python】Django——django简介、django安装、创建项目、快速上手
笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ Django基础——django安装、创建django项目、django快速上手 django简介django安装1. conda创建环境pydjango2. pip安装django3. django目录 创建项目1. 打开终端(cmd)2. 进入某个目录3.创建项目命令4.django项目…...

未来之选:为什么向量数据库是您的数据管理利器
文章目录 前言什么是向量数据库?向量数据库的机制向量数据库的优点查询向量数据库 什么是向量Embedding?Amazon OpenSearch Service总结 前言 向量数据库擅长处理复杂的高维数据,正在彻底改变商业世界的数据检索和分析。它们执行相似性搜索…...

隧道施工工艺流程vr线上虚拟展示成为产品3D说明书
行业内都知道,汽车生产的大部分都需要冲压加工来完成,因此汽车冲压工艺是汽车制造过程中的重要环节,传统的展示方式往往局限于二维图纸和实地操作,难以充分展现工艺的细节和流程。然而,随着技术的进步,汽车…...
Nacos(含安装)
Nacos是一个开源的动态服务发现、配置和管理平台。它提供了服务发现、服务健康检查、动态配置管理、服务元数据管理等功能,支持多种服务发现和注册方式。Nacos可以帮助开发者快速构建一个具有弹性和高可用性的微服务应用程序。Nacos的全称是Named after Configurati…...

本地跑项目解决跨域问题
跨域问题: 指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对 javascript 施加的安全限制。 同源策略: 是指协议(protocol)、域名(host)、端口号&…...
聊聊logback的isDebugEnabled
序 本文主要研究一下logback的isDebugEnabled isDebugEnabled public final class Loggerimplements org.slf4j.Logger, LocationAwareLogger, LoggingEventAware, AppenderAttachable<ILoggingEvent>, Serializable {//......public boolean isDebugEnabled() {retur…...

ChatGPT+Roblox,元宇宙的AI叙事逻辑#Leveling Up
MixCopilot 嗨,亲爱的听众朋友们!欢迎收听我们的播客节目!我是你们的主播:MixCopilot 混合副驾。今天我们要为大家带来的是我们的AI革命系列节目之一。这个系列节目聚焦于AI领域的一些最有影响力的建设者,他们将会讨论…...

Spark算子
一、编写spark程序的准备工作(程序入口 SparkContext) 1.创建SparkConf val conf new SparkConf().setMaster("local[2]").setAppName("hello-app") 2.创建sparkContext val sc: SparkContext new SparkContext(conf) 二、基…...

Containerd接入Harbor仓库
在使用容器时,避免不了会使用到私有仓库,一般都是采用 harbor 作为私有仓库,docker 对接 harbor 仓库非常简单,哪 containerd 如何对接 harbor 呢? 在内网使用 harbor 根据个人习惯,一般都是非 http 并且是…...
Angular 组件介绍及使用(一)
Angular 概述 Angular 是一个用于构建 Web 应用程序的开源前端框架,由 Google 团队开发和维护。它采用 TypeScript 编程语言,并借鉴了一些传统的 Web 开发模式和最佳实践,提供了强大而灵活的工具和特性。 以下是 Angular 的一些概述要点&am…...

2023.11.13 hive数据仓库之分区表与分桶表操作,与复杂类型的运用
目录 0.hadoop hive的文档 1.一级分区表 2.一级分区表练习2 3.创建多级分区表 4.分区表操作 5.分桶表 6. 分桶表进行排序 7.分桶的原理 8.hive的复杂类型 9.array类型: 又叫数组类型,存储同类型的单数据的集合 10.struct类型: 又叫结构类型,可以存储不同类型单数据的集合…...

Spring Cloud学习(七)【Docker 容器】
文章目录 初识 DockerDocker 介绍Docker与虚拟机Docker架构安装 Docker Docker 基本操作镜像相关命令容器相关命令数据卷 Dockerfile 自定义镜像镜像结构Dockerfile DockerComposeDockerCompose介绍安装DockerCompose Docker镜像仓库常见镜像仓库服务私有镜像仓库 初识 Docker …...

好题分享(2023.11.5——2023.11.11)
目录 前情回顾: 前言: 题目一:补充《移除链表元素》 题目二:《反转链表》 解法一:三指针法 解法二:头插法 题目三: 《相交链表》 题目四:《合并两个有序数列》 题目五&…...

第二章 03Java基础-IDEA相关叙述
文章目录 前言一、IDEA概述二、IDEA下载和安装三、IDEA项目结构介绍四、IDEA的项目和模块操作总结前言 今天我们学习Java基础,IDEA下载以及相关配置和基础使用方法 一、IDEA概述 1.IDEA全称IntelliJ IDEA,是用于Java语言开发的集成工具,是业界公认的目前用于Java程序开发最…...

第三阶段第二章——Python高阶技巧
时间过得很快,这么快就来到了最后一篇Python基础的学习了。话不多说直接进入这最后的学习环节吧!!! 期待有一天 春风得意马蹄疾,一日看尽长安花 o(* ̄︶ ̄*)o 1.闭包 什么是闭包? 答…...

【Git】Git分支与应用分支Git标签与应用标签
一,Git分支 1.1 理解Git分支 在 Git 中,分支是指一个独立的代码线,并且可以在这个分支上添加、修改和删除文件,同时作为另一个独立的代码线存在。一个仓库可以有多个分支,不同的分支可以独立开发不同的功能࿰…...

本地PHP搭建简单Imagewheel私人云图床,在外远程访问——“cpolar内网穿透”
文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道(云端设置)3.3.Cpolar稳定隧道(本地设置) 4.公网访问测…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...