快乐学习
前程无忧、中华英才非你莫属!

6-OpenCV-改变色彩空间和几何变换

前言

本章节你将学习图像的改变色彩空间、提取对象、图像的几何变换

一、改变色彩空间


目标:

本章节你需要学习以下内容:

*你将学习如何将图像从一个颜色空间转换为另一个颜色空间,例如BGR↔Gray,BGR↔HSV等。

*除此之外,我们还将创建一个提取视频中某个特定彩色对象的应用程序

*你将学习以下函数:cv.cvtColor(),cv.inRange()等。

1.改变色彩空间

OpenCV中有150多种颜色空间转换方法。但我们将只研究两种最广泛使用的转换方法,BGRGray和BGRHSV。

对于颜色转换,我们使用函数cv.cvtColor(input_image,flag),其中flag确定转换类型。

对于BGR→Gray转换,我们使用标志cv.COLOR_BGR2GRAY。类似地,对于BGR→HSV,我们使用标志cv.COLOR_BGR2HSV。要获取其他标志,只需在Python终端中运行以下命令:

>>> import cv2 as cv

>>> flags = [i for i in dir(cv) if i.startswith('COLOR_')]

>>> print( flags )

注意:对于HSV色彩空间,色调的取值范围是[0,179],饱和度的取值范围是[0,255],亮度的取值范围是[0,255]。不同的软件可能使用不同的取值方式,因此,如果要将OpenCV的HSV值与其他软件的HSV值进行比较时,则需要对这些范围进行标准化。


2.对象提取

现在我们知道如何将BGR图像转换为HSV,我们可以使用HSV色彩空间来提取彩色对象。在HSV中表示颜色比在BGR颜色空间中更容易。

在我们的程序中,我们将尝试提取视频画面中的蓝色对象。下面是方法程序执行步骤:

  • 获取视频中的每一帧

  • 从BGR转换为HSV颜色空间

  • 将HSV图像阈值设为一系列蓝色

  • 单独提取并显示蓝色对象,之后我们便可以对我们想要的图像做任何事情。

以下是详细评论的代码:

import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
while(1):
    
    # Take each frame
    _, frame = cap.read()
    
    # Convert BGR to HSV
    hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
    
    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])
    
    # Threshold the HSV image to get only blue colors
    mask = cv.inRange(hsv, lower_blue, upper_blue)
    
    # Bitwise-AND mask and original image
    res = cv.bitwise_and(frame,frame, mask= mask)
    
    cv.imshow('frame',frame)
    cv.imshow('mask',mask)
    cv.imshow('res',res)
    k = cv.waitKey(5) & 0xFF
    if k == 27:
        break
        
cv.destroyAllWindows()

下面的图片展示了我们提取蓝色对象后的效果:

注意:图像中有一些噪音,我们将在后面的章节中看到如何删除它们。这是对象提取中最简单的方法。

一旦你学习了轮廓的功能,你就可以做很多事情,比如找到这个物体的重心并用它来追踪物体,只需在镜头前移动你的手以及许多其他有趣的东西来绘制图表。


3.如何找到要跟踪的HSV值


这是我们在stackoverflow.com中常见的问题。其实解决这个问题非常简单,你可以使用相同的函数cv.cvtColor()。

你只需传递所需的BGR值,而不是传递图像。例如,要查找绿色的HSV值,在Python终端中输入以下命令:

>>> green = np.uint8([[[0,255,0 ]]])
>>> hsv_green = cv.cvtColor(green,cv.COLOR_BGR2HSV)
>>> print( hsv_green )
[[[ 60 255 255]]]

现在分别将[H-10,100,100]和[H+10,255,255]作为下限和上限。除了这种方法,你可以使用任何图像编辑工具如GIMP,或任何在线转换器来查找这些值,但不要忘记调整HSV范围。


二、图像的几何变换


目标

本章节你需要学习以下内容:

*将不同的几何变换应用于图像,如平移,旋转,仿射变换等。

*你将看到以下函数:cv.getPerspectiveTransform

1.转换

