opencv python 识别图形轮廓
Posted 想要成为钢铁侠的男人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv python 识别图形轮廓相关的知识,希望对你有一定的参考价值。
目的:
1. 识别并框选出图片中红色的几何图形,分辨出各是什么图形(不允许用鼠标 操作)。
2. 将红色图形中心连线,计算连线围成图形的面积。
代码如下:
import cv2
import sys
import cmath
import numpy
#读取图像
areas = list()
x= list()
y = list()
img1 = cv2.imread("E:/a/qw.jpg")
(B,G,R) = cv2.split(img1)
retal , img2 = cv2.threshold(R,0,255,cv2.THRESH_OTSU)
contours, hierarachy = cv2.findContours(img2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
#cv2.drawContours(img1,contours,i,(0,0,255),10)
area = cv2.contourArea(contours[i],False)
areas.append(area)
areas.sort(reverse=True)
for i in range(len(contours)):
area = cv2.contourArea(contours[i],False)
if area > areas[5]:
if area < areas[1]:
print(i)
epsilon = 0.02 * cv2.arcLength(contours[i], True)
approx = cv2.approxPolyDP(contours[i],epsilon,True)
cv2.polylines(img1,[approx],True,(0,0,255),10)
M = cv2.moments(contours[i])
cx = int(M["m10"]/M["m00"])
cy = int(M["m01"]/M["m00"])
x.append(cx)
y.append(cy)
if len(approx) > 4:
print("圆形")
text = "y"
elif len(approx) == 3:
print("三角形")
text = "s"
elif len(approx) == 4:
print("矩形")
text = "j"
cv2.putText(img1,text,(cx,cy),cv2.FONT_HERSHEY_PLAIN,10,(0, 255, 0),5)
S = (1/2)*(x[0]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0]+x[2]*y[0]-x[1]*y[1])
print("s=%d"%S)
pts = numpy.array([[x[0],y[0]],[x[1],y[1]],[x[2],y[2]]])
pts = pts.reshape((-1,1,2))
cv2.polylines(img1,[pts],True,(255, 0, 0),10)
cv2.namedWindow("RED",cv2.WINDOW_NORMAL)
cv2.imshow("RED",img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
首先:
读取文件中的图片,注意:文件地址的斜杠要是/或\\\\,否则会报错
img1 = cv2.imread("E:/a/qw.jpg")
我们用imshow函数来显示图片的时候会发现图片过大屏幕显示不完
cv2.imshow("RED",img1)
比如这样,所以我们需要将图像变形以便更合适显示在我们的屏幕,利用下面的函数就可以舒服的显示我们的图像啦
cv2.namedWindow("RED",cv2.WINDOW_NORMAL)
标志参数 | 作用 |
WINDOW_AUTOSIZE | 根据图像大小显示窗口,不允许用户调整大小 |
WINDOW_FREERATIO | 窗口大小自适应比例 |
WINDOW_KEEPRATIO | 保持图像的比例 |
WINDOW_NORMAL | 显示图像后,允许用户随意调整窗口大小 |
进行图片的通道分离:利用split函数来分离出蓝、绿、红三种颜色的灰度图
(B,G,R) = cv2.split(img1)
这个是红色分离后的图像,可以看出红色的地方已经变成白色或灰色
然后经过图像二值化函数threshold()得到黑白的图像(二值图),从而把红色更好的提出
retal , img2 = cv2.threshold(R,0,255,cv2.THRESH_OTSU)
寻找图形轮廓,把刚刚得到的二值图放进函数,在二值图中寻找轮廓,返回每个轮廓的点contours
contours, hierarachy = cv2.findContours(img2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
通过这个轮廓得到的点去画出得到的轮廓利用drawContours来画出:
cv2.drawContours(img1,contours,i,(0,0,255),10)
我们发现有很多的噪声需要消掉,我们通过判断面积来将不是红色轮廓的其他轮廓消除,不难看出红色的三个图形轮廓的面积在全部轮廓中排名3,4,5.所以我们通过contourArea()函数求出每个轮廓的面积并把他们放在areas列表中。
area = cv2.contourArea(contours[i],False)
areas.append(area)
这是把其他轮廓去除之后的图形
我们发现这三分个轮廓,每个轮廓都是由很多个轮廓点组成,但是确实像矩形可以只用四个轮廓点表示,三角形可以只用三个轮廓点表示就可以了,所以下一步为了方便我们检测图形是否是三角形、圆形还是矩形,我们需要对轮廓点进行优化,所以我们就用到了approxPolyDP函数
epsilon = 0.02 * cv2.arcLength(contours[i], True)
approx = cv2.approxPolyDP(contours[i],epsilon,True)
在这里epsilon作为一个参数,这个需要调一下。0.02就是调出来的。具体参考:
opencv 使用approxPolyDP轮廓近似_brooknew的专栏-CSDN博客
再利用polylines()函数来画出轮廓点之间的连线
cv2.polylines(img1,[approx],True,(0,0,255),10)
效果如下:
然后根据轮廓点的个数就可以判断是什么形状啦。
下一步我们寻找红色图形的中心点,用moments()函数求出图形的矩,并求出每个图形的重心,详细可以看
Python OpenCV findContours()函数与drawContours()函数用法_dz4543的博客-CSDN博客_drawcontours()参数说明
M = cv2.moments(contours[i])
cx = int(M["m10"]/M["m00"])
cy = int(M["m01"]/M["m00"])
然后根据三点求面积公式就可以求出三个重心围成的面积
S=(1/2)*(x1y2*1+x2y3*1+x3y1*1-x1y3*1-x2y1*1-x3y2*1)
S = (1/2)*(x[0]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0]+x[2]*y[0]-x[1]*y[1])
然后利用polylines()函数连接三个重心
pts = numpy.array([[x[0],y[0]],[x[1],y[1]],[x[2],y[2]]])
pts = pts.reshape((-1,1,2))
cv2.polylines(img1,[pts],True,(255, 0, 0),10)
在这里reshape()是为了规范参数形式,让pts自适应维度大小。
最终的图形为
本文章是作者为了记录学习过程而写,如果有错误请大家指正。
以上是关于opencv python 识别图形轮廓的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV-Python实战(11)——OpenCV轮廓检测相关应用