VC++中使用OpenCV进行形状和轮廓检测

VC++中使用OpenCV进行形状和轮廓检测

在VC++中使用OpenCV进行形状和轮廓检测,轮廓是形状分析以及物体检测和识别的有用工具。如下面的图像中Shapes.png中有三角形、矩形、正方形、圆形等,我们如何去区分不同的形状,并且根据轮廓进行检测呢?
Shapes..png
原图下载地址为:https://github.com/murtazahassan/Learn-OpenCV-cpp-in-4-Hours/blob/main/Resources/shapes.png
1、首先我们对原始图像进行预处理,将原始图形灰度化、高斯模糊、Canny边缘检测、膨胀化处理,最后得到一副膨胀的图形
2、基于这幅膨胀的图像,我们调用findContours函数从膨胀化的二值图像中检索出所有的轮廓,结果放到vector<vector<Point>> contours数组中
3、遍历每一个轮廓多边形,首选计算轮廓面积,过滤那些面积特别小的轮廓(比如面积小于1000则不处理,例如上图中的那个黑色的圆点),消除噪声;计算轮廓周长(封闭的或者非封闭的)或曲线长度,以指定精度逼近多边形曲线,计算顶点集合或灰度图像的非零像素的右上边界矩形,获取边界包围盒;然后轮廓多边形的角落(顶点)个数objCor,根据objCor判断轮廓多边形的形状类型,特别注意矩形和正方形的区别,我们根据轮廓的宽高比来区分,当轮廓宽高比大于0.95或者小于1.05时我们可以认定轮廓为正方形
4、最后我们在第三步基础上,绘制轮廓或填充轮廓,颜色为粉色;绘制边界包围盒,颜色为绿色;在边界包围盒左上方往上5像素的位置,绘制其形状的描述文字

C++示例代码

示例代码如下:

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>using namespace cv;
using namespace std;///  Color Detection  //
// 获取轮廓边界、绘制边界包围盒、形状描述
void getContours(Mat imgDil, Mat img) {vector<vector<Point>> contours;vector<Vec4i> hierarchy;// 从膨胀化的二值图像中检索轮廓findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);//drawContours(img, contours, -1, Scalar(255, 0, 255), 2);vector<vector<Point>> conPoly(contours.size());	// 逼近的多边形曲线,接近contours轮廓多边形		vector<Rect> boundRect(contours.size());	// contours轮廓多边形的边界包围盒// 遍历每一个轮廓多边形for (int i = 0; i < contours.size(); i++){int area = contourArea(contours[i]);	// 计算轮廓的面积cout << area << endl;string objectType;if (area > 1000)	// 过滤那些面积特别小的轮廓,消除噪声{float peri = arcLength(contours[i], true);	// 计算轮廓周长(封闭的或者非封闭的)或曲线长度approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);	// 以指定精度逼近多边形曲线cout << conPoly[i].size() << endl;boundRect[i] = boundingRect(conPoly[i]);	// 计算顶点集合或灰度图像的非零像素的右上边界矩形,获取边界包围盒int objCor = (int)conPoly[i].size();	// 轮廓多边形的角落(顶点)个数// 根据objCor判断轮廓多边形的形状类型if (objCor == 3) {objectType = "Tri";	// 三角形} else if (objCor == 4)	{ // 四边形float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;	// 边界包围盒的宽高比:宽度/高度cout << aspRatio << endl;if (aspRatio > 0.95 && aspRatio < 1.05) {	// 边界包围盒宽高比大于0.95,或者小于1.05,则认为是正方形objectType = "Square";	// 正方形} else {objectType = "Rect";	// 矩形}} else if (objCor > 4) {objectType = "Circle";	// 圆形}drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);	// 绘制轮廓或填充轮廓,颜色为粉色rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);	// 绘制边界包围盒,颜色为绿色putText(img, objectType, { boundRect[i].x,boundRect[i].y - 5 }, FONT_HERSHEY_PLAIN, 1, Scalar(0, 69, 255), 2);	// 在边界包围盒左上方往上5像素的位置,绘制其形状的描述文字}}
}int main() {string path = "Resources/shapes.png";Mat img = imread(path);Mat imgGray, imgBlur, imgCanny, imgDil, imgErode;// PreprocessingcvtColor(img, imgGray, COLOR_BGR2GRAY);	// 灰度图GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);	// 高斯模糊处理Canny(imgBlur, imgCanny, 25, 75);	// Canny边缘检测算法Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));dilate(imgCanny, imgDil, kernel);	// 膨胀图// 基于膨胀图,在原图上绘制轮廓边界、绘制边界包围盒以及形状描述getContours(imgDil, img);imshow("Image", img);//imshow("Image Gray", imgGray);//imshow("Image Blur", imgBlur);//imshow("Image Canny", imgCanny);//imshow("Image Dil", imgDil);waitKey(0);return 0;
}

