OpenCV图像处理技术(Python)——图像轮廓

OpenCV图像处理技术(Python)——图像轮廓
© Fu Xianjun. All Rights Reserved.

文章目录

  • 学习目标
  • 学习内容
  • 一、图像轮廓
    • 1.图像轮廓的概念
    • 2.查找轮廓
    • 3.绘制轮廓
  • 二、计算轮廓的面积及长度
    • 1.矩特征
    • 2.计算轮廓的面积
    • 3.计算轮廓长度
  • 三、使用Hu特征进行形状匹配
    • 1.Hu特征概念
    • 2.形状匹配
  • 四、轮廓拟合
    • 1.矩形包围框
    • 2.最小包围框
    • 3.最小包围圆形
    • 4.最优拟合椭圆
    • 5.最优拟合直线
    • 6.逼近多边形
  • 总结


学习目标

1.能够掌握轮廓查找与绘制的方法
2.能够掌握轮廓面积及长度的计算方法
3.能够编程实现形状匹配
4.能够掌握轮廓的几何形状拟合方法


学习内容

一、图像轮廓

1.图像轮廓的概念

1.1边缘检测虽然能够检测出边缘,但边缘是不连续的,检测到的边缘并不是一个整体。图像轮廓是指将边缘连接起来形成的一个整体,用于后续的计算。

1.2图像轮廓是图像中非常重要的一个特征信息,通过对图像轮廓的操作,我们能够获取目标图像的大小、位置、方向等信息。

1.3轮廓是一系列相连的点组成的曲线,代表了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全部连续。

2.查找轮廓

OpenCV图像处理技术(Python)——图像轮廓_第1张图片

这是核心代码以及解释:
cv2.RETR_EXTERNAL 只检测外轮廓

cv2.RETR_LIST检测的轮廓不建立等级关系

cv2.RETR_CCOMP建立两个等级的轮廓

cv2.RETR_TREE建立一个等级树结构的轮廓

method:

cv2.CHAIN_APPROX_NONE存储所有的轮廓点

cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。

import cv2
import numpy as np
img = cv2.imread('shape.jpg')    #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\
                                       cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours)       #轮廓个数
print(n)
print(len(contours[0]))       #轮廓0像素数目
print(len(contours[1]))       #轮廓1像素数目
print(len(contours[2]))       #轮廓2像素数目
print(len(contours[3]))       #轮廓3像素数目

3.绘制轮廓

核心代码:
image=cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)

cv2.imshow("img",img) #显示原图像
img2 = cv2.drawContours(img,contours,1,(0,165,255),-1)  #绘制轮廓,1表示绘制第几个轮廓
cv2.imshow("contours",img2)   #显示轮廓
cv2.waitKey()
cv2.destroyAllWindows()

代码运行结果:
OpenCV图像处理技术(Python)——图像轮廓_第2张图片
逐个绘制图像内的边缘信息:

n=len(contours)       #轮廓个数
contoursImg=[]
for i in range(n):
    temp=np.zeros(img.shape,np.uint8) #生成黑背景
    contoursImg.append(temp)
    contoursImg[i]=cv2.drawContours(contoursImg[i],contours,i,(255,255,255), 3)  #绘制轮廓
    cv2.imshow("contours[" + str(i)+"]",contoursImg[i])   #显示轮廓
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
OpenCV图像处理技术(Python)——图像轮廓_第3张图片

二、计算轮廓的面积及长度

1.矩特征

比较两个轮廓最简单的方法是比较二者的轮廓矩。轮廓矩代表了一个轮廓、一幅图像、一组点集的全局特征。矩信息包含了对应对象不同类型的几何特征,例如大小、位置、角度、形状等。矩特征被广泛地应用在模式识别、图像识别等方面。

核心代码以及解释: retval=cv2.moments(array[,binaryImage])
array:可以是点集,也可以是灰度图像或者二值图像。
binaryImage:当为True时,array内所有的非零值都会被处理为1.

2.计算轮廓的面积

area=cv2.contourArea(contour [, oriented])
contour :轮廓。
oriented:布尔值,当为True时,表示顺时针或逆时针计算.
import cv2
import numpy as np
img = cv2.imread('shape.jpg')    #读取图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转为灰度值图
ret, binary = cv2.threshold(gray,220,255,cv2.THRESH_BINARY) #转为二值图
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,\
                                       cv2.CHAIN_APPROX_NONE) #寻找轮廓
n=len(contours)       #轮廓个数
contoursImg=[]
for i in range(n):
    area = cv2.contourArea(contours[i])
    print(f"轮廓{i}的面积:\n{area}")

3.计算轮廓长度

length=cv2.arcLength(curve,closed)
curve :轮廓。
closed :布尔值,当为True时,表示闭合.
n=len(contours)       #轮廓个数
contoursImg=[]
for i in range(n):
    length = cv2.arcLength(contours[i], True)  #获取轮廓长度
    print(f"轮廓{i}的长度:\n{length}")

三、使用Hu特征进行形状匹配

1.Hu特征概念

Hu矩是归一化中心矩的线性组合,Hu矩再图像旋转,缩放,平移等操作后,仍能保持矩的不变性,经常使用 Hu 矩来识别图像的特征。在 OpenCV 中,使用函数 cv2.HuMoments()可以得到 Hu 距。该函数使用 cv2.moments()函数的返回值作为参数,返回 7 个 Hu 矩值。

2.形状匹配

import cv2
o1 = cv2.imread('m1.png')
o2 = cv2.imread('m2.png')
o3 = cv2.imread('m3.png') 
gray1 = cv2.cvtColor(o1,cv2.COLOR_BGR2GRAY) 
gray2 = cv2.cvtColor(o2,cv2.COLOR_BGR2GRAY) 
gray3 = cv2.cvtColor(o3,cv2.COLOR_BGR2GRAY) 
ret, binary1 = cv2.threshold(gray1,127,255,cv2.THRESH_BINARY) 
ret, binary2 = cv2.threshold(gray2,127,255,cv2.THRESH_BINARY) 
ret, binary3 = cv2.threshold(gray3,127,255,cv2.THRESH_BINARY) 
contours1, hierarchy = cv2.findContours(binary1,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 
contours2, hierarchy = cv2.findContours(binary2,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 
contours3, hierarchy = cv2.findContours(binary3,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 
cnt1 = contours1[0]
cnt2 = contours2[0]
cnt3 = contours3[0]
ret0 = cv2.matchShapes(cnt1,cnt1,1,0.0)
ret1 = cv2.matchShapes(cnt1,cnt2,1,0.0)
ret2 = cv2.matchShapes(cnt1,cnt3,1,0.0)
print("相同图像的 matchShape=",ret0)
print("相似图像的 matchShape=",ret1)
print("不相似图像的 matchShape=",ret2)

四、轮廓拟合

1.矩形包围框

retval = cv2.boundingRect( array )
retval:矩形边界左上角顶点的坐标值及矩形边界的宽度和高度。
contour2:第二个灰度或轮廓图像。
method :比较两个对象的Hu 矩的方法,写1吧
import cv2
img=cv2.imread('shape.jpg')
cv2.imshow("original",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 
x,y,w,h=cv2.boundingRect(contours[0])
cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,0),2)
cv2.imshow("result",img)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
OpenCV图像处理技术(Python)——图像轮廓_第4张图片

2.最小包围框

import cv2
o=cv2.imread('shape.jpg')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 
rect = cv2.minAreaRect(contours[1])
print("返回值 rect:\n",rect)
points = cv2.boxPoints(rect)
print("\n 转换后的 points:\n",points)
points = np.int64(points)                 #取整,np.int64=np.int0
image=cv2.drawContours(o,[points],0,(0,0,0),2)
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
OpenCV图像处理技术(Python)——图像轮廓_第5张图片

3.最小包围圆形

import cv2
o=cv2.imread('shape.jpg')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) 
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

(x,y),radius = cv2.minEnclosingCircle(contours[1])
center = (int(x),int(y))
radius = int(radius)
cv2.circle(o,center,radius,(0,0,0),2)          # 跟 matplotlib 类似吧。。
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:OpenCV图像处理技术(Python)——图像轮廓_第6张图片

4.最优拟合椭圆

import cv2
o=cv2.imread('shape.jpg')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) 
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

ellipse = cv2.fitEllipse(contours[1])
print("ellipse=",ellipse)
cv2.ellipse(o,ellipse,(0,255,0),3)
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
OpenCV图像处理技术(Python)——图像轮廓_第7张图片

5.最优拟合直线

import cv2
o=cv2.imread('shape.jpg')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) 
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

rows,cols = o.shape[:2]
[vx,vy,x,y] = cv2.fitLine(contours[1], cv2.DIST_L2,0,0.01,0.01) # 返回值是共线的归一化向量,和线上一点
lefty = int((-x*vy/vx) + y)                   # 说白了就是一个方向和一个点,点斜式嘛,还啥vec4f,,讲究
righty = int(((cols-x)*vy/vx)+y)                # 计算两个点,代值计算就行
cv2.line(o,(cols-1,righty),(0,lefty),(0,255,0),2)   
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
OpenCV图像处理技术(Python)——图像轮廓_第8张图片

6.逼近多边形

import cv2
import numpy as np

# 多边形逼近
# 1.先找到轮廓
img = cv2.imread('contours3.png')
cv2.imshow("original",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]

# 2.进行多边形逼近,得到多边形的角点
approx1 = cv2.approxPolyDP(cnt, 3, True)
approx2 = cv2.approxPolyDP(cnt, 15, True)
approx3 = cv2.approxPolyDP(cnt, 75, True)

# 3.画出多边形
adp=img.copy()
img1=cv2.polylines(adp, [approx1], True, (255, 0, 0), 2)
cv2.imshow('approxPloyDP1', img1)
####
adp=img.copy()
img2=cv2.polylines(adp, [approx2], True, (0, 255, 0), 2)
cv2.imshow('approxPloyDP2', img2)
#####
adp=img.copy()
img3=cv2.polylines(adp, [approx3], True, (0, 0, 255), 2)
cv2.imshow('approxPloyDP3', img3)

print(len(approx1),len(approx2),len(approx3))  # 角点的个数



cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
OpenCV图像处理技术(Python)——图像轮廓_第9张图片


总结

今天要了解的内容比较多,但是也是很重要的内容,这里的东西在以后的学习之中也会有充分的利用。

你可能感兴趣的:(OpenCV图像处理技术(Python)——图像轮廓)