在这一章里,我们将学到如何去使用OpenCV来做一些有趣的图像几何变换。当我们学习之前,我们需要来安装OpenCV-Python的开发环境,同时安装一些重要的工具和程序包。
当你读完这章,你将学会:
- 如何安装OpenCV-Python的开发环境
- 如何读取、展示并储存图像
- 如何转换不同的颜色标准
- 如何应用一些变化如转换、变化、缩放等
- 如何将仿射、投影的变化应用于图像的有趣的几何变换
安装OpenCV-Pyhon的开发环境
下面让我们一起来看一下如何在不同的系统下安装OpenCV-Pyhon的开发环境。
Windows
为了获取OpenCV-Python的开发环境并且使它能够完美运行,我们需要做一些准备:
- 首先你要做的事安装Python:确定你的电脑上安装了2.7.x版本的Python。如果你没有,你可以从下面这个网址里面获取它:
https://www.python.org/downloads/windows/ - 然后安装NumPy:在Python中,NumPy是一个强大的数值计算程序包。在这个程序包里有很多强大的函数和方法。NumPy+OpenCV-Python的协作非常强大,因此我们会经常使用这个程序包。你可以在这个网址中安装最新的版本:
https://sourceforge.net/projects/numpy/files/NumPy/
将这些程序包安装到它们默认的路径上。安装好这些程序包之后,我们需要确定它们是否正常工作。打开Python的环境并输入:
>>> import numpy
如果正常运行,则不会抛出任何错误。做完这步之后,你需要下载最新的OpenCV版本,地址是:http://opencv.org/downloads.html(译者注:请下载OpenCV2.x.x的版本,而非下载 OpenCV3.x.x的。)
下载完之后安装,我们需要做一些如下的改变:
1.找到opencv/build/python/2.7
2.你将会看到一个cv2.pyd的文件。复制这个文件到
C:/Python27/lib/sitepackages这个路径下。
做完之后,让我们来确定一下OpenCV是否可以运行。打开python编辑器,输入下面的代码:
** >>> import cv2**
如果你没有看到任何错误,证明已经安装完毕,你就可以使用OpenCV-Python了。
Mac OSX
为了安装OpenCV-Python的开发环境,我们需要使用Homebrew。Homebrew是一个强大的程序包管理器,它将帮助你安装各种各样的库到你的系统上。如果你的电脑并没有安装Homebrew,打开终端,你可以运行下面的命令来安装:
$ ruby -e "$(curl -fsSL
https://raw.githubusercontent.com/Homebrew/install/master/install)"
即使OSX的系统已经集成了Python,我们还是要用Homebrew来安装Python以方便我们使用。这里的版本叫做brewed Python。安装完Homebrew之后,打开终端并输入:
$ brew install python
这个操作会自动的安装pip。pip是一个程序包管理工具专门用于安装Python的程序包,我们将用它安装其他的程序包。我们先来确定Python是否可以工作。打开你的终端并输入:
$ which python
你将在终端上看到/usr/locol/bin/python。(注,usr是你自己的电脑用户名称)这意味着你使用的是brewed Python而不是系统自带的。安装好brewed Python之后,下一步我们需要添加一个OpenCV所在的仓库,homebrew/science。打开终端并输入:
$ brew tap homebrew/sicence
确定NumPy是否安装,如果没有,输入:
$ pip install numpy
下一步安装OpenCV。在终端上输入:
$brew install opencv --with-tbb --with-opengl
现在OpenCV已经安装到了你的计算机上,你可以在
/usr/local/Cellar/opencv/2.4.9的路径上找到。(译者注:不一定是2.4.9,可能是更高级的版本)但是此时你还不能使用OpenCV,你需要将Python与安装包的路径匹配。在终端上运行下面的命令:
$ cd /Library/Python/2.7/site-packages/
$ ln -s /usr/local/Cellar/opencv/2.4.9/lib/python2.7/site-packages/cv.pycv.py
$ ln -s /usr/local/Cellar/opencv/2.4.9/lib/python2.7/site-packages/cv2.socv2.so
设置完成之后。我们来验证OpenCV是否可以正常运行。打开python的脚本编辑器并输入:
>>> import cv2
如果没有出现任何错误,你就可以使用OpenCV-Python了。
译者注:这种方法比较繁琐,我在csdn上提供了一种简便的方法,http://blog.csdn.net/edwardlee123/article/details/52037447,根据教程走完之后,在https://anaconda.org/ 这个网址里 ,输入opencv,找到匹配你系统的版本,点击进入,会发现一个命令行,复制命令行到终端中,就可以使用opencv了。这种方法对windows和linux同样适用。切记,不要下载opencv3版本。
Linux(for Ubuntu)
在开始之前,我们需要安装一些支持文件。让我们使用下面的安装包管理器安装它们:
$ sudo apt-get -y install libopencv-dev build-essential cmake libdc1394-22libdc1394-22-dev libjpeg-dev libpng12-dev libtiff4-dev libjasper-devlibavcodec-dev libavformat-dev libswscale-dev libxine-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev libtbb-dev libqt4-devlibmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-devlibvorbis-dev libxvidcore-dev x264 v4l-utils python-scipy python-pippython-virtualenv
安装好了这些支持文件后,我们需要建立OpenCV的 Python支持环境:
$ wget "https://github.com/Itseez/opencv/archive/2.4.9.tar.gz" -O./opencv/opencv.tar.gz
$ cd opencv
$ tar xvzf opencv.tar.gz -C .
$ mkdir release
$ cd release
$ sudo apt-get –y install make
$ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_PYTHON_SUPPORT=ON -D WITH_XINE=ON -D WITH_OPENGL=ON -D WITH_TBB=ON -DWITH_EIGEN=ON -D BUILD_EXAMPLES=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -DWITH_V4L=ON ../
$ make –j4
$ sudo make install
让我们确定是否已经安装成功,打开Python的脚本编辑器并输入:
>>>import cv2
如果没有错误,表明安装成功。
你可以在下面的网址中看到其他linux版本安装信息:
http://opencv.org/downloads.html
读取,展示和储存图像
现在让我们看看如何用OpenCV-Python加载一个图像。创建一个first_program.py的文件并在你喜欢的编辑器中打开,(译者用的是pycharm)。在工程文件夹下创建一个文件夹命名为images并确定文件夹中有个.jpg格式的图片。
做完之后,在python文件中写入如下代码:
import cv2
img = cv2.imread('./images/input.jpg')
cv2.imshow('Input Image',img)
cv2.waitkey()
运行该程序,你将会在一个新的窗口中看到这张图片。
图像颜色空间
在计算机视觉和图像处理中,颜色空间指的是组织颜色的具体方式。颜色空间实际上是两件事的组合:颜色模型和映射功能。我们想要颜色模型的原因是因为它帮助我们使用元组表示像素值。映射函数将颜色模型映射到可以表示的所有可能颜色的集合。
在我们的使用当中,有很多不同的颜色空间可以使用,常用的有RGB、YUV、HSV、Lab等等。不同的颜色空间有着不同的优点。在OpenCV,我们选择了解决现实问题的常用的几个颜色空间。接下来,我们会看这几个颜色空间,看看它们分别提供了什么信息:
- RGB:RGB可能是最流行的颜色空间了。它代表了红、绿、蓝。在这个颜色空间中,每种颜色都表示为红色、绿色、蓝色的加权组合。因此,每个像素值被表示为对应于红色、绿色和蓝色的三个数字的元组。红色、绿色和蓝色的值都在0~255之间。
- YUV:尽管RGB在许多应用上已经足够好了,但是在现实应用中,它还是有很多局限性。人们开始考虑不同的方法来分离从颜色信息中分离出强度信息。因此,他们提出了“YUV”颜色空间。Y表示亮度或强度,U / V通道表示颜色信息。这在许多应用中效果良好,因为人类视觉系统能很好的从信息中感知不同的强度信息。
- HSV:事实证明,即使YUV对于某些应用来说仍然不够好。事实证明,即使YUV对于某些应用来说仍然不够好。所以人们开始考虑人类如何看待颜色,并且想出了HSV颜色空间。HSV分别代表色调(hue)、饱和度(saturation)和值(value)。这是一个圆柱形系统,我们分离三种最主要的颜色属性,并使用不同的通道代表它们。这与人类视觉系统如何理解颜色密切相关并且使得我们在处理图像上有了很大的灵活性。
转化两种不同的颜色空间
考虑到所有的颜色空间,OpenCV提供了大约有190种的转换选项。如果想查看所有可用标志的列表,请到Python shell并输入以下内容:
>>> import cv2
>>> print [x for x in dir(cv2) if x.startswith('COLOR_')]
你将在OpenCV中看到可用于从一个颜色空间转换到另一个颜色空间的选项列表。我们几乎可以将任何颜色空间转换成任何其他颜色空间。首先,我们来看如何将一张彩色图转化为灰度图:
import cv2
img = cv2.imread('./images/input.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('Grayscale image', gray_img)
cv2.waitKey()
在这里,我们使用cvtColor函数在颜色空间之间进行转换。第一个参数是输入图像,第二个参数指定颜色空间转换。你可以使用下面的语句将图像转化成YUV颜色空间:
yuv_img = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
图像将如下图所示:
这看起来可能像原始图像的劣化版本,但实际上并不是如此。让我们分解其三个通道:
cv2.imshow('Y channel', yuv_img[:, :, 0])
cv2.imshow('U channel', yuv_img[:, :, 1])
cv2.imshow('V channel', yuv_img[:, :, 2])
cv2.waitKey()
由于yuv_img是一个numPy数组,我们可以通过分割三个通道进行分割。如果你使用yuv_img.shape函数查看其形状,你会看到它是一个三维数组,其大小事是NUM_ROWS x NUM_COLUMNS x NUM_CHANNELS。所以一旦你运行了前面的代码,你会看到三个不同的图像。Y通道如下所示:
Y通道基本上是一个灰度图。让我们来看U通道:
最后,让我们看一下V通道:
在这里我们可以看出,Y通道基本上就是一张灰度图。它代表了图像的亮度值或者说强度值。而U和V代表了颜色信息。
接下来用下列代码将图像转化为HSV,看看会发生什么:
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV image', hsv_img)
接下来,让我们分割通道:
cv2.imshow('H channel', hsv_img[:, :, 0])
cv2.imshow('S channel', hsv_img[:, :, 1])
cv2.imshow('V channel', hsv_img[:, :, 2])
cv2.waitKey()
运行上述代码之后,我们同样会看到三个图像:
首先是H通道:
接下来是S通道:
最后是V通道:
这些案例可以给出你一个基本的看法,如何使用OpenCV在颜色空间之间进行转换。你可以使用更多的颜色空间来观察图象外观。我们将在随后的章节中讨论相关的颜色空间。
图像变换
在本节中,我们将讨论如何转换图像。假设我们想在我们的参考框架内移动图像。这在计算机视觉术语中,被称为图像变换。接下来我们看如何去实现图像变换:
import cv2
import numpy as np
img = cv2.imread('images/input.jpg')
num_rows, num_cols = img.shape[:2]
translation_matrix = np.float32([ [1,0,70], [0,1,110] ])
img_translation = cv2.warpAffine(img, translation_matrix, (num_cols,
num_rows))
cv2.imshow('Translation', img_translation)
cv2.waitKey()
运行上述代码之后,你将看到如下所示:
要了解上述代码,我们需要了解变形的工作原理。变换过程基本上意味着我们需要通过更改X和Y坐标来移动图像。为此,我们需要建立一个如下所示的转换矩阵。
其中,tx和ty的值指的是X和Y的平移值,即图像向右移动X个单位,向下移动Y个单位。所以我们可以使用warpAffine这个函数创建了这样的矩阵来应用到我们的图像上。warpAffine中的第三个参数是指生成的图像中的行数和列数。由于行和列的尺寸与原始图像相同,因此得到的图像将被裁剪。原因是因为当我们应用变换矩阵时,输出中没有足够的空间。为了避免裁剪,我们可以这样做:
img_translation = cv2.warpAffine(img, translation_matrix, (num_cols + 70, num_rows + 110))
如果在我们的程序中替换相应的行,你将看到以下图像:
假设你想在更大的图像画面中间移动图像;我们可以通过执行以下操作来做这样的事情:
import cv2
import numpy as np
img = cv2.imread('images/input.jpg')
num_rows, num_cols = img.shape[:2]
translation_matrix = np.float32([ [1,0,70], [0,1,110] ])
img_translation = cv2.warpAffine(img, translation_matrix, (num_cols + 70,
num_rows + 110))
translation_matrix = np.float32([ [1,0,-30], [0,1,-50] ])
img_translation = cv2.warpAffine(img_translation, translation_matrix,
(num_cols + 70 + 30, num_rows + 110 + 50))
cv2.imshow('Translation', img_translation)
cv2.waitKey()
运行代码之后,将显示下述图像: