基于python OpenCV多边形图像识别的实现
首先说一下我的整体思路:
① 首先定义了一个识别器类型,封装了计算边长,识别形状和展示结果三个函数。
② 主函数先读入图片,然后将图片转化为灰度图片,然后高斯滤波平滑处理,然后将灰度图片转化为黑白两色图片。
③ 调用函数识别图片中所有的轮廓,然后列表形式返回图片,轮廓等信息,然后只取轮廓的所有点信息(每个点的信息为平面坐标)作为一个列表程序(第91,92,93行代码)
④ 用之前创建的识别器实例对每个轮廓中的点进行多边形拟合,得到顶点的坐标的列表中去(class中28~32行代码)
⑤ 输出识别结果
以下是代码部分:(注意,这里是opencv3的代码,请先检查自己的opencv版本)
import cv2
import mathTHRESHOLE_VALUE=60
COEFFICIENT=0.02class ShapeDetector:#初始化类def __init__(self):#字典类型对应每一种图形的计数器self.counter = {"unrecognized image": 0, "triangle": 0, "rhombus": 0, "rectangle": 0, "pentagon": 0,"hexagon": 0, "circle": 0}#初始化图形类型为不可识别self.shape = "unrecognized image"#图形顶点集置空self.approx = []#初始化该图形的周长为0self.peri = 0# 计算欧式距离(主要作用通过计算边长区分菱形和长方形)def distance(self, x1, y1, x2, y2):return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)def detect(self, c):#cv2.arcLength函数返回周长self.peri = cv2.arcLength(c, True)#cv2.approxPolyDP用多边形取拟合,返回的是顶点的列表self.approx = cv2.approxPolyDP(c, COEFFICIENT * self.peri, True)#3个顶点,三角形if len(self.approx) == 3:self.shape = "triangle"#同理,四个顶点,四边形elif len(self.approx) == 4:#计算相邻两边的长度,做差判在误差范围内是否相等dist1 = self.distance(self.approx[0][0][0], self.approx[0][0][1], self.approx[1][0][0],self.approx[1][0][1])dist2 = self.distance(self.approx[0][0][0], self.approx[0][0][1], self.approx[3][0][0],self.approx[3][0][1])result = math.fabs(dist1 - dist2)# print(result)#误差小于10,可近似认为相等,为菱形if result <= 10:self.shape = "rhombus"else:self.shape = "rectangle"#五边形elif len(self.approx) == 5:self.shape = "pentagon"#六边形elif len(self.approx) == 6:self.shape = "hexagon"#圆else:self.shape = "circle"#相应形状计数器加一self.counter[self.shape] += 1#返回形状return self.shapedef Display(self):#展现结果for kind in self.counter.keys():print("The number of {} is {}".format(kind, self.counter[kind]))def main():#读入图片testID = "test.png"image = cv2.imread(testID)#将图片转换为灰度图片gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 高斯滤波,图像平滑处理blurred = cv2.GaussianBlur(gray, (5, 5), 0)#根据阈值,将灰度图片转化为黑白两色图片thresh = cv2.threshold(blurred, THRESHOLE_VALUE, 255, cv2.THRESH_BINARY_INV)[1]#返回图片和图中轮廓信息,列表形式返回到cnts中cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)#只需要取轮廓上点的信息cnts = cnts[1]#创建一个识别器实例sd = ShapeDetector()#分别对每个轮廓进行处理for c in cnts:#得到形状shape = sd.detect(c)#print(shape)#输出结果sd.Display()if __name__=="__main__":main()
以下为本程序用到的函数表:
(第9行)init(self) (类初始化函数)
(第23行)distance(self, x1, y1, x2, y2): (计算(x1,y1),(x2,y2)两点之间的距离,点为像素坐标)
(第24行)math.sqrt() (数学开平方运算)
(第26行)detect(self, c): (判断轮廓的形状)
(第28行)cv2.arcLength()(计算周长函数。一参数c是轮廓的点集;二参数true代表闭合,false代表开放。)
链接:https://blog.csdn.net/u011854789/article/details/79836242
(第31行) cv2.approxPolyDP()(多边形拟合函数。
一参数c是轮廓的点集;
二参数代表图形边长允许的偏差范围,因为图片中的图形边长上是凹凸不平的,但是电脑是根据标准的直线来进行边的拟合,所以难免每个点处都有和标准直线偏差的距离,此参数便是设置最大偏差距离不能超过多少,不然就会用一个新的边拟合,此处设置的是边长的百分之二;
三参数为true指示拟合的多边闭合,false为开放。 返回值为拟合出来的所有图形顶点坐标,用列表表示)
链接:https://blog.csdn.net/brooknew/article/details/103512228
(有好几行) len()(计算可迭代对象的长度)
(第71行)Display(self)(输出结果)
(第74行) print()(通过标准输出流将缓冲区信息输出到控制台(str.format的用法自己查))
(第79行) cv2.imread()(读入图片,
一参数图片路径;
二参数加载形式,可缺省)
链接:https://blog.csdn.net/lccrun/article/details/95594268
(第83行) cv2.cvtColor(转换颜色空间函数,
一参数为原图片;
二参数为转换的方法,常见的转化方法见链接)
链接:https://blog.csdn.net/m0_37192554/article/details/81946430
(第85行) cv2.GaussianBlur()(高斯滤波函数,图像平滑处理。
一参数是源图片;
二参数是高斯矩阵的大小;
三参数表示标准差。此函数用用就行不用搞懂具体干啥,如果感兴趣可以看下面的链接)
链接:https://blog.csdn.net/weixin_44657197/article/details/102679434
(第87行) cv2.threshold()(图像阈值处理函数,
一参数为源图片;
二参数为阈值;
三参数为设置颜色的最大RGB值;
四参数为划分的方法。
此函数的目的是为了将图片转化为黑白二色图,根据常识,颜色深的是黑色,颜色浅的是白色对吧,那么如何定义颜色的深浅呢?先补充一下:
***RGB:***计算机中常用的表示颜色的方法。计算机上每一个像素点都是三个颜色不同比例得到的,由一个元组来表示(R,G,B),分别代表红色,绿色和蓝色。
主流的划分是每个位置划分为256个段位,用0~255的整数表示,比如(255,255,255)就是最白的白色,(0,0,0)就是最黑的黑色,(255,0,0)就是最亮的红色。 ***灰度:***前面的cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)就是将RGB彩色图片转换为灰度图片。具体的转换公式不用管,但是灰度为50的图片RGB值为(50,50,50)这个知道就行了。
第二参数阈值:对图片的每个像素点,根据RGB值计算其灰度,如果灰度大于这个阈值,那么就变成黑色(或者白色),小于等于就变成白色(或者黑色)。
第三参数最大RGB值:就是把灰度变成255,说白了就是白色 第四参数划分方法:见下图
dst(x,y)是(x,y)处像素之后的灰度,src(x,y)是源图片在(x,y)坐标像素的灰度)
链接:https://blog.csdn.net/a19990412/article/details/81172426
(第90行) cv2.findContours()(寻找图片中的所有轮廓,
一参数为带轮廓的图片;
二参数为找到的轮廓的输出形式;
三参数为指定轮廓的近似方法,返回值的话只需要取列表中的第二个,即可获得所有轮廓的所有点坐标。详细见链接)
链接:https://blog.csdn.net/u014120499/article/details/99675967
备注:
1、在使用cv2.threshold()函数时,第四个参数划分方法,当背景为白色时要用cv2.THRESH_BINARY_INV但是背景为黑色是要去掉_INV,用cv2.THRESH_BINARY。其他背景颜色自己想一想吧。。。。。。
2、要是统计的个数出现了问题的话,这是精度的问题,比如我当前设置下,圆的边数是8,改变精度只需要调整全局变量COEFFICIENT的大小就行
祝学习愉快~
评价(涂红):* * * * *
基于python OpenCV多边形图像识别的实现相关推荐
- 基于python+OpenCV的车牌号码识别
基于python+OpenCV的车牌号码识别 车牌识别行业已具备一定的市场规模,在电子警察.公路卡口.停车场.商业管理.汽修服务等领域已取得了部分应用.一个典型的车辆牌照识别系统一般包括以下4个部分: ...
- 基于python opencv人脸识别的签到系统
基于python opencv人脸识别的签到系统 前言 先看下效果 实现的功能 开始准备 页面的构建 功能实现 代码部分 总结 前言 一个基于opencv人脸识别和TensorFlow进行模型训练的人 ...
- 基于Python+OpenCV车道线检测(直道和弯道)
基于Python+OpenCV车道线检测(直道和弯道) 基于Python+OpenCV车道线检测(直道和弯道)
- 基于python 使用sikuli图像识别
基于python使用sikuli图像识别 import time from jpype import * 参考如下代码段: if __name__ == '__main__':startJVM(r'C ...
- 【开源分享】基于Python+OpenCV+PyQt5车牌识别(GUI界面)
亲测无错:基于Python+OpenCV+PyQt5车牌识别(GUI界面)绝对可以用的!!!!! 基于Python+OpenCV+PyQt5车牌识别(GUI界面) 参考文档
- 基于python+opencv+pyautogui的图像识别点击
第一次发文没啥经验 很多都是借鉴若有侵权请告知 必更改 开源代码只供学习交流请勿用作其他用途!!! get_img()#这个函数是获取rgb格式屏幕截图,可用于截图一次识别多个元素 imgclick( ...
- 基于python+opencv的图像目标区域自动提取
向AI转型的程序员都关注了这个号???????????? 机器学习AI算法工程 公众号:datayx 一.提取纸张中的内容 一张照片中的感兴趣区域总是沿着x,y,z三个轴都有一定倾斜(如下图),要 ...
- 基于python+openCV的中值滤波
先直接来一个3×3的吧 def median(src_img, filter_size, channels):# 首先,定义一个大小为9的0数组# list = [[0, 0, 0, 0, 0, 0, ...
- python drawline_基于python,OPenCv中基本的绘图函数
(一)OpenCv中,python接口的基本的绘图函数 1-用于绘制直线的--------cv2.line()函数 2-用于绘制椭圆的--------cv2.ellipse()函数 3-用于绘制矩形的 ...
最新文章
- linq.designer.cs学习笔记
- 在水晶报表中实现任意选择指定字段显示-模板及C#升级版
- Docker导入、导出、删除容器
- 信息学奥赛一本通C++语言——1002:输出第二个整数
- jquery mysql表格_使用jQuery设计数据表格:设计表格基类
- Hadoop集群搭建过程中ssh免密码登录(二)
- 【word】为什么word分两栏的最后一页左边一栏没写完跑到右边去了
- 数据库服务器系统崩溃,mssql数据库系统崩溃后的一般处理步骤与方法
- PotPlayer+SVP4视频补帧简易教程
- 曝光三要素:光圈、快门、ISO
- 如何给 ReactJS 应用增加配置文件?
- Java实现碧蓝航线连续作战
- PS进阶篇——如何PS软件给房间地板换颜色(五)
- 计算机网络部分知识梳理
- python雪花_用 Python 实现雪花效果
- 简单易懂且有趣的pycharm运行小游戏
- 在Windows Embedded Standard中阻止安装提示和OOBE
- 关于w5500客户端和服务器的调试心得
- 施努卡:机器视觉产业前景(机器视觉技术的发展及应用)
- Origin如何绘制三维图形?