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轮廓检测相关应用

使用 OpenCV (Python) 改进轮廓检测

颜色识别轮廓识别-树莓派 Opencv-基于Python学习记录DAY-4

使用 OpenCV-Python 识别答题卡判卷

OpenCV+python轮廓

OpenCV红绿灯识别 轮廓识别 C++ OpenCV 案例实现