可以直接跳到最后整体代码看一看是不是很少的代码!!!!
思路:
1. 数据的整合
2. 图片的灰度转化
3. 图片的二值转化
4. 图片的轮廓识别
5. 得到图片的顶点数
6. 依据顶点数判断图像形状
一、原数据的展示
图片文件共36个文件夹,每个文件夹有100张图片,共3600张图片。
每一个文件夹里都有形同此类的图形
二、数据的整合
对于多个文件夹,分析起来很不方便,所有决定将其都放在一个文件夹下进行分析,在python中具体实现如下:
本次需要的包
1
2
3
4
5
|
import cv2
import os
from pil import image
import matplotlib.pyplot as plt
import numpy as np
|
1
2
3
4
5
6
|
a = os.listdir( 'c:\\users\\dell\\desktop\\opencvproofset' ) #循环读取每个子文件夹
for i in range ( len (a)):
b = os.listdir( 'c:\\users\\dell\\desktop\\opencvproofset\\' + a[i]) #读取每个子文件下的图片文件
for j in range ( len (b)):
c = image. open ( 'c:\\users\\dell\\desktop\\opencvproofset\\'+a[i]+' \\' + b[j]) #循环读取每个图片文件
c.save( 'c:\\users\\dell\\desktop\\cleardata\\'+str(i)+' _ '+str(j)+' .png') #以文件夹序号和图片序号为名保存在一个兴建文件夹下
|
结果如下:
三、图片轮廓的确定
3.1图片的灰度处理
以下以一张图片为例子作为说明
对于灰度的处理,选择使用opencv的cv2.cvtcolor函数,代码示例如下:
1
2
3
|
d = os.listdir( 'c:\\users\\dell\\desktop\\cleardata\\' ) #文件路径
e = cv2.imread( 'c:\\users\\dell\\desktop\\cleardata\\' + d[ 5 ]) #以矩阵的形式图片读入
plt.imshow(e) #画出示例图
|
进行灰度的转化:
1
|
g = cv2.cvtcolor(e,cv2.color_bgr2gray) ##灰度转化
|
3.2图片的二值转化
对于图片的二值转化这里选用cv2.threshold函数,代码示例如下:
1
|
r,b = cv2.threshold(g, 0 , 255 ,cv2.thresh_otsu) #二值转化,大于0的像素统一设置为255,小于等于0的统一设置为0
|
上述代码的第一个参数为灰度图形,第二个参数是阈值,即大于0的像素点转化为255,然后选用的thresh_otsu方法,具体说明如下:
通常情况,我们一般不知道设定怎样的阈值thresh才能得到比较好的二值化效果,只能去试。如对于一幅双峰图像(理解为图像直方图中存在两个峰),我们指定的阈值应尽量在两个峰之间的峰谷。这时,就可以用第四个参数thresh_otsu,它对一幅双峰图像自动根据其直方图计算出合适的阈值(对于非双峰图,这种方法得到的结果可能不理想)。
对于双峰图,我们需要多传入一个参数cv2.thresh_otsu,并且把阈值thresh设为0,算法会找到最优阈值,并作为第一个返回值ret返回。
其中会返回两个值,第二个值就是二值化后的图形矩阵。
3.3轮廓的寻找
在轮廓的寻找方面,采用cv2.findcontours方式。代码示例如下:
1
2
|
cr,t = cv2.findcontours(b, cv2.retr_tree, cv2.chain_approx_simple) ##找到边界,第一个参数是二值图像,第二个参数是获取轮廓的方式,
#第三个参数定义轮廓的近似方式
|
上述函数里的参数中,第一个参数是二值化后的矩阵,第二个参数是获取轮廓的方式,第三个参数是定义轮廓的近似方式。后面两个参数的具体解释如下:
上面得到的结果中第一个结果是轮廓点的集合。
画出边界轮廓,运用函数是cv2.drawcontours,代码示例如下:
1
2
|
plt.imshow(cv2.drawcontours(e,cr, - 1 , 50 )) #画出边界,可以看出有坐标轴和五角星两个边界,第一个参数是原图,第二个参数是边界,
#第三个参数代表画出所有边界,第四个参数是线的粗细
|
上述函数中第一个参数是原始图形,第二个参数是得到的轮廓点的集合,第三个参数是代表画出所有轮廓点,第四个参数是线的粗细。
得到结果如下:
可以发现,坐标轴的轮廓和五角星的轮廓都被画了出来。
3.4轮廓的逼近,得到顶点
在得到轮廓点后,需要得到轮廓的顶点,通过顶点得到具体什么图形,在轮廓逼近中用到两个函数:cv2.arclength,cv2.approxpolydp,代码示例如下:
1
2
|
ep = 0.01 * cv2.arclength(cr[ 1 ], true) #五角星轮廓的周长cr[0]是坐标轴的周长,然后将其缩小,作为下一步的阈值
ap = cv2.approxpolydp(cr[ 1 ], ep, true) #轮廓的转折点的近似点
|
cv2.arclength得到的是轮廓点形成的曲线围成的图形的周长,cr[1]代表里层五角星的轮廓点,因为cr里有两个轮廓集合,一个是外层的坐标轴的轮廓点集合,一个是里层五角星的轮廓点集合。true代表闭合的曲线。将其取1%作为下一个函数的阈值。
cv2.approxpolydp将其得到的轮廓点进行筛选(按设定的阈值与其真实的线进行比较),其筛选的标准就是上一个函数得到的1%的周长,大于这个值的点舍去,小于这个值的点保留,true依然代表闭合曲线。
通过以上的步骤就可以保留一些点,而这些点就是得到顶点(这点需要读者去想一想,为什么以1%周长为阈值得到的点就是顶点,作者认为是两条线的拐点相对于来说是里真实线最近的点)
顶点数:
1
|
len (ap) #可以看见五角星有10个点
|
四、依据顶点判断形状
根据得到的定点数就可判断出形状了,三个顶点就是三角形,四个就是矩形,十个就是五角星,十个以上就是圆形了;上述的完整代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import cv2
import os
from pil import image
import matplotlib.pyplot as plt
import numpy as np
d = os.listdir( 'c:\\users\\dell\\desktop\\cleardata\\' )
for i in range ( len (d)):
e = cv2.imread( 'c:\\users\\dell\\desktop\\cleardata\\' + d[i])
g = cv2.cvtcolor(e,cv2.color_bgr2gray)
r,b = cv2.threshold(g, 0 , 255 ,cv2.thresh_otsu)
cr,t = cv2.findcontours(b, cv2.retr_tree, cv2.chain_approx_simple)
ep = 0.01 * cv2.arclength(cr[ 1 ], true)
ap = cv2.approxpolydp(cr[ 1 ], ep, true)
co = len (ap)
if co = = 3 :
st = '三角形'
elif co = = 4 :
st = '矩形'
elif co = = 10 :
st = '五角星'
else :
st = '圆'
plt.imsave( 'c:\\users\\dell\\desktop\\形状\\'+st+str(e[100][100])+str(i)+' .jpg',e) #取图像中间的点的rgb作为颜色代表
|
这里我还取了图形的中点,希望得到图片的颜色,其得到的是rgb值,通过rgb值就可以得到颜色。
最终结果如下:
到此这篇关于基于opencv的简单图像轮廓形状识别(全网最简单最少代码)的文章就介绍到这了,更多相关opencv 图像轮廓形状识别内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/WjoKe/article/details/113205908