运行结果如下图所示:
运行结果

参考资料

  • LEARN OPENCV C++ in 4 HOURS | Including 3x Projects | Computer Vision
  • Learn-OpenCV-cpp-in-4-Hours
  • LEARN OPENCV in 3 HOURS with Python | Including 3xProjects | Computer Vision
  • Learn-OpenCV-in-3-hours

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/639016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

制作linux运行包

从源码制作 syslinux:https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.tar.gz busybox:https://busybox.net/downloads/busybox-1.26.0.tar.bz2 kernel:https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.5.7.tar.gz 遇到问题&…

初识React,基础(1), 安装react,jsx文件,类组件和函数组件,css样式

第一部分:初识react react: 用于构建用户界面的 JavaScript 库全局安装,win r, 命令: npm install create-react-app -g3. 创建一个react应用, 这里我在vscode 里面创建, 创建之后,运行 create-react-app my-appcd my-app npm start 第二部分: redact 组件定义以及使用 rea…

当 OpenTelemetry 遇上阿里云 Prometheus

作者&#xff1a;逸陵 背景 在云原生可观测蓬勃发展的当下&#xff0c;想必大家对 OpenTelemetry & Prometheus 并不是太陌生。OpenTelemetry 是 CNCF&#xff08;Cloud Native Computing Foundation&#xff09;旗下的开源项目&#xff0c;它的目标是在云原生时代成为应…

【Unity学习笔记】New Input System 部分源码和测试用例补充

转载请注明出处&#xff1a;&#x1f517;https://blog.csdn.net/weixin_44013533/article/details/135630016 作者&#xff1a;CSDN|Ringleader| 主要参考&#xff1a; Unity官方Input System手册与API【Unity学习笔记】Unity TestRunner使用【Unity学习笔记】第十二 New Inp…

MySQL的执行流程

一、MySQL的执行流程 MySQL架构分为Server层、存储引擎&#xff0c;其中Server层又分为连接器、查询缓存、分析器、优化器执行器五个部分。当客户端发送请求后依次需要经过 处理请求、查询缓存、语法解析、查询优化、存储引擎部分。 1. 连接器 负责维持和管理连接&#xff…

【差分数组】【图论】【分类讨论】【整除以2】100213按距离统计房屋对数目

作者推荐 【动态规划】【数学】【C算法】18赛车 本文涉及知识点 差分数组 图论 分类讨论 整除以2 LeetCode100213按距离统计房屋对数目 给你三个 正整数 n 、x 和 y 。 在城市中&#xff0c;存在编号从 1 到 n 的房屋&#xff0c;由 n 条街道相连。对所有 1 < i < n…

Apache-iotdb物联网数据库的安装及使用

一、简介 >Apache IoTDB (Database for Internet of Things) is an IoT native database with high performance for data management and analysis, deployable on the edge and the cloud. Due to its light-weight architecture, high performance and rich feature set…

爬虫工作量由小到大的思维转变---<第三十七章 Scrapy redis里面的key >

前言: 终于找到机会,开始把scrapy-redis细致地给大伙通一通了! 为什么非要细致讲scrapy-redis呢? 1.市面上关于scrapy-redis的教程,都比较笼统; demo级别好写,但是一旦上了项目,就问题百出!2.scrapy-redis里面的思路,其实跟单个爬虫或者集合式爬虫他的思路有点不一样; 正文…

Java代码审计Shiro反序列化CB1链source入口sink执行gadget链

