使用opencv实现图像中几何图形检测
1 几何图形检测介绍
1.1 轮廓(contours)
什么是轮廓,简单说轮廓就是一些列点相连组成形状、它们拥有同样的颜色、轮廓发现在图像的对象分析、对象检测等方面是非常有用的工具,在OpenCV
中使用轮廓发现相关函数时候要求输入图像是二值图像,这样便于轮廓提取、边缘提取等操作。轮廓发现的函数与参数解释如下:
函数原型:
findContours(image, mode, method, contours=None, hierarchy=None, offset=None)
参数:
image输入/输出的二值图像mode 迒回轮廓的结构、可以是List、Tree、Externalmethod 轮廓点的编码方式,基本是基于链式编码contours 迒回的轮廓集合hieracrchy 迒回的轮廓层次关系offset 点是否有位移


1.2 多边形逼近
多边形逼近,是通过对轮廓外形无限逼近,删除非关键点、得到轮廓的关键点,不断逼近轮廓真实形状的方法,OpenCV中多边形逼近的函数与参数解释如下:
函数原型:
approxPolyDP(curve, epsilon, closed, approxCurve=None)
参数:
curve 表示输入的轮廓点集合epsilon 表示逼近曲率,越小表示相似逼近越厉害close 是否闭合
1.3 几何距计算
图像几何距是图像的几何特征,高阶几何距中心化之后具有特征不变性,可以产生Hu距输出,用于形状匹配等操作,这里我们通过计算一阶几何距得到指定轮廓的中心位置,计算几何距的函数与参数解释如下:
函数原型:
moments(array, binaryImage=None)
参数:
array表示指定输入轮廓binaryImage默认为None
2 基于opencv实现几何图形检测
整个代码实现分为如下几步完成
- 加载图像,
- 图像二值化
- 轮廓发现
- 几何形状识别
- 测量周长、面积、计算中心
- 颜色提取
2.1 加载图像并进行二值化处理
的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。这是研究灰度变换的最特殊的方法,称为图像的二值化(Binarization)。
函数原型:
def threshold(src: Any,thresh: Any,maxval: Any,type: Any,dst: Any = None) -> None
src:源图像,可以为8位的灰度图,也可以为32位的彩色图像。(两者由区别)
dst:输出图像
thresh:阈值
maxval:dst图像中最大值
type:阈值类型,可以具体类型如下:
enum ThresholdTypes {THRESH_BINARY = 0, //黑白
THRESH_BINARY_INV = 1, //黑白反转
THRESH_TRUNC = 2, //得到图像多像素值
THRESH_TOZERO = 3, //当前点值大于阈值时,不改
变,否则设置为0
THRESH_TOZERO_INV = 4, //当前点值大于阈值时,
设置为0,否则不改变
THRESH_MASK = 7,
THRESH_OTSU = 8, //自适应阈值
THRESH_TRIANGLE = 16
};
具体实现代码:
frame = cv.imread("./data/jihe2.png")# 二值化图像
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
cv.imshow("input image", frame)
2.2 轮廓检测与逼近
当需要对图像进行形状分析时,需要使用多边形逼近一个轮廓,使得顶点数目变少,算法原理比较简单,核心就是不断找多边形最远的点加入形成新的多边形,直到最短距离小于指定的精度。OpenCV里面用函数approxPolyDP()实现。approxPolyDP()用另一条顶点较少的曲线来逼近一条曲线或者一个多边形,这样两条曲线之间的距离小于或等于指定的精度。同时也有使闭合逼近曲线的选项(那就是说,起始点和终止点相同)。
findContours后的轮廓信息contours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似,approxPolyDP 主要功能是把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合。
具体实现代码:
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for cnt in range(len(contours)):# 提取与绘制轮廓cv.drawContours(result, contours, cnt, (0, 255, 0), 2)# 轮廓逼近epsilon = 0.01 * cv.arcLength(contours[cnt], True)approx = cv.approxPolyDP(contours[cnt], epsilon, True)
2.3 几何形状判断
根据corners数量对形状进行判断。
approx = cv.approxPolyDP(contours[cnt], epsilon, True)# 分析几何形状
corners = len(approx)
shape_type = ""if corners < 3:continueif corners == 3:count = self.shapes['triangle']count = count + 1self.shapes['triangle'] = countshape_type = "三角形"
if corners == 4:count = self.shapes['rectangle']count = count + 1self.shapes['rectangle'] = countshape_type = "矩形"
if corners >= 10:count = self.shapes['circles']count = count + 1self.shapes['circles'] = countshape_type = "圆形"
if 4 < corners < 10:count = self.shapes['polygons']count = count + 1self.shapes['polygons'] = countshape_type = "多边形"
2.4 面积周长计算
# 计算面积与周长
p = cv.arcLength(contours[cnt], True)
area = cv.contourArea(contours[cnt])
print("周长: %.3f, 面积: %.3f 颜色: %s 形状: %s " % (p, area, color_str,
2.5 完整代码:
import cv2 as cv
import numpy as npclass ShapeAnalysis:def __init__(self):self.shapes = {'triangle': 0, 'rectangle': 0, 'polygons': 0, 'circles': 0}def analysis(self, frame):h, w, ch = frame.shaperesult = np.zeros((h, w, ch), dtype=np.uint8)# 二值化图像print("start to detect lines...\n")gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)cv.imshow("input image", frame)contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)for cnt in range(len(contours)):# 提取与绘制轮廓cv.drawContours(result, contours, cnt, (0, 255, 0), 2)# 轮廓逼近epsilon = 0.01 * cv.arcLength(contours[cnt], True)approx = cv.approxPolyDP(contours[cnt], epsilon, True)# 分析几何形状corners = len(approx)shape_type = ""if corners < 3:continueif corners == 3:count = self.shapes['triangle']count = count + 1self.shapes['triangle'] = countshape_type = "三角形"if corners == 4:count = self.shapes['rectangle']count = count + 1self.shapes['rectangle'] = countshape_type = "矩形"if corners >= 10:count = self.shapes['circles']count = count + 1self.shapes['circles'] = countshape_type = "圆形"if 4 < corners < 10:count = self.shapes['polygons']count = count + 1self.shapes['polygons'] = countshape_type = "多边形"# 求解中心位置mm = cv.moments(contours[cnt])if mm['m00'] == 0:continuecx = int(mm['m10'] / mm['m00'])cy = int(mm['m01'] / mm['m00'])cv.circle(result, (cx, cy), 3, (0, 0, 255), -1)# 颜色分析color = frame[cy][cx]color_str = "(" + str(color[0]) + ", " + str(color[1]) + ", " + str(color[2]) + ")"# 计算面积与周长p = cv.arcLength(contours[cnt], True)area = cv.contourArea(contours[cnt])print("周长: %.3f, 面积: %.3f 颜色: %s 形状: %s " % (p, area, color_str, shape_type))cv.imshow("Analysis Result", result)print("triangle: ", self.shapes['triangle'])print("rectangle: ", self.shapes['rectangle'])print("polygons: ", self.shapes['polygons'])print("circles: ", self.shapes['circles'])return self.shapesif __name__ == "__main__":src = cv.imread("./data/jihe2.png")ld = ShapeAnalysis()ld.analysis(src)cv.waitKey(0)cv.destroyAllWindows()
原始图像:

运行结果显示:

周长: 553.973, 面积: 11687.500 颜色: (190, 146, 112) 形状: 矩形
周长: 479.556, 面积: 14743.500 颜色: (232, 162, 0) 形状: 矩形
周长: 543.144, 面积: 18333.500 颜色: (21, 0, 136) 形状: 多边形
周长: 341.421, 面积: 7593.000 颜色: (164, 73, 163) 形状: 多边形
周长: 761.796, 面积: 13221.500 颜色: (87, 122, 185) 形状: 圆形
周长: 594.257, 面积: 24703.500 颜色: (39, 127, 255) 形状: 圆形
周长: 592.000, 面积: 14508.000 颜色: (36, 28, 237) 形状: 矩形
周长: 432.291, 面积: 11939.500 颜色: (204, 72, 63) 形状: 多边形
周长: 280.451, 面积: 4917.000 颜色: (190, 146, 112) 形状: 多边形
周长: 531.588, 面积: 10587.000 颜色: (164, 73, 163) 形状: 矩形
周长: 405.262, 面积: 4172.500 颜色: (76, 177, 34) 形状: 圆形
周长: 370.191, 面积: 9746.000 颜色: (232, 162, 0) 形状: 圆形
周长: 486.000, 面积: 14762.000 颜色: (232, 162, 0) 形状: 矩形
triangle: 0
rectangle: 5
polygons: 4
circles: 4
相关文章:
使用opencv实现图像中几何图形检测
1 几何图形检测介绍 1.1 轮廓(contours) 什么是轮廓,简单说轮廓就是一些列点相连组成形状、它们拥有同样的颜色、轮廓发现在图像的对象分析、对象检测等方面是非常有用的工具,在OpenCV 中使用轮廓发现相关函数时候要求输入图像是二值图像,这…...
补题与周总结:leetcode第 376 场周赛
文章目录 复盘与一周总结2967. 使数组成为等数数组的最小代价(中位数贪心 回文数判断)2968. 执行操作使频率分数最大(中位数贪心 前缀和 滑窗) 复盘与一周总结 wa穿了第3题,赛时其实想到了思路:中位数贪心…...
js指纹库,可跟踪用户唯一性
fingerprintjs官网 资料: Browserleaks - Check your browser for privacy leaks...
Shell三剑客:awk(内部变量)
一、$0 :完整的输入记录 [rootlocalhost ~]# awk -F: {print $0} passwd.txt root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/s…...
JVM中的虚拟机栈的动态链接部分存放到底是什么
在Java虚拟机(JVM)中,每个线程在执行一个方法时都会创建一个栈帧(Stack Frame),栈帧中包含了方法的运行时数据。栈帧通常包括局部变量表、操作数栈、动态链接、方法返回地址等部分。 动态链接 动态链接&a…...
Leetcode 55 跳跃游戏
题意理解: 非负整数数组 nums, 最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 需要跳到nums最后一个元素即为成功。 目标:是否能够跳到最后一个元素。 解题思路: 使用贪心算法来解题,需要理解…...
构建陪诊预约系统:技术实战指南
在医疗科技的飞速发展中,陪诊预约系统的应用为患者和陪诊人员提供了更为便捷和贴心的服务。本文将带领您通过技术实现,构建一个简单而实用的陪诊预约系统,以提升医疗服务的效率和用户体验。 技术栈选择 在开始之前,我们需要选择…...
windows和linux将文件删除至回收站【C++】【Go】语言实现
目录 C Windows平台 Linux平台 开平台,代码合并 Go 实现步骤 Go语言实现示例 go单独的windows版本实现 代码解释 C 在C中,将文件移动到回收站的实现在Linux和Windows平台上是不同的。首先,我会为你提供在Windows平台上实现的代码示例…...
10 Vue3中v-html指令的用法
概述 v-html主要是用来渲染富文本内容,比如评论信息,新闻信息,文章信息等。 v-html是一个特别不安全的指令,因为它会将文本以HTML的显示进行渲染,一旦文本里面包含一些恶意的js代码,可能会导致整个网页发…...
华为数通方向HCIP-DataCom H12-831题库(多选题:181-200)
第181题 如图所示,R1、R2、R3、R4都部署为SPF区域0,链路的cost值如图中标识。R1、R2R3、R4的Loopback0通告入OSPF。R1、R2、R3与R4使用Loopback0作为连接接口,建立BGP对等体关系,其中R4为RR设备,R1、R2、R3是R4的客户端。当R4的直连地址172.20,1,4/32通告入BGP后,以下关R…...
DC-磁盘管理
2023年全国网络系统管理赛项真题 模块B-Windows解析 题目 在DC2上安装及配置软RAID 5。在安装好的DC2虚拟机中添加三块10G虚拟磁盘。组成RAID 5,磁盘分区命名为卷标H盘:Raid5。手动测试破坏一块磁盘,做RAID磁盘修复,确认RAID 5配置完毕。配置步骤 关闭虚拟机,添加3块10G磁…...
使用Docker运行镜像文件与设置端口
1,创建镜像文件前准备 # 使用基础镜像FROM alpine:latest# 设置工作目录WORKDIR /app# 复制应用程序文件到镜像中COPY . .# 暴露容器的端口 不会自动将容器的端口映射到宿主机上 docker run -d -p <宿主机端口>:7080 <镜像名称>EXPOSE 7080# 定义容器启…...
Centos 8.5 Oracle12c安装
由于多次安装踩坑,所以本次写了一份12c安装的完整版。可以直接使用。 一、安装数据库基本信息 名称 值 主机名 database 操作系统 CentOS Linux release 8.5.2111 Oracle用户名/密码 oracle Oracle 版本 12c Enterprise Edition Release 12.2.0.1.0 oracle…...
Apache Tomcat httpoxy 安全漏洞 CVE-2016-5388 已亲自复现
Apache Tomcat httpoxy 安全漏洞 CVE-2016-5388 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 漏洞名称 漏洞描述 在Apache Tomcat中发现了一个被归类为关键的漏洞,该漏洞在8.5.4(Application Server Soft ware)以下。受影响的是组…...
ChatGLM3-6B 的调用参数说明,chat 与stream_chat 接口函数的参数说明
ChatGLM3-6B 是一个语言大模型,最近在评估这个模型,但发现它的文档有限,只能从demo代码中猜测调用的参数的含义,准确度是有限的;于是,通过查看源代码来研究,目前整理笔记如下: Chat…...
Vuex的学习-2
Vuex的核心概念 StateMutationAction 1.State State提供唯一的公共数据源,所有共享的数据都统一放在Store的State中进行存储。 const store new Vuex.Store({state : { count: 0 } }) 这是渲染的页面 组件访问数据的第一种方式 组件访问数据的第二种方式 // 1…...
智慧安防视频监控EasyCVR如何通过回调接口向第三方平台推送RTSP视频通道离线通知
安防视频监控系统EasyCVR能在局域网、公网、专网等复杂的网络环境中部署,可支持4G、5G、WiFi、有线等方式进行视频的接入与传输、处理和分发。平台能将接入的视频流进行汇聚、转码、多格式输出和分发,具体包括:RTMP、RTSP、HTTP-FLV、WebSock…...
Scrum项目管理流程及免费敏捷工具
项目启动: 团队明确项目愿景、目标和范围,确定项目范围和优先级,并建立团队以及开展初步计划。 制定产品待办事项清单(Product Backlog): 定义项目所需功能、任务和需求列表,并按优先级排序…...
大型医院PACS系统源码,影像存储与传输系统源码,支持多种图像处理及三维重建功能
PACS系统是医院影像科室中应用的一种系统,主要用于获取、传输、存档和处理医学影像。它通过各种接口,如模拟、DICOM和网络,以数字化的方式将各种医学影像,如核磁共振、CT扫描、超声波等保存起来,并在需要时能够快速调取…...
HDFS NFS Gateway(环境配置,超级详细!!)
HDFS NFS Gateway简介: HDFS NFS Gateway是Hadoop Distributed File System(HDFS)中的一个组件,它允许客户端通过NFS(Network File System,网络文件系统)与HDFS进行交互。具体来说,HDFS NFS…...
如何快速掌握阴阳师自动化脚本:OAS解放双手的完整教程
如何快速掌握阴阳师自动化脚本:OAS解放双手的完整教程 【免费下载链接】OnmyojiAutoScript Onmyoji Auto Script | 阴阳师脚本 项目地址: https://gitcode.com/gh_mirrors/on/OnmyojiAutoScript 阴阳师自动化脚本(Onmyoji Auto Script,…...
告别时间混乱:一份超全的Hive日期函数使用手册与常见错误排查
告别时间混乱:一份超全的Hive日期函数使用手册与常见错误排查 在数据开发领域,时间数据处理一直是高频且易错的环节。无论是日志分析、用户行为追踪还是财务报表生成,准确的时间计算都是确保数据质量的基础。Hive作为大数据生态中广泛使用的数…...
从零构建大语言模型:Transformer架构、训练技巧与实战指南
1. 项目概述:从零构建你自己的大语言模型最近几年,大语言模型(LLM)的热度居高不下,从ChatGPT到Claude,再到国内外的各种开源模型,它们展现出的理解和生成能力让人惊叹。但你是否也和我一样&…...
探索下一代命令行界面:OpenCLI 架构设计与插件化实践
1. 项目概述:一个面向未来的命令行界面原型最近在开源社区里,我注意到一个名为sys-fairy-eve/nightly-mvp-2026-03-19-opencli的项目。这个标题信息量不小,它不像一个成熟的产品,更像是一个开发过程中的里程碑快照。sys-fairy-eve…...
Pandrator:基于Python的自动化内容生成与数据转换工具实践
1. 项目概述与核心价值最近在折腾一些自动化数据处理和内容生成的工作流,发现了一个挺有意思的开源项目,叫Pandrator。乍一看这个名字,可能会联想到“潘多拉”和“生成器”的结合,实际上它也确实是一个功能强大的内容转换与生成工…...
基于树莓派与QT Py的本地化物联网红外遥控器DIY指南
1. 项目概述与核心价值想没想过,把家里那堆遥控器——电视的、机顶盒的、空调的、音响的——统统集成到一个你手机能打开的网页里?而且这个控制中心完全在你家局域网里运行,不依赖任何云服务,不用担心厂商倒闭后设备变砖。今天分享…...
认识Python数据包套接字
如你所知,数据包格式套接字(Datagram Sockets)也叫“无连接的套接字”,在代码中使用 SOCK_DGRAM 表示。可以将 SOCK_DGRAM 比喻成高速移动的摩托车快递,它有以下特征:强调快速传输而非传输顺序;…...
多语种出海必备,ElevenLabs菲律宾文语音质量实测对比:Wavenet vs. Instant Voice vs. Custom Model(附MOS评分表)
更多请点击: https://intelliparadigm.com 第一章:多语种出海语音技术演进与菲律宾语本地化挑战 随着全球数字服务加速出海,语音交互系统正从单语种向多语种、低资源语言深度拓展。菲律宾语(Filipino/Tagalog)作为东…...
有向无环图(DAG)在Multi-Agent系统中的应用(图编排、动态DAG、Dynamic DAG)动态Agent Graph
文章目录有向无环图(DAG)在 Multi-Agent 系统中的应用一、什么是 DAG(有向无环图)二、为什么 Multi-Agent 需要 DAG三、Multi-Agent 的本质:任务图四、DAG 在 Multi-Agent 中的核心作用五、一个典型 Multi-Agent DAG六…...
【仅剩47份】Midjourney湿版摄影风格训练数据包(含1851–1889年原始湿版扫描图谱×236张+ICC色彩配置文件×5):精准匹配V6.6新渲染引擎底层纹理采样逻辑
更多请点击: https://intelliparadigm.com 第一章:湿版摄影风格的历史溯源与数字再生价值 湿版摄影(Wet Plate Collodion Process)诞生于1851年,由英国科学家弗雷德里克斯科特阿彻(Frederick Scott Archer…...
