(三)OpenCV中的图像处理之改变色彩空间及图像的几何变换

注释:本文翻译自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颜色空间更容易。在下面的应用程序中,我们尝试提取一个蓝色的对象,这里的方法是:

  1.  获取视频的每一帧
  2.   从BGR转换为HSV色彩空间
  3.   为HSV图像设置一系列蓝色阈值
  4.   单独提取蓝色对象

示例代码如下:

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()

结果:




猜你喜欢

转载自blog.csdn.net/u014403318/article/details/80487305