OpenCV提供了两个转换函数cv.warpAffine和cv.warpPerspective,你可以使用它们进行各种转换。

cv.warpAffine采用2x3变换矩阵作为参数输入,而cv.warpPerspective采用3x3变换矩阵作为参数输入。

2.缩放

缩放只是调整图像大小。为此,OpenCV附带了一个函数cv.resize()。

可以手动指定图像的大小,也可以指定缩放系数。

可以使用不同的插值方法,常用的插值方法是用于缩小的cv.INTER_AREA和用于缩放的cv.INTER_CUBIC(慢)和cv.INTER_LINEAR。

默认情况下,使用的插值方法是cv.INTER_LINEAR,它用于所有调整大小的目的。你可以使用以下方法之一调整输入图像的大小:

import numpy as np

import cv2 as cv

img = cv.imread('messi5.jpg')

res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC)

#OR

height, width = img.shape[:2]

res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)

3.平移

平移是对象位置的移动。如果你知道像素点(x,y)要位移的距离,让它为变为($t_x$,$t_y$),你可以创建变换矩阵M,如下所示:

$$M=begin{bmatrix} 1&0&t_x 0&1&t_y end{bmatrix}$$

你可以将其设置为np.float32类型的Numpy数组,并将其传递给cv.warpAffine()函数。下面的示例演示图像像素点整体进行(100,50)位移:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img,M,(cols,rows))
cv.imshow('img',dst)
cv.waitKey(0)
cv.destroyAllWindows()

注意:cv.warpAffine()函数的第三个参数是输出图像的大小,它应该是(宽度,高度)的形式。请记住,width=列数,height=行数。

窗口将如下图显示:

4.旋转

通过改变图像矩阵实现图像旋转角度θ

$$M=begin{bmatrix} cosTheta &-sinTheta sinTheta & cosTheta end{bmatrix}$$

但OpenCV提供可调旋转,即旋转中心可调,因此你可以在任何位置进行旋转。修正的变换矩阵由下式给出:

$$begin{bmatrix} alpha & beta & left ( 1-alpha right )cdot center.x-beta cdot center.y  -beta & alpha & beta cdot center.xleft ( 1-alpha right )cdot center.y end{bmatrix}$$

其中:

$$alpha = scalecdot cosTheta$$

$$beta = scalecdot sinTheta $$

为了找到这个转换矩阵,OpenCV提供了一个函数cv.getRotationMatrix2D。


以下示例将图像相对于中心旋转90度而不进行任何缩放。

img = cv.imread('messi5.jpg',0)

rows,cols = img.shape

M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)

dst = cv.warpAffine(img,M,(cols,rows))

窗口将如下图显示:

5.仿射变换

在仿射变换中,原始图像中的所有平行线仍将在输出图像中平行。为了找到变换矩阵,我们需要输入图像中的三个点及其在输出图像中的相应位置。然后cv.getAffineTransform将创建一个2x3矩阵,最后该矩阵将传递给cv.warpAffine。

参考以下示例,并查看我选择的点(以绿色标记):

img = cv.imread('drawing.png')

rows,cols,ch = img.shape

pts1 = np.float32([[50,50],[200,50],[50,200]])

pts2 = np.float32([[10,100],[200,50],[100,250]])



M = cv.getAffineTransform(pts1,pts2)

dst = cv.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()

窗口将如下图显示:

6.透视变换

对于透视变换,你需要一个3x3变换矩阵。即使在转换之后,直线仍将保持笔直。要找到此变换矩阵,输入图像上需要4个点,输出图像上需要相应的4个点。在这4个点中,其中任意3个不共线。然后可以通过函数cv.getPerspectiveTransform找到变换矩阵,将cv.warpPerspective应用于此3x3变换矩阵。

请参阅以下代码:

img = cv.imread('sudoku.png')
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 = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')

窗口将如下图显示:



打赏

未经允许不得转载:同乐学堂 » 6-OpenCV-改变色彩空间和几何变换

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

特别的技术,给特别的你!

联系QQ:1071235258QQ群:367203382
error: Sorry,暂时内容不可复制!