在這一章里赖草,我們將學(xué)到如何去使用OpenCV來做一些有趣的圖像幾何變換滴某。當(dāng)我們學(xué)習(xí)之前午乓,我們需要來安裝OpenCV-Python的開發(fā)環(huán)境站宗,同時(shí)安裝一些重要的工具和程序包。
當(dāng)你讀完這章益愈,你將學(xué)會(huì):
- 如何安裝OpenCV-Python的開發(fā)環(huán)境
- 如何讀取梢灭、展示并儲(chǔ)存圖像
- 如何轉(zhuǎn)換不同的顏色標(biāo)準(zhǔn)
- 如何應(yīng)用一些變化如轉(zhuǎn)換夷家、變化、縮放等
- 如何將仿射敏释、投影的變化應(yīng)用于圖像的有趣的幾何變換
安裝OpenCV-Pyhon的開發(fā)環(huán)境
下面讓我們一起來看一下如何在不同的系統(tǒng)下安裝OpenCV-Pyhon的開發(fā)環(huán)境库快。
Windows
為了獲取OpenCV-Python的開發(fā)環(huán)境并且使它能夠完美運(yùn)行,我們需要做一些準(zhǔn)備:
- 首先你要做的事安裝Python:確定你的電腦上安裝了2.7.x版本的Python钥顽。如果你沒有义屏,你可以從下面這個(gè)網(wǎng)址里面獲取它:
https://www.python.org/downloads/windows/ - 然后安裝NumPy:在Python中,NumPy是一個(gè)強(qiáng)大的數(shù)值計(jì)算程序包蜂大。在這個(gè)程序包里有很多強(qiáng)大的函數(shù)和方法湿蛔。NumPy+OpenCV-Python的協(xié)作非常強(qiáng)大,因此我們會(huì)經(jīng)常使用這個(gè)程序包县爬。你可以在這個(gè)網(wǎng)址中安裝最新的版本:
https://sourceforge.net/projects/numpy/files/NumPy/
將這些程序包安裝到它們默認(rèn)的路徑上。安裝好這些程序包之后添谊,我們需要確定它們是否正常工作财喳。打開Python的環(huán)境并輸入:
>>> import numpy
如果正常運(yùn)行,則不會(huì)拋出任何錯(cuò)誤斩狱。做完這步之后耳高,你需要下載最新的OpenCV版本,地址是:http://opencv.org/downloads.html(譯者注:請(qǐng)下載OpenCV2.x.x的版本所踊,而非下載 OpenCV3.x.x的泌枪。)
下載完之后安裝,我們需要做一些如下的改變:
1.找到opencv/build/python/2.7
2.你將會(huì)看到一個(gè)cv2.pyd的文件秕岛。復(fù)制這個(gè)文件到
C:/Python27/lib/sitepackages這個(gè)路徑下碌燕。
做完之后,讓我們來確定一下OpenCV是否可以運(yùn)行继薛。打開python編輯器修壕,輸入下面的代碼:
** >>> import cv2**
如果你沒有看到任何錯(cuò)誤,證明已經(jīng)安裝完畢遏考,你就可以使用OpenCV-Python了慈鸠。
Mac OSX
為了安裝OpenCV-Python的開發(fā)環(huán)境,我們需要使用Homebrew灌具。Homebrew是一個(gè)強(qiáng)大的程序包管理器青团,它將幫助你安裝各種各樣的庫到你的系統(tǒng)上。如果你的電腦并沒有安裝Homebrew咖楣,打開終端督笆,你可以運(yùn)行下面的命令來安裝:
$ ruby -e "$(curl -fsSL
https://raw.githubusercontent.com/Homebrew/install/master/install)"
即使OSX的系統(tǒng)已經(jīng)集成了Python,我們還是要用Homebrew來安裝Python以方便我們使用截歉。這里的版本叫做brewed Python胖腾。安裝完Homebrew之后,打開終端并輸入:
$ brew install python
這個(gè)操作會(huì)自動(dòng)的安裝pip。pip是一個(gè)程序包管理工具專門用于安裝Python的程序包咸作,我們將用它安裝其他的程序包锨阿。我們先來確定Python是否可以工作。打開你的終端并輸入:
$ which python
你將在終端上看到/usr/locol/bin/python记罚。(注墅诡,usr是你自己的電腦用戶名稱)這意味著你使用的是brewed Python而不是系統(tǒng)自帶的。安裝好brewed Python之后桐智,下一步我們需要添加一個(gè)OpenCV所在的倉庫末早,homebrew/science。打開終端并輸入:
$ brew tap homebrew/sicence
確定NumPy是否安裝说庭,如果沒有然磷,輸入:
$ pip install numpy
下一步安裝OpenCV。在終端上輸入:
$brew install opencv --with-tbb --with-opengl
現(xiàn)在OpenCV已經(jīng)安裝到了你的計(jì)算機(jī)上刊驴,你可以在
/usr/local/Cellar/opencv/2.4.9的路徑上找到姿搜。(譯者注:不一定是2.4.9,可能是更高級(jí)的版本)但是此時(shí)你還不能使用OpenCV捆憎,你需要將Python與安裝包的路徑匹配舅柜。在終端上運(yùn)行下面的命令:
$ 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
設(shè)置完成之后。我們來驗(yàn)證OpenCV是否可以正常運(yùn)行躲惰。打開python的腳本編輯器并輸入:
>>> import cv2
如果沒有出現(xiàn)任何錯(cuò)誤致份,你就可以使用OpenCV-Python了。
譯者注:這種方法比較繁瑣础拨,我在csdn上提供了一種簡便的方法氮块,http://blog.csdn.net/edwardlee123/article/details/52037447,根據(jù)教程走完之后,在https://anaconda.org/ 這個(gè)網(wǎng)址里 诡宗,輸入opencv雇锡,找到匹配你系統(tǒng)的版本,點(diǎn)擊進(jìn)入僚焦,會(huì)發(fā)現(xiàn)一個(gè)命令行锰提,復(fù)制命令行到終端中,就可以使用opencv了芳悲。這種方法對(duì)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支持環(huán)境:
$ 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
讓我們確定是否已經(jīng)安裝成功融蹂,打開Python的腳本編輯器并輸入:
>>>import cv2
如果沒有錯(cuò)誤旺订,表明安裝成功。
你可以在下面的網(wǎng)址中看到其他linux版本安裝信息:
http://opencv.org/downloads.html
讀取超燃,展示和儲(chǔ)存圖像
現(xiàn)在讓我們看看如何用OpenCV-Python加載一個(gè)圖像区拳。創(chuàng)建一個(gè)first_program.py的文件并在你喜歡的編輯器中打開,(譯者用的是pycharm)意乓。在工程文件夾下創(chuàng)建一個(gè)文件夾命名為images并確定文件夾中有個(gè).jpg格式的圖片樱调。
做完之后,在python文件中寫入如下代碼:
import cv2
img = cv2.imread('./images/input.jpg')
cv2.imshow('Input Image',img)
cv2.waitkey()
運(yùn)行該程序届良,你將會(huì)在一個(gè)新的窗口中看到這張圖片笆凌。
圖像顏色空間
在計(jì)算機(jī)視覺和圖像處理中,顏色空間指的是組織顏色的具體方式士葫。顏色空間實(shí)際上是兩件事的組合:顏色模型和映射功能乞而。我們想要顏色模型的原因是因?yàn)樗鼛椭覀兪褂迷M表示像素值。映射函數(shù)將顏色模型映射到可以表示的所有可能顏色的集合慢显。
在我們的使用當(dāng)中晦闰,有很多不同的顏色空間可以使用,常用的有RGB鳍怨、YUV、HSV跪妥、Lab等等鞋喇。不同的顏色空間有著不同的優(yōu)點(diǎn)。在OpenCV眉撵,我們選擇了解決現(xiàn)實(shí)問題的常用的幾個(gè)顏色空間侦香。接下來,我們會(huì)看這幾個(gè)顏色空間纽疟,看看它們分別提供了什么信息:
- RGB:RGB可能是最流行的顏色空間了罐韩。它代表了紅、綠污朽、藍(lán)散吵。在這個(gè)顏色空間中,每種顏色都表示為紅色蟆肆、綠色矾睦、藍(lán)色的加權(quán)組合。因此炎功,每個(gè)像素值被表示為對(duì)應(yīng)于紅色枚冗、綠色和藍(lán)色的三個(gè)數(shù)字的元組。紅色蛇损、綠色和藍(lán)色的值都在0~255之間赁温。
- YUV:盡管RGB在許多應(yīng)用上已經(jīng)足夠好了坛怪,但是在現(xiàn)實(shí)應(yīng)用中,它還是有很多局限性股囊。人們開始考慮不同的方法來分離從顏色信息中分離出強(qiáng)度信息袜匿。因此,他們提出了“YUV”顏色空間毁涉。Y表示亮度或強(qiáng)度沉帮,U / V通道表示顏色信息。這在許多應(yīng)用中效果良好贫堰,因?yàn)槿祟愐曈X系統(tǒng)能很好的從信息中感知不同的強(qiáng)度信息穆壕。
- HSV:事實(shí)證明,即使YUV對(duì)于某些應(yīng)用來說仍然不夠好其屏。事實(shí)證明喇勋,即使YUV對(duì)于某些應(yīng)用來說仍然不夠好。所以人們開始考慮人類如何看待顏色偎行,并且想出了HSV顏色空間川背。HSV分別代表色調(diào)(hue)、飽和度(saturation)和值(value)蛤袒。這是一個(gè)圓柱形系統(tǒng)熄云,我們分離三種最主要的顏色屬性,并使用不同的通道代表它們妙真。這與人類視覺系統(tǒng)如何理解顏色密切相關(guān)并且使得我們?cè)谔幚韴D像上有了很大的靈活性缴允。
轉(zhuǎn)化兩種不同的顏色空間
考慮到所有的顏色空間,OpenCV提供了大約有190種的轉(zhuǎn)換選項(xiàng)珍德。如果想查看所有可用標(biāo)志的列表练般,請(qǐng)到Python shell并輸入以下內(nèi)容:
>>> import cv2
>>> print [x for x in dir(cv2) if x.startswith('COLOR_')]
你將在OpenCV中看到可用于從一個(gè)顏色空間轉(zhuǎn)換到另一個(gè)顏色空間的選項(xiàng)列表。我們幾乎可以將任何顏色空間轉(zhuǎn)換成任何其他顏色空間锈候。首先薄料,我們來看如何將一張彩色圖轉(zhuǎn)化為灰度圖:
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函數(shù)在顏色空間之間進(jìn)行轉(zhuǎn)換泵琳。第一個(gè)參數(shù)是輸入圖像摄职,第二個(gè)參數(shù)指定顏色空間轉(zhuǎn)換。你可以使用下面的語句將圖像轉(zhuǎn)化成YUV顏色空間:
yuv_img = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
圖像將如下圖所示:
這看起來可能像原始圖像的劣化版本获列,但實(shí)際上并不是如此琳钉。讓我們分解其三個(gè)通道:
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是一個(gè)numPy數(shù)組,我們可以通過分割三個(gè)通道進(jìn)行分割蛛倦。如果你使用yuv_img.shape函數(shù)查看其形狀歌懒,你會(huì)看到它是一個(gè)三維數(shù)組,其大小事是NUM_ROWS x NUM_COLUMNS x NUM_CHANNELS溯壶。所以一旦你運(yùn)行了前面的代碼及皂,你會(huì)看到三個(gè)不同的圖像甫男。Y通道如下所示:
Y通道基本上是一個(gè)灰度圖。讓我們來看U通道:
最后验烧,讓我們看一下V通道:
在這里我們可以看出板驳,Y通道基本上就是一張灰度圖。它代表了圖像的亮度值或者說強(qiáng)度值碍拆。而U和V代表了顏色信息若治。
接下來用下列代碼將圖像轉(zhuǎn)化為HSV,看看會(huì)發(fā)生什么:
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()
運(yùn)行上述代碼之后端幼,我們同樣會(huì)看到三個(gè)圖像:
首先是H通道:
接下來是S通道:
最后是V通道:
這些案例可以給出你一個(gè)基本的看法,如何使用OpenCV在顏色空間之間進(jìn)行轉(zhuǎn)換弧满。你可以使用更多的顏色空間來觀察圖象外觀婆跑。我們將在隨后的章節(jié)中討論相關(guān)的顏色空間。
圖像變換
在本節(jié)中庭呜,我們將討論如何轉(zhuǎn)換圖像滑进。假設(shè)我們想在我們的參考框架內(nèi)移動(dòng)圖像。這在計(jì)算機(jī)視覺術(shù)語中募谎,被稱為圖像變換扶关。接下來我們看如何去實(shí)現(xiàn)圖像變換:
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()
運(yùn)行上述代碼之后,你將看到如下所示:
要了解上述代碼数冬,我們需要了解變形的工作原理节槐。變換過程基本上意味著我們需要通過更改X和Y坐標(biāo)來移動(dòng)圖像。為此吉执,我們需要建立一個(gè)如下所示的轉(zhuǎn)換矩陣。
其中地来,tx和ty的值指的是X和Y的平移值戳玫,即圖像向右移動(dòng)X個(gè)單位,向下移動(dòng)Y個(gè)單位未斑。所以我們可以使用warpAffine這個(gè)函數(shù)創(chuàng)建了這樣的矩陣來應(yīng)用到我們的圖像上咕宿。warpAffine中的第三個(gè)參數(shù)是指生成的圖像中的行數(shù)和列數(shù)。由于行和列的尺寸與原始圖像相同蜡秽,因此得到的圖像將被裁剪府阀。原因是因?yàn)楫?dāng)我們應(yīng)用變換矩陣時(shí),輸出中沒有足夠的空間芽突。為了避免裁剪试浙,我們可以這樣做:
img_translation = cv2.warpAffine(img, translation_matrix, (num_cols + 70, num_rows + 110))
如果在我們的程序中替換相應(yīng)的行,你將看到以下圖像:
假設(shè)你想在更大的圖像畫面中間移動(dòng)圖像寞蚌;我們可以通過執(zhí)行以下操作來做這樣的事情:
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()
運(yùn)行代碼之后田巴,將顯示下述圖像: