Python计算机视觉:第十章 OpenCV
第十章 OpenCV
這一章主要講述通過Python接口使用目前流行的計算機視覺編程庫OpenCV。OpenCV是一個C++庫,用于實時處理計算機視覺方面的問題。
10.1 OpenCV Python接口
OpenCV是一個C++庫,它涵蓋了很多計算機視覺領域的模塊。可以通過訪問[http://opencv.willowgarage.com/ documentation/python/index.html]。
OpenCV目前最新的版本是2.4.8。實際上,OpenCV有兩個Python接口,老版本的cv模塊使用OpenCV內置的數據類型,新版本的cv2模塊使用NumPy數組。對于新版本的模塊,可以通過下面方式導入:
import cv2而老版本的模塊則通過下面方式導入:
import cv2.cv在本章中,我們使用cv2模塊,譯者使用的OpenCV版本是2.4.6。
10.2 OpenCV基礎
OpenCV提供了讀取圖像和寫入圖像,矩陣操作以及數學庫函數。我們先來看看這些基本組件并學習怎樣使用它們。
10.2.1 讀取、寫入圖像
下面是一個簡短的載入圖像、打印尺寸、轉換格式及保存圖像為.png格斯的例子:
# -*- coding: utf-8 -*- import cv2# 讀入圖像 im = cv2.imread('../data/empire.jpg')# 打印圖像尺寸 h, w = im.shape[:2] print h, w# 保存原jpg格式的圖像為png格式圖像 cv2.imwrite('../images/ch10/ch10_P210_Reading-and-Writing-Images.png',im)運行上面代碼后,在ch10文件下保存有empire.jpg轉換成.png格式的圖片,即ch10P210Reading-and-Writing-Images.png,下面是轉換格式后保存的.png的圖像:函數imread()將圖像返回為一個標準的NumPy數組,如果你喜歡的話,你可以將該函數用于PIL圖像讀取的備選函數。函數imwrite()能夠根據文件后綴自動的進行格式轉換。
10.2.2 顏色空間
在OpenCV中,圖像不是用常規的RGB顏色通道來存儲的,它們用的是BGR順序。當讀取一幅圖像后,默認的是BGR,不過有很多轉換方式是可以利用的。顏色空間轉換可以用函數cvtColor()函數。比如,下面是一個轉換為灰度圖像的例子:
import cv2im = cv2.imread('../data/empire.jpg') # create a grayscale version gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)10.2.3 顯示圖像和結果
下面我們看一些用OpenCV進行圖像處理并用OpenCV繪圖及窗口管理功能顯示圖像后的結果的示例。
第一個例子是從文件中讀取一幅圖像,并創建積分圖像表示:
# -*- coding: utf-8 -*- import cv2 from pylab import *# 添加中文字體支持 from matplotlib.font_manager import FontProperties font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)# 讀入圖像 im = cv2.imread('../data/fisherman.jpg') # 轉換顏色空間 gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)# 顯示積分圖像 fig = plt.figure() subplot(121) plt.gray() imshow(gray) title(u'灰度圖', fontproperties=font) axis('off')# 計算積分圖像 intim = cv2.integral(gray) # 歸一化 intim = (255.0*intim) / intim.max()#顯示積分圖像 subplot(122) plt.gray() imshow(intim) title(u'積分圖', fontproperties=font) axis('off') show()# 用OpenCV顯示圖像 #cv2.imshow("Image", intim) #cv2.waitKey()# 用OpenCV保存積分圖像 #cv2.imwrite('../images/ch10/ch10_P211_Displaying-Images-and-Results-cv2.jpg',intim)# 保存figure中的灰度圖像和積分圖像 fig.savefig("../images/ch10/ch10_P211_Displaying-Images-and-Results.png")運行上面代碼,顯示如下結果,并在/images/ch10/目錄下生成一幅保存有灰度圖像和積分圖像的圖片:第二個例子從種子像素開始應用泛洪(漫水)填充:
# -*- coding: utf-8 -*- import cv2 import numpy from pylab import *# 添加中文字體支持 from matplotlib.font_manager import FontProperties font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)# 讀入圖像 filename = '../data/fisherman.jpg' im = cv2.imread(filename) # 轉換顏色空間 rgbIm = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)# 顯示原圖 fig = plt.figure() subplot(121) plt.gray() imshow(rgbIm) title(u'原圖', fontproperties=font) axis('off')# 獲取圖像尺寸 h, w = im.shape[:2] # 泛洪填充 diff = (6, 6, 6) mask = zeros((h+2, w+2), numpy.uint8) cv2.floodFill(im, mask, (10, 10), (255, 255, 0), diff, diff)# 顯示泛洪填充后的結果 subplot(122) imshow(im) title(u'泛洪填充', fontproperties=font) axis('off')show() #fig.savefig("../images/ch10/floodFill.png")# 在OpenCV窗口中顯示泛洪填充后的結果 # cv2.imshow('flood fill', im) # cv2.waitKey() # 保存結果 # cv2.imwrite('../images/ch10/floodFill.jpg',im)譯者使用的是matplotlib顯示泛洪填充后的結果,上面代碼底下的注釋部分是用OpenCV顯示泛洪填充的結果。如果你用OpenCV窗口顯示上面運行的結果,可以反注釋。下面是上面泛洪填充后的結果:作為最后一個例子,我們看一下提取圖像的SURF(加速穩健特征)特征。SURF是SIFT特征的一個快速版本。這里我們也會展示一些OpenCV繪制命令。
# -*- coding: utf-8 -*- import cv2 import numpy from pylab import *# 讀入圖像 im = cv2.imread('../data/empire.jpg') # 下采樣 im_lowres = cv2.pyrDown(im) # 轉化為灰度圖像 gray = cv2.cvtColor(im_lowres, cv2.COLOR_RGB2GRAY) # 檢測特征點 s = cv2.SURF() mask = numpy.uint8(ones(gray.shape)) keypoints = s.detect(gray, mask) # 顯示圖像及特征點 vis = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) for k in keypoints[::10]:cv2.circle(vis, (int(k.pt[0]), int(k.pt[1])), 2, (0, 255, 0), -1)cv2.circle(vis, (int(k.pt[0]), int(k.pt[1])), int(k.size), (0, 255, 0), 2) cv2.imshow('local descriptors', vis) cv2.waitKey()cv2.imwrite('../images/ch10/ch10_P261_Fig10-3.jpg',vis)上面代碼先讀入一幅圖像,用pyrDown下采樣,得到的一幅尺寸是原圖像尺寸一半的降采樣圖像,即im_lowres,然后將圖像轉換為灰度圖像,并將它傳遞給SURF關鍵點檢測對象。運行上面代碼,可得下面SURF特征點檢測結果:
10.3 視頻處理
單純利用Python處理視頻是比較困難的,因為要考慮到速度、編解碼器、攝像機、操作系統已經文件格式等問題。目前Python還沒有視頻處理庫。Python處理視頻的接口僅有的較好的就是OpenCV。在這一節,我們會展示一些對視頻進行處理的基本例子。
10.3.1 視頻輸入
OpenCV能夠很好地支持視頻的讀入。下面的例子展示了捕獲視頻幀,并在OpenCV窗口中顯示它們:
import cv2 # setup video capture cap = cv2.VideoCapture(0) while True:ret,im = cap.read()cv2.imshow('video test',im)key = cv2.waitKey(10)if key == 27:breakif key == ord(' '):cv2.imwrite('vid_result.jpg',im)上面VideoCapture從攝像頭或文件中捕獲視頻。這里我們給它傳遞了一個整數作為初始化參數,它實際是視頻設備的ID號,對于單個連著的攝像頭,其ID號為0。read()方法解碼并返回下一視頻幀。waitKey()函數等待用戶按下“Esc”(對應的ASCII碼為27)終止應用,或按“space”將當前幀保存起來。
我們將上面例子進行拓展,使其能夠在OpenCV窗口中對輸出的視頻進行模糊。對上面的例子進行稍微的修改便可實現該功能:
import cv2 # setup video capture cap = cv2.VideoCapture(0) # get frame, apply Gaussian smoothing, show result while True:ret,im = cap.read()blur = cv2.GaussianBlur(im,(0,0),10)cv2.imshow('camera blur',blur)if cv2.waitKey(10) == 27:break上面對每一幀圖像,將其傳給GaussianBlur()函數,該函數實現對圖像進行高斯濾波。在這個實例中,我們傳遞的是彩色圖像,每一個顏色通道可以分別對其進行模糊。該函數以一個濾波器大小元組及高斯函數的標準差作為輸入,如果濾波器大小設置為0,則它自動賦為標準差。運行上面的結果如下:
10.3.2 讀取視頻到NumPy數組
OpenCV可以從一個文件中讀取視頻幀序列,并將它們轉換成NumPy數組。下面給出了一個從攝像頭捕獲視頻,并將它們存儲在NumPy數組中的例子。
import cv2 from pylab import * # setup video capture cap = cv2.VideoCapture(0) frames = [] # get frame, store in array while True:ret,im = cap.read()cv2.imshow('video',im)frames.append(im)if cv2.waitKey(10) == 27:break frames = array(frames) # check the sizes print im.shape print frames.shape上面每一幀數組會被添加到列表的末尾直到捕獲終止。打印出的數組大小表示的幀數、高度、寬度、3。運行上面代碼打印出的結果為:
(480, 640, 3) (40, 480, 640, 3)這里,記錄了40幀。類似如這樣的視頻數據數組非常適合視頻處理,比兔計算視頻幀差異以及跟蹤。
10.4 跟蹤
跟蹤是對視頻幀序列中的物體進行跟蹤。
10.4.1 光流法
10.4.2 Lucas-Kanade算法
Lucas-Kanade算法原理這里略,具體可以參閱中譯本。
import lktrackimnames = ['../data/bt/bt.003.pgm', '../data/bt/bt.002.pgm', '../data/bt/bt.001.pgm', '../data/bt/bt.000.pgm'] # create tracker object lkt = lktrack.LKTracker(imnames) # detect in first frame, track in the remaining lkt.detect_points() lkt.draw() for i in range(len(imnames)-1):lkt.track_points()lkt.draw() import lktrack from pylab import * imnames = ['../data/viff/viff.000.ppm', '../data/viff/viff.001.ppm','../data/viff/viff.002.ppm', '../data/viff/viff.003.ppm', '../data/viff/viff.004.ppm'] # track using the LKTracker generator lkt = lktrack.LKTracker(imnames) for im,ft in lkt.track():print 'tracking %d features' % len(ft)# plot the tracks figure() imshow(im) for p in ft:plot(p[0],p[1],'bo') for t in lkt.tracks:plot([p[0] for p in t],[p[1] for p in t]) axis('off') show()
from: http://yongyuan.name/pcvwithpython/chapter10.html
總結
以上是生活随笔為你收集整理的Python计算机视觉:第十章 OpenCV的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python计算机视觉:第九章 图像分割
- 下一篇: matlab安装配置VLFeat库