计算机视觉OpenCV(五):图像金字塔与轮廓检测

目录

    • 图像金字塔
      • 1. 高斯金字塔(Gaussian Pyramid)
      • 2. 拉普拉斯金字塔(Laplacian Pyramid)
    • 图像轮廓
      • 1. 查找检测物体的轮廓
      • 2. 绘制轮廓
      • 3. 轮廓特征
      • 4. 轮廓近似
      • 5. 边界矩形
      • 6. 外接圆
      • 7. 扩展(画图)

图像金字塔

1. 高斯金字塔(Gaussian Pyramid)

首先将原图像作为最底层图像 G0(高斯金字塔的第0层),利用高斯核(5 * 5)对其进行卷积,然后对卷积后的图像进行下采样(去除偶数行和列)得到上一层图像 G1,将此图像作为输入,重复卷积和下采样操作得到更上一层图像,反复迭代多次,形成一个金字塔形的图像数据结构,即高斯金字塔。

向下采样方法(缩小):pyrDown 函数
向上采样方法(放大):pyrUp 函数

cv2.pyrDown() 从一个高分辨率大尺寸的图像向上构建一个金字塔(尺寸变小,分辨率降低)

cv2.pyrDown(src, dst=None, dstsize=None, borderType=None)

cv2.pyrUp() 从一个低分辨率小尺寸的图像向下构建一个金子塔(尺寸变大,但分辨率不会)

cv2.pyrUp(src, dst=None, dstsize=None, borderType=None)
import cv2
import matplotlib.pyplot as plt
%matplotlib inline

img = cv2.imread("atongmu.jpg")
up = cv2.pyrUp(img) #向上采样
down = cv2.pyrDown(img) #向下采样

plt.imshow(img)
# plt.imshow(up)
# plt.imshow(down)
print("原图:" + str(img.shape))
print("放大:" + str(up.shape))
print("缩小:" + str(down.shape))

计算机视觉OpenCV(五):图像金字塔与轮廓检测_第1张图片

2. 拉普拉斯金字塔(Laplacian Pyramid)

LP = image - pyrUp(pyrDown(image))
用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

img = cv2.imread("atongmu.jpg")
down_up = cv2.pyrUp(cv2.pyrDown(img))
LP = img - down_up
cv_show("Laplacian Pyramid",LP)
plt.imshow(LP)

计算机视觉OpenCV(五):图像金字塔与轮廓检测_第2张图片


图像轮廓

1. 查找检测物体的轮廓

image, contours, hierarchy = cv2.findContours(img, mode, method)

参数:
(1)图像
(2)mode 轮廓检索方式:
  cv2.RETR_EXTERNAL:只检测外轮廓;
  cv2.RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
    cv2.RETR_CCOMP:建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
  cv2.RETR_TREE:建立一个等级树结构的轮廓。
(3)method 轮廓逼近方法:
  cv2.CHAIN_APPROX_NONE:存储所有的轮廓点,相邻的两个点的像素位置差不超过 1,即 max(abs(x1-x2),abs(y2-y1))==1
  cv2.CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需 4 个点来保存轮廓信息
  cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS 使用 teh-Chinl chain 近似算法
返回值:
(1)image 其实与输入参数的img原图没啥区别
(2)轮廓本身
(3)每条轮廓对应的属性
注意: cv2.findContours() 函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图。

2. 绘制轮廓

cv2.drawContours(image, contours, contourIdx, color,thickness) 

参数:
(1)需要绘制轮廓的图像;
(2)轮廓本身,在 Python 中是一个 list。
(3)指定绘制轮廓 list 中的哪条轮廓,如果是 -1 则绘制其中的所有轮廓。
(4)颜色
(5)轮廓线的宽度(厚度),如果是 -1(cv2.FILLED)则为填充模式。

例如:img 是图像,contours 是轮廓,-1 表示全画,然后是颜色,厚度

cv2.drawContours(img,contours,-1,(0,255,0),3)
img = cv2.imread("star.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) #二值化阈值
#查找检测物体的轮廓
image,contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
draw_img = img.copy() #注意需要copy,否则原图会变
#绘制图像轮廓
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show("star",res)
plt.imshow(res)

计算机视觉OpenCV(五):图像金字塔与轮廓检测_第3张图片

3. 轮廓特征

cnt = contours[0]
area = cv2.contourArea(cnt) #面积
len = cv2.arcLength(cnt,True) #周长,True表示闭合的
print("面积:" + str(area))
print("周长:" + str(len))

4. 轮廓近似

approxPolyDP() 函数是 opencv 中对指定的点集进行多边形逼近的函数

approx = cv2.approxPolyDP(curve, epsilon, closed)

返回值 approx:输出的点集,当前点集是能最小包容指定点集的,画出来即是一个多边形。
参数:
(1)curve:输入的点集
(2)epsilon:指定的精度,也即是原始曲线与近似曲线之间的最大距离。
(3)closed:若为 true,则说明近似曲线是闭合的;若为 false,则断开。

#import、函数cv_show与前面一样,省略,仅修改下面
img = cv2.imread("star.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0] #点集
epsilon = 0.001*cv2.arcLength(cnt,True) #精度
approx = cv2.approxPolyDP(cnt,epsilon,True) #逼近

draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv_show("star",res)
plt.imshow(res)

计算机视觉OpenCV(五):图像金字塔与轮廓检测_第4张图片

5. 边界矩形

用一个最小的矩形,把找到的形状包起来

x,y,w,h = cv2.boundingRect(img)

参数:img 是一个二值图
返回值 x,y,w,h:x、y 是矩阵左上点的坐标,w、h 是矩阵的宽和高

画矩形:

cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)

参数:
(1)img 是原图
(2)(x,y) 是矩阵的左上点坐标
(3)(x+w,y+h) 是矩阵的右下点坐标
(4)画线对应的 rgb 颜色
(5)线的宽度

#import、函数cv_show与前面一样,省略,仅修改下面
img = cv2.imread("star.png")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
image,contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]

#画出最小的矩形框架
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

cv_show("img",img)
plt.imshow(img)

计算机视觉OpenCV(五):图像金字塔与轮廓检测_第5张图片

6. 外接圆

cv2.minEnclosingCircle() 得到包含二维点集的最小圆

(x,y),radius = cv2.minEnclosingCircle(cnt) 

返回值:圆形的中心坐标,最小圆的半径(均为 float 型)
参数:输入的二维点集

绘制圆 cv2.circle()

cv2.circle(img, center, radius, color, thickness)

参数:img 背景图,center 圆心,radius 半径,color 颜色,thickness 线粗细

#import、函数cv_show与前面一样,省略,仅修改下面
img = cv2.imread("star.png")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
image,contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]

(x,y),radius = cv2.minEnclosingCircle(cnt) #最小圆
center = (int(x),int(y)) 
radius = int(radius) 
img_1 = cv2.circle(img,center,radius,(0,255,0),2) #画圆
cv_show("img",img_1)
plt.imshow(img_1)

计算机视觉OpenCV(五):图像金字塔与轮廓检测_第6张图片

7. 扩展(画图)

(1)cv2.line() 画线
参数:图像,起点,终点,颜色,线条宽度

cv2.line(img,(10,10),(200,200),(0,255,0),3)

(2)cv2.circle() 画圆
参数:图像,圆心,半径,颜色,线条宽度

cv2.circle(img,(60,60),30,(0,0,213),-1)

(3)cv2.rectangle() 画矩形
参数:图像,左上顶点,右下顶点,颜色,线条宽度

cv2.rectangle(img,(10,10),(30,40),(134,2,34),1)

(4)cv2.ellipse() 椭圆
参数:图像,中心点位置,长轴和短轴的长度,椭圆沿逆时针选择角度,顺时针起始角度,顺时针结束角度,颜色,线条宽度

cv2.ellipse(img,(256,256),(100,50),0,0,180,(20,213,79),-1)

(5)cv2.putText() 文字绘制
参数:图像,绘制的文字,左上角坐标,字型,字体大小,文字颜色,线条宽度

cv2.putText(img,’OpenCV’,(80,90), font, 2,(255,255,255),3)

(6)cv2.polylines() 多边形 — 需要指定每个顶点的坐标
参数:图像,点集,是否闭合,颜色,线条宽度

cv2.polylines(img,[pts],True,(0,0,255),1)
import cv2
import matplotlib.pyplot as plt
%matplotlib inline

img = cv2.imread('white_board.png')
img_2 = img.copy()

#直线 - 绿色
cv2.line(img_2,(10,10),(200,200),(0,255,0),3)
#圆 - 天蓝
cv2.circle(img_2,(200,200),30,(0,150,210),2)
#矩形 - 红色
cv2.rectangle(img_2,(150,60),(300,110),(255,0,0),5)
#椭圆 - 实心淡绿
cv2.ellipse(img_2,(300,150),(80,30),0,0,360,(170,228,170),-1)
#文字 - 黑色
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img_2, 'OpenCV', (150, 40), font, 1, (0, 0, 0), 2)
#多边形 - 蓝色
#定义四个顶点坐标,必须为np.int32
pts = np.array([[50, 100],  [10, 175], [100, 200], [100, 120]], np.int32)
pts = pts.reshape((-1, 1, 2)) #顶点个数:4,矩阵变成4*1*2维
cv2.polylines(img_2, [pts], True, (0, 0, 255), 3)

plt.imshow(img_2)

计算机视觉OpenCV(五):图像金字塔与轮廓检测_第7张图片

本笔记记录学习OpenCV,若有错误,欢迎批评指正,学习交流。

你可能感兴趣的:(opencv,计算机视觉,opencv,python)