在這一章里,我們將學到如何去使用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()
運行代碼之后,將顯示下述圖像: