机器视觉基础
常用图像处理技术包括色彩处理、形态相关操作、色彩梯度和轮廓处理我们将在后面内容中进行一一介绍,不过在正式开始之前,我们要先说明一下OpenCV的基础操作。
轮廓处理
图像轮廓操作包括:查找轮廓、绘制轮廓、轮廓拟合等。待处理的源图像必须是灰度二值图,将不需要的变成黑色
查找轮廓、绘制轮廓
img = cv2.imread('../data/3.png', 1)[..., ::-1]
#轮廓转二值化
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
#查找轮廓
cnts, hie = cv2.findContours(binary,
mode=cv2.RETR_EXTERNAL, #只检测外轮廓
method=cv2.CHAIN_APPROX_NONE) #存储所有的轮廓点
#绘制轮廓
img_cnt = cv2.drawContours(binary, cnts,
-1, # 绘制cnts中全部轮廓
(255, 255, 255), # 轮廓颜色BGR格式
20) # 轮廓粗细
fig, axes = plt.subplots(1, 4, figsize=(12, 12))
axes[0].imshow(img)
axes[1].imshow(gray, cmap=plt.get_cmap('gray'))
axes[2].imshow(binary, cmap=plt.get_cmap('gray')) # 因为使用了cv2.drawContours(binary.所以修改了原图
axes[3].imshow(img_cnt, cmap=plt.get_cmap('gray'))
plt.show()
绘制矩形
fig, axes = plt.subplots(1, 4, figsize=(15, 15))
img = cv2.imread('../data/cloud.png', 1)[..., ::-1]
axes[0].imshow(img)
#灰度化
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
axes[1].imshow(gray, cmap=plt.get_cmap('gray'))
#二值化
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
axes[2].imshow(binary, cmap=plt.get_cmap('gray'))
#查找轮廓
cnts, hie = cv2.findContours(binary,
mode=cv2.RETR_EXTERNAL, #只检测外轮廓
method=cv2.CHAIN_APPROX_NONE) #存储所有的轮廓点
x, y, w, h = cv2.boundingRect(cnts[0]) #实际上cnts只有一个轮廓,因为原图就一个图像
print('左上角定点:({},{}),宽度和高度({},{})'.format(x, y, w, h))
#根据矩形参数,确定四个顶点
poins = np.array([[[x, y]],
[[x, y + h]],
[[x + w, y + h]],
[[x + w, y]]])
#绘制矩形
img_cnt = cv2.drawContours(binary, [poins], -1, (255, 255, 255), 3)
axes[3].imshow(img_cnt, cmap=plt.get_cmap('gray'))
plt.show()
圆型包围
fig, axes = plt.subplots(1, 4, figsize=(15, 15))
img = cv2.imread('../data/cloud.png', 1)[..., ::-1]
axes[0].imshow(img)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
axes[1].imshow(gray, cmap=plt.get_cmap('gray'))
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
axes[2].imshow(binary, cmap=plt.get_cmap('gray'))
#查找轮廓
cnts, hie = cv2.findContours(binary,
mode=cv2.RETR_EXTERNAL, #只检测外轮廓
method=cv2.CHAIN_APPROX_NONE) #存储所有的轮廓点
center, radius = cv2.minEnclosingCircle(cnts[0])
print('圆心和半径:({},{})'.format(center, radius))
#圆心和半径必须是整数
center = (int(center[0]), int(center[1]))
radius = int(radius)
img_cnt = cv2.circle(binary, center, radius, (255, 255, 255), 3) #会修改原图
axes[3].imshow(img_cnt, cmap=plt.get_cmap('gray'))
plt.show()
椭圆包围
fig, axes = plt.subplots(1, 4, figsize=(15, 15))
img = cv2.imread('../data/cloud.png', 1)[..., ::-1]
axes[0].imshow(img)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
axes[1].imshow(gray, cmap=plt.get_cmap('gray'))
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
axes[2].imshow(binary, cmap=plt.get_cmap('gray'))
#查找轮廓
cnts, hie = cv2.findContours(binary,
mode=cv2.RETR_EXTERNAL, #只检测外轮廓
method=cv2.CHAIN_APPROX_NONE) #存储所有的轮廓点
ellipse = cv2.fitEllipse(cnts[0])
#ellipse为RotatedRect类型的值,包含外接矩形的质心、宽、高、旋转角度等参数信息,这些信息正好与椭圆的中心点、轴长度、旋转角度等信息吻合
print("ellipse:", ellipse)
# 绘制椭圆
img_cnt = cv2.ellipse(binary, ellipse, (0, 0, 0), 4)
axes[3].imshow(img_cnt, cmap=plt.get_cmap('gray'))
plt.show()
多边形拟合
fig, axes = plt.subplots(1, 4, figsize=(15, 15))
img = cv2.imread('../data/cloud.png', 1)[..., ::-1]
axes[0].imshow(img)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
axes[1].imshow(gray, cmap=plt.get_cmap('gray'))
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
axes[2].imshow(binary, cmap=plt.get_cmap('gray'))
#查找轮廓
cnts, hie = cv2.findContours(binary,
mode=cv2.RETR_EXTERNAL, #只检测外轮廓
method=cv2.CHAIN_APPROX_NONE) #存储所有的轮廓点
epsilon = 0.01 * cv2.arcLength(cnts[0], True) # 精度,根据周长计算,True表示求封闭周长,0。01表示是0.01倍周长
poins = cv2.approxPolyDP(cnts[0], epsilon, True) # 构造多边形True表示闭合
# 绘制椭圆
img_cnt = cv2.drawContours(binary, [poins], -1, (0, 0, 0), 4) #-1表示轮廓集内所有轮廓都要画出来,是轮廓的索引
axes[3].imshow(img_cnt, cmap=plt.get_cmap('gray'))
plt.show()
视频操作
读取摄像头
'''
读取摄像头,并播放
'''
import cv2
# 读取摄像头对象
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, img = cap.read() # 捕获一帧图像
cv2.imshow('img', img)
key = cv2.waitKey(1)
if key == 27:
break
cap.release() # 释放掉摄像头对象
cv2.destroyAllWindows()
播放视频文件
import cv2
cap = cv2.VideoCapture("./output.avi") # 打开视频文件
while cap.isOpened():
ret, frame = cap.read() # 读取帧
cv2.imshow("frame", frame) # 显示
c = cv2.waitKey(25)
if c == 27: # ESC键
break
cap.release() # 释放视频设备
cv2.destroyAllWindows()
捕获并保存视频
import numpy as np
import cv2
""" 编解码4字标记值说明
cv2.VideoWriter_fourcc('I','4','2','0')表示未压缩的YUV颜色编码格式,色度子采样为4:2:0。
该编码格式具有较好的兼容性,但产生的文件较大,文件扩展名为.avi。
cv2.VideoWriter_fourcc('P','I','M','I')表示 MPEG-1编码类型,生成的文件的扩展名为.avi。
cv2.VideoWriter_fourcc('X','V','I','D')表示MPEG-4编码类型。如果希望得到的视频大小为平均值,可以选用这个参数组合。
该组合生成的文件的扩展名为.avi。
cv2.VideoWriter_fourcc('T','H','E','O')表示Ogg Vorbis编码类型,文件的扩展名为.ogv。
cv2.VideoWriter_fourcc('F','L','V','I')表示Flash视频,生成的文件的扩展名为.flv。
"""
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc("I", "4", "2", "0") # 编解码4字标记值
out = cv2.VideoWriter("C:\\Users\\BJTT\\Desktop\\0810\\output.avi", # 文件名
fourcc, # 编解码类型
20, # fps(帧速度)
(640, 480)) # 视频分辨率
while cap.isOpened():
ret, frame = cap.read() # 读取帧
if ret == True:
out.write(frame) # 写入帧
cv2.imshow("frame", frame)
if cv2.waitKey(1) == 27: # ESC键
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()