目录 0x00 前言 0x01 CC链&CB链简介 1. Commons Collections链是什么&#xff1f; 2. Commons BeanUtils链是什么&#xff1f; 0x02 测试Commons BeanUtils1链 0x03 Shiro550 - Commons BeanUtils1链 - 跟踪分析&#xff08;无依赖&#xff09; 1. 前置知识 2. Co…

Node开发基础

1. 概述 1.1 为什么要学习服务器端开发基础 能够和后端程序员更加紧密的配合 网站业务逻辑前置&#xff0c;学习前端技术需要后端技术支撑 扩宽知识视野&#xff0c;能够站在更高的角度审视整个项目 1.2 服务器端开发要做的事情 实现网站的业务逻辑 ---网站登录部分&#…

矩阵重叠问题判断

创作背景 看到一道题目有感而发想写一篇题解&#xff0c;涉及的是一种逆向思维 桌面窗体重叠 - 洛谷https://www.luogu.com.cn/problem/U399827题目来源于《信息学奥赛课课通》 大致就是给一个长方形的左上顶点坐标&#xff08;x1,y1&#xff09;和右下顶点坐标&#xff08;x…

【设计模式】适配器和桥接器模式有什么区别?

今天我探讨一下适配器模式和桥接模式&#xff0c;这两种模式往往容易被混淆&#xff0c;我们希望通过比较他们的区别和联系&#xff0c;能够让大家有更清晰的认识。 适配器模式&#xff1a;连接不兼容接口 当你有一个类的接口不兼容你的系统&#xff0c;而你又不希望修改这个…

mini-spring-Bean含参实例化(三)

上一节&#xff0c;bean是在AbstractAutowireCapableBeanFactory.doCreateBean方法中用beanClass.newInstance()来实例化&#xff0c;仅适用于bean有无参构造函数的情况。 本节考虑含参的bean的实例化 考虑两个问题 一、串流程从哪合理的把构造函数的入参信息传递到实例化操作里…

各行业领域向chatgpt高质量提问的方式

一、技术/业务/事项咨询&#xff1a; ChatGPT可以回答关于技术领域以及工作生活等各方面的问题&#xff0c;包括最佳实践、开发工具、编程语言选择等&#xff0c;咨询标准方案等。 常见问法&#xff1a; 我准备做***&#xff0c;【目前的选择有***】&#xff0c;请告诉我选哪…

sql注入基础

一、SQL注入攻击的根源可以归结为两个主要因素: 程序命令和用户数据之间缺乏有效的隔离措施,以及对用户输入数据的信任。 程序命令和用户数据之间缺乏隔离:在一个应用程序中,程序命令(如SQL语句)和用户数据(即用户输入)应该被严格分离,以避免恶意用户利用输入数据来改…

云服务器定价_云服务器价格_云主机计费模式_腾讯云

腾讯云服务器租用价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月&#xff0c;云服务器CVM S5实例2核2G配置280.8元一年…

嵌入式培训机构四个月实训课程笔记(完整版)-C++和QT编程第六天-Qt UDP编程(物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1-u7GvgM0TLuiy9z7LYQ80Q?pwd1688 提取码&#xff1a;1688 在Qt中提供了QUdpSocket 类来进行UDP数据报&#xff08;datagrams&#xff09;的发送和接收。这里我们还要了解一个名词Socket&#xff0c;也就是常说的“套接字”。 Qt 网络…

2024.1.18力扣每日一题——拿出最少数目的魔法豆

2024.1.18 题目来源我的题解方法一 排序前缀和方法二 优化版本 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2171 我的题解 方法一 排序前缀和 结果与原始顺序无关&#xff0c;因此先进行排序&#xff0c;然后计算前缀和。 有官方题解证明&#xff1a;最终在 拿出最少…

ImageMagick使用手册

ImageMagick使用手册 文章目录 ImageMagick使用手册ImageMagick是什么指令总结1.查看版本2.官网验证指令解读3.svg转png4.png转ico5.将指定文件夹中的所有PNG图像转换为ICO图标 本教程持续更新&#xff0c;我学到多少就更新多少。关于ffmpeg如何安装可以看上一篇博客win系统环境…