注释:本文翻译自OpenCV3.0.0 document->OpenCV-Python Tutorials,包括对原文档种错误代码的纠正
3.1 改变色彩空间
3.1.1 目标:
- 这章节,学会如何转换图像的色彩空间,如BGR与Gray之间的转换,BGR与HSV之间的转换等
- 创建一个在视频中提取彩色对象的程序
- 学会这些函数:cv2.cvtColor()、cv2.inRange()等
3.1.2 改变颜色空间
在OpenCV中,有超过150种色彩空间转换的函数。但这里只介绍两种常用的:BGR与Gray,BGR与HSV。
函数cv2.cvtColor(input_image,flag),其中flag表示转换的类型从BGR到Gray用cv2.COLOR_BGR2GRAY。同样的BGR到HSV用cv2.BGR2HSV。
要获取所有的flag类型,在Python terminal种运行以下代码:
import cv2
flags = [i for i in dir(cv2) if startswith('COLOR_')]
print flags
Note:对于HSV,色相范围为[0,179],饱和度范围为[0,255],值范围为[0,255]。 不同的软件使用不同的刻度。 因此,如果您将OpenCV值与它们进行比较,则需要对这些范围进行规范化。
3.1.3 目标跟踪
在HSV中,表示颜色比RGB颜色空间更容易。在下面的应用程序中,我们尝试提取一个蓝色的对象,这里的方法是:
- 获取视频的每一帧
- 从BGR转换为HSV色彩空间
- 为HSV图像设置一系列蓝色阈值
- 单独提取蓝色对象
示例代码如下:
import cv2
import numpy as np
#传递参数0表示打开摄像头
cap = cv2.VideoCapture(0)
while (1):
# 获取每一帧
_, frame = cap.read()
# 将BGR转换为HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 定义HSV蓝色值的范围
lower_blue = np.array([110, 50, 50])
upper_blue = np.array([130, 255, 255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)
res = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('frame', frame)
cv2.imshow('mask', mask)
cv2.imshow('res', res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
结果如下:
3.2 图像的几何变换
3.2.1 目标:
- 学会图像的几种不同变换,如:旋转、平移、仿射变换等
- 学习这些函数:cv2.getPerspectiveTransform()
3.2.2转换
OpenCV种提供了两种转换函数:cv2.warpAffine()和cv2.warpPerspective(),可以使用它们进行各种转换,cv2.warpAffine()需要一个2*3的矩阵,而cv2.warpPerspective()需要一个3*3的矩阵作为输入。
3.2.3 缩放
缩放只是调整图像的大小。因此,OpenCV带有一个函数cv2.resize()。可以手动指定图像的大小,也可以指定缩放因子。使用不同的插值方法,优先选择的插值方法是cv2.INTER_AREA用于缩小和cv2.INTER_CUBI(slow)&cv2.INTER_KINEAR用于缩放。
默认情况下,使用的插值方法是cv2.INTER_LINEAR用于所有调整大小的图像。
缩放的示例代码如下:结果是把图像放大了一倍
'''
图像缩放
'''
import cv2
import numpy as np
img=cv2.imread('1.jpg')
##cv2.INTER_CUBIC is slow
#res=cv2.resize(img,None,fx=0.25,fy=0.25,interpolation=cv2.INTER_CUBIC)
#OR
height,width=img.shape[:2]
res=cv2.resize(img,(width*2,height*2),interpolation=cv2.INTER_CUBIC)
cv2.imshow('res',res)
k=cv2.waitKey(0)
cv2.destroyAllWindows()
3.2.4 平移
平移是物体位置的移动。如果你知道移动方位(tx,ty),就可以创建变换矩阵并移动,变换矩阵M如下:
可以将其变换为np.float32类型的Numpy数组,并将其传递给cv2.warpAffine()函数。
平移变换的示例代码如下:
'''
图像的平移变换:关键是创建平移矩阵,如代码中的M
'''
import cv2
import numpy as np
img = cv2.imread('1.jpg', 0)
rows, cols = img.shape
M = np.float32([[1, 0, 100], [0, 1, 50]]) # 将矩阵变换为np.float32类型的Numpy数组,并将其传递给cv2.warpAffine函数
# cv2.warpAffine()函数的第三个参数是输出图像的size,opencv3种必须以元组(width,height)的格式,
# 原文档中是分别传递width,height其实是错误的
# width=the number of columns,height=the number of rows
dst = cv2.warpAffine(img, M, (cols, rows)) # 第三个参数是输出图像的大小应该是(width,height)的格式
cv2.imshow('img', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
3.2.5 旋转
通过图像的变换矩阵来实现角度的旋转,变换矩阵如下:
但是OpenCV提供了可调节的旋转中心的旋转缩放,以便您可以在任何您喜欢的位置进行旋转。旋转矩阵变为:
其中:
要找到这个旋转矩阵,OpenCV中提供了一个cv2.getRotationMatrix2D()。
旋转的示例代码如下:
'''
图像旋转:得到旋转矩阵,使用cv2.getRotationMatrix2D()函数
将图像相对于中心旋转了90度,没有任何缩放
'''
import cv2
img = cv2.imread('1.jpg', 0)
rows, cols = img.shape
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('res', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.2.6 仿射变换
在仿射变换中,原始图像中所有平行线在输出图像中仍然是平行的。为了找到转换矩阵,我们需要输入图像中的三个点和它们在输出图像中的对应位置。然后,cv2.getAffineTransform()将创建一个2*3的矩阵,并传递给cv2.warpAffine().
仿射变换的示例代码如下:
'''
仿射变换:
1.在仿射变换中,原始图像中所有平行线在输出图像中仍然是平行的
2.也需要一个转换矩阵:需要输入图像中的三个点和它们在输出图像中的对应位置
3.用cv2.getAffineTransform()创建一个2*3的矩阵,传递给cv2.warpAffine()
'''
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('1.jpg')
rows, cols, ch = img.shape
# 输入点位置和输出点位置
pst1 = np.float32([[50, 50], [200, 50], [50, 200]])
pst2 = np.float32([[10, 100], [200, 50], [100, 50]])
# 通过输入点位置和输出点位置得到的变换矩阵
M = cv2.getAffineTransform(pst1, pst2)
dst = cv2.warpAffine(img, M, (cols, rows))
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()
结果:
3.2.7 透视变换
对于透视变换,需要一个3*3的变换矩阵。即使变换后,直线仍然保持直线,要找到此变换矩阵,需要输入图像上的四个点和输出图像上的对应点。在这4个点中,3个不应该共线。转换矩阵可以通过cv2.getPerspectiveTransform()找到,然后将这个3*3的矩阵应用到cv2.warpPerspective().
透视变换的示例代码如下:
'''
透视变换:
1.需要一个3*3的矩阵
2.变换后,直线仍然是直线
3.找到变换矩阵,需要输入图像上的四个点和对应的输出点(四个点中三个不应该共线)
4.变换矩阵可以通过cv2.getPerspectiveTransform()找到
5.最后将变换矩阵应用到cv2.warpPerspective()
'''
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('1.jpg')
rows, cols, ch = img.shape
# 四个输入点坐标及对其在输出图像中的对应左边
pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
# 获得变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)
# 将变换矩阵应用到cv2.warpPerspective()
dst = cv2.warpPerspective(img, M, (300, 300))
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()
结果: