一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

OpenCV3計(jì)算機(jī)視覺(jué)Python語(yǔ)言實(shí)現(xiàn)筆記(二)

 雪柳花明 2017-09-14

1. 圖像與原始字節(jié)之間的轉(zhuǎn)換

  從概念上講,一個(gè)字節(jié)能表示0到255的整數(shù)。目前,對(duì)于多有的實(shí)時(shí)圖像應(yīng)用而言,雖然有其他的表示形式,但一個(gè)像素通常由每個(gè)通道的一個(gè)字節(jié)表示。

  一個(gè)OpenCV圖像是.array類(lèi)型的二維或三維數(shù)組。8位的灰度圖像是一個(gè)含有字節(jié)值的二維數(shù)組。一個(gè)24位的BGR圖像是一個(gè)三維數(shù)組,它也包含了字節(jié)值。可使用表達(dá)式訪問(wèn)這些值,如image[0,0]或image[0,0,0]。第一個(gè)值代表像素的y坐標(biāo)啊或行,0表示頂部;第二個(gè)值是像素的x坐標(biāo)或列,0表示最左邊;第三個(gè)值(如果可用的話)表示顏色通道。如,對(duì)于一個(gè)左上角有白色像素的8位灰度圖像而言,image[0,0]的值為255. 對(duì)于一個(gè)左上角有藍(lán)色像素的24位BGR圖像而言,image[0,0]是[255,0,0]。

  可以用另外一個(gè)表示,如image[0,0]或image[0,0]=128,還可表示成image.item((0,0))或image.setitem((0,0),128)。對(duì)于單像素操作,第二種表示方式更有效。

  若一幅圖像的每個(gè)通道為8位,則可將其顯示轉(zhuǎn)換為標(biāo)準(zhǔn)的一維Python bytearray格式:

byteArray = bytearray(image)

  反之,bytearray含有恰當(dāng)順序的字節(jié),可以通過(guò)顯示轉(zhuǎn)換和重構(gòu),得到numpy.array形式的圖像:

 garyImage = numpy.array(garyByteArray ).reshape(height, width)

    bgrImage = numpy.array(bgrByteArray ).reshape(height, width, 3)

  下面介紹將含有隨機(jī)字節(jié)的bytearray轉(zhuǎn)換為灰度圖像和BGR圖像:

復(fù)制代碼
import cv2
import numpy as np
import os

# 創(chuàng)建一個(gè)120000個(gè)隨機(jī)字節(jié)的數(shù)組
randomByteArray = bytearray(os.urandom(120000))  #os.urandom(n) 返回n個(gè)隨機(jī)byte值的string,作為加密使用
flatNumpyArray = np.array(randomByteArray)

# 將數(shù)組轉(zhuǎn)換為400 x 300的灰度圖像
garyImage = flatNumpyArray.reshape(300, 400)
cv2.imwrite('randomGary.png', garyImage)

# 將數(shù)組轉(zhuǎn)換為400 x 300的彩色圖像
bgrImage = flatNumpyArray.reshape(100, 400, 3)
cv2.imwrite('randomColor.png', bgrImage)
復(fù)制代碼

  運(yùn)行該程序,將會(huì)在程序所在目錄中生成兩張灰度圖像(如下所示)。尺寸分別為400 x 100,400 x 400

  使用Python標(biāo)準(zhǔn)的os.urandom()函數(shù)可隨機(jī)生成原始字節(jié),隨后會(huì)把該字節(jié)轉(zhuǎn)換為NumPy數(shù)組。需要注意的是,諸如numpy.random.randint(0, 256, 120000).reshape(400, 300)語(yǔ)句也能直接(并且更高效地)隨機(jī)生成NumPy數(shù)組。使用os.urandom()函數(shù)的原因是該語(yǔ)句有助于展示原始字節(jié)的轉(zhuǎn)換。

2. 使用numpy.array訪問(wèn)圖像數(shù)據(jù)

  加載OpenCV圖像最簡(jiǎn)單的方式是使用imread()函數(shù),該函數(shù)會(huì)返回一幅圖像,這幅圖像是一個(gè)數(shù)組(根據(jù)imread()函數(shù)輸入?yún)?shù)的不同,該圖像可能是二維數(shù)組,也可能是三維數(shù)組)。

  y.array結(jié)構(gòu)針對(duì)數(shù)組操作有很好的優(yōu)化,它允許某些塊(bulk)操作,這些操作在通常的Python中不可用這些特定的.array操作在OpenCV的圖像處理中會(huì)很方便。利用numpy.array函數(shù)來(lái)轉(zhuǎn)換數(shù)組比用普通的Python數(shù)組轉(zhuǎn)換要快得多。

復(fù)制代碼
import cv2
import numpy as np

img = cv2.imread('flower.jpg')
img[0,0] = [255, 255, 255]
cv2.imshow('my image', img)
cv2.waitKey()
復(fù)制代碼

  在圖像左上方會(huì)出現(xiàn)一個(gè)白點(diǎn)。

  假設(shè)想要改變一個(gè)特定像素的藍(lán)色值,numpy.array提供了item()方法。該函數(shù)有3個(gè)參數(shù):x(或左)位置,y(或頂部)位置以及(x,y)位置的數(shù)組索引(注意,在BGR圖像中,某一位置的數(shù)據(jù)是按B,G,R的順序保存的三元數(shù)組),該函數(shù)能返回索引函數(shù)的值。另一個(gè)方法是通過(guò)itemset()函數(shù)可設(shè)置指定像素在指定通道的值(itemset()有兩個(gè)參數(shù):一個(gè)三元組(x,y和索引)和要設(shè)定的值)。如下例子將坐標(biāo)(150,120)的當(dāng)前藍(lán)色值127變?yōu)?55

復(fù)制代碼
import cv2
import numpy as np

img = cv2.imread('flower.jpg')
print(img.item(150, 120, 0))  # 打印當(dāng)前坐標(biāo)點(diǎn)的藍(lán)色值
img.itemset((150, 120, 0), 255)
print(img.item(150, 120, 0))
復(fù)制代碼

  建議使用內(nèi)置的濾波器和方法來(lái)處理整個(gè)圖像,上述方法只適合于處理特定的小區(qū)域。

  下面介紹操作通道:將指定通道(B,G,R)的所有值置為0.(注:通過(guò)循環(huán)來(lái)處理Python數(shù)組的效率非常低,應(yīng)該盡量避免這樣的操作。使用數(shù)組索引可以高效地操作像素。像素操作是一個(gè)高代價(jià)的低效操作,特別是在視頻數(shù)據(jù)處理時(shí),會(huì)發(fā)現(xiàn)要等很久才能得到結(jié)果??捎盟饕?indexing)來(lái)解決該問(wèn)題)

  以下代碼可將圖像所有的G(綠色)值設(shè)為0

復(fù)制代碼
import cv2
import numpy as np

img = cv2.imread('flower.jpg')
img[:, :, 1] = 0
cv2.imshow('my image', img)
cv2.waitKey()
復(fù)制代碼

  運(yùn)行結(jié)果為:

  通過(guò)NumPy數(shù)組的索引訪問(wèn)原始像素,還可設(shè)定感興趣區(qū)域(Region Of Interest, ROI)。一旦設(shè)定了該區(qū)域,就可以執(zhí)行許多操作,例如,將該區(qū)域與變量綁定,然后設(shè)定第二個(gè)區(qū)域,并將第一個(gè)區(qū)域的值分配給第二個(gè)區(qū)域(將圖像的一部分拷貝到該圖像的另一個(gè)位置):

復(fù)制代碼
import cv2
import numpy as np

img = cv2.imread('flower.jpg')
roi = img[0:100, 0:100]
img[100:200, 100:200] = roi # 此處需考慮所用圖像的尺寸,不能超過(guò),并確保兩個(gè)區(qū)域的大小一樣
cv2.imshow('my image', img)
cv2.waitKey()
復(fù)制代碼

運(yùn)行結(jié)果為:

  此外,還可使用numpy.array來(lái)獲得圖像其他屬性。

  shape:NumPy返回包含寬度、高度和通道數(shù)(如果圖像是彩色的)數(shù)組,這在調(diào)試圖像類(lèi)型時(shí)很有用;如果圖像是單色或灰度的,將不包含通道值;

  size:該屬性是指圖像像素的大??;

  datatype:該屬性會(huì)得到圖像的數(shù)據(jù)類(lèi)型(通常為一個(gè)無(wú)符號(hào)整數(shù)類(lèi)型的變量和該類(lèi)型占的位數(shù),比如unit8類(lèi)型)

復(fù)制代碼
import cv2
import numpy as np

img = cv2.imread('flower.jpg')
print(img.shape)
print(img.size)
print(img.dtype)
復(fù)制代碼

運(yùn)行結(jié)果為:

(220, 252, 3)
166320
uint8

3.視頻文件的讀/寫(xiě)

  OpenCV提供了VideoCapture類(lèi)和VideoWriter類(lèi)來(lái)支持各種格式的視頻文件。支持的格式類(lèi)型會(huì)因系統(tǒng)的不同而變化,但應(yīng)該都支持AVI格式。在到達(dá)視頻文件末尾之前,VideoCapture類(lèi)可通過(guò)read()函數(shù)來(lái)獲取新的幀,每幀都是一幅基于BGR格式的圖像。

  可將一幅圖像傳遞給VideoWriter類(lèi)的write()函數(shù),該函數(shù)會(huì)將這幅圖像加到VideoWriter類(lèi)所指向的文件中。

  如下示例讀取AVI文件的幀,并采用YUV顏色編碼將其寫(xiě)入另一幀中:

復(fù)制代碼
import cv2
videoCapture = cv2.VideoCapture('myvideo.avi')
fps = videoCapture.get(cv2.CAP_PROP_FPS)
size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
videoWriter = cv2.VideoWriter('MyOutputVid.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)
success, frame = videoCapture.read()
while success:  # 循環(huán)直到所有幀結(jié)束
    videoWriter.write(frame)
    success, frame = videoCapture.read()
復(fù)制代碼

  要特別注意:必須要為VideoWriter類(lèi)的構(gòu)造函數(shù)指定視頻文件名,這個(gè)文件名對(duì)應(yīng)的文件若存在,會(huì)被覆蓋。也必須指定視頻編解碼器。編解碼器的可用性根據(jù)系統(tǒng)不同而不同。下面是一些常用選項(xiàng):

  cv2.VideoWriter_force('I', '4', '2', '0'):該選項(xiàng)是一個(gè)未壓縮的YUV顏色編碼,是4:2:0色度子采樣。這種編碼有很好的兼容性,但會(huì)產(chǎn)生較大文件,文件擴(kuò)展名為.avi。

  cv2.VideoWriter_force('P', 'I', 'M', '1'):該選項(xiàng)是MPEG-1編碼類(lèi)型,文件擴(kuò)展名為.avi。

  cv2.VideoWriter_force('X', 'V', 'I', 'D'):該選項(xiàng)是MPEG-4編碼類(lèi)型,如果希望得到的視頻大小為平均值,推薦使用此選項(xiàng),文件擴(kuò)展名為.avi。

  cv2.VideoWriter_force('T', 'H', 'E', 'O'):該選項(xiàng)是Ogg Vorbis,文件擴(kuò)展名應(yīng)為.ogv。

  cv2.VideoWriter_force('F', 'L', 'V', '1'):該選項(xiàng)是一個(gè)Flash視頻,文件擴(kuò)展名應(yīng)為.flv。

  幀速率和幀大小也必須要指定,因?yàn)樾枰獜牧硪粋€(gè)視頻文件復(fù)制視頻幀,這些屬性可以通過(guò)VideoCapture類(lèi)的get()函數(shù)得到。

 4. 捕獲攝像頭的幀

  VideoCapture類(lèi)可以獲得攝像頭的幀流。但對(duì)攝像頭而言,通常不是用視頻的文件名來(lái)構(gòu)造VideoCapture類(lèi),而是需要傳遞攝像頭的設(shè)備索引(device index)。

  下面的例子會(huì)捕獲攝像頭10秒的視頻信息,并將其寫(xiě)入一個(gè)AVI文件中:

復(fù)制代碼
import cv2
cameraCapture = cv2.VideoCapture(0)
fps = 30
size = (int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
videoWriter = cv2.VideoWriter('MyOutputVid.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), fps, size)
success, frame = cameraCapture.read()
numFramesRemaining = 10 * fps - 1
while success and numFramesRemaining > 0:
    videoWriter.write(frame)
    success, frame = cameraCapture.read()
    numFramesRemaining -= 1
cameraCapture.release()
復(fù)制代碼

  然而,VideoCapture類(lèi)的get()方法不能反悔攝像頭幀速率的準(zhǔn)確值,它總是返回0。

  為了針對(duì)攝像頭創(chuàng)建合適的VideoWriter類(lèi),要么對(duì)幀速率做出假設(shè),要么使用計(jì)時(shí)器來(lái)測(cè)量。攝像頭的數(shù)量和順序由系統(tǒng)決定,但OpenCV沒(méi)有提供任何查詢攝像頭數(shù)量和屬性的方法。如果使用無(wú)效索引構(gòu)造了VideoCapture類(lèi),就不會(huì)得到幀,VideoCapture的read()函數(shù)會(huì)返回(false, None)。為了不讓read()函數(shù)從沒(méi)有正確打開(kāi)的VideoCapture類(lèi)中獲取數(shù)據(jù),可在執(zhí)行該函數(shù)之后使用VideoCapture.isOpened方法做一個(gè)判斷,該方法返回一個(gè)Boolean值。

  當(dāng)需要同步一組攝像頭或一個(gè)多頭攝像頭(例如立體攝像頭或Kinect)時(shí),read()方法就不再適合了,可用grab()和retrive()方法代替它。對(duì)于一組攝像頭,可以使用以下代碼:

success0 = cameraCapture0.grab()
success1 = cameraCapture1.grab()
if success0 and success1:
    frame0 = cameraCapture0.retrive()
    frame1 = cameraCapture1.retrive()

5. 在窗口顯示圖像

  用imshow()函數(shù)實(shí)現(xiàn)顯示圖像的操作。imshow()函數(shù)有兩個(gè)參數(shù):顯示圖像的幀名字以及要顯示的圖像本身。

import cv2
import numpy as np
img = cv2.imread('flower.jpg')
cv2.imshow('my image', img)
cv2.waitKey()
cv2.destroyAllWindows()   # 釋放由OpenCV創(chuàng)建的所有窗口

6. 在窗口顯示攝像頭幀

  OpenCV的namedWindow()、imshow()和DestoryWindow()函數(shù)允許指定窗口名來(lái)創(chuàng)建、顯示和銷(xiāo)毀(destroy)窗口。此外,任何窗口都可以通過(guò)waitKey()函數(shù)來(lái)獲取鍵盤(pán)輸入,通過(guò)setMouseCallback()函數(shù)來(lái)獲取鼠標(biāo)輸入。以下代碼可實(shí)時(shí)顯示攝像頭幀:

復(fù)制代碼
import cv2
clicked = False
def onMouse(event, x, y, flags, param):
    global clicked
    if event == cv2.EVENT_LBUTTONUP:
        clicked = True

cameraCapture = cv2.VideoCapture(0)
cv2.namedWindow('MyWindow')
cv2.setMouseCallback('MyWindow', onMouse)

print('showing camera feed. Click window or press any key to stop.')
success, frame = cameraCapture.read()
while success and cv2.waitKey(1) == -1 and not clicked:
    cv2.imshow('MyWindow', frame)
    success, frame = cameraCapture.read()
cv2.destroyWindow('MyWindow')
cameraCapture.release()
復(fù)制代碼

  waitKey()的參數(shù)為等待鍵盤(pán)觸發(fā)的時(shí)間,單位為毫秒,其返回值為-1(表示沒(méi)有鍵被按下)或ASCII碼。另外,Python提供了一個(gè)標(biāo)準(zhǔn)函數(shù)ord(),該函數(shù)可以將字符轉(zhuǎn)換為ASCII碼。(注:在一些系統(tǒng)中,waitKey()的返回值可能比ASCII碼的值更大(在Linux系統(tǒng)中,如果OpenCV使用GTK作為后端的GUI庫(kù),就會(huì)出現(xiàn)bug),在所有系統(tǒng)中,可以通過(guò)讀取返回值的最后一個(gè)字節(jié)來(lái)保證肢體去ASCII碼,代碼為:

keycode = cv2.waitkey(1)

if keycode != -1:

  keycode &= 0xff )

  OpenCV的窗口函數(shù)和waitKey()函數(shù)相互依賴。OpenCV的窗口只有在調(diào)用waitKey()函數(shù)時(shí)才會(huì)更新,waitKey()函數(shù)只有在OpenCV窗口成為活動(dòng)窗口時(shí),才能捕獲輸入信息。

  鼠標(biāo)回調(diào)函數(shù)setMouseCallback()有5個(gè)參數(shù),param是可選參數(shù),它是setMouseCallback()函數(shù)的第三個(gè)參數(shù),默認(rèn)情況下,該參數(shù)是0.回調(diào)時(shí)間參數(shù)可以取如下的值,它們分別對(duì)應(yīng)不同的鼠標(biāo)事件。

cv2.EVENT_MOUSEMOVE:該事件對(duì)應(yīng)鼠標(biāo)移動(dòng)    
cv2.EVENT_LBUTTONDOWN:該事件對(duì)應(yīng)鼠標(biāo)左鍵按下
cv2.EVENT_RBUTTONDOWN:該事件對(duì)應(yīng)鼠標(biāo)右鍵按下
cv2.EVENT_MBUTTONDOWN:該事件對(duì)應(yīng)鼠標(biāo)中間鍵按下
cv2.EVENT_LBUTTONUP:該事件對(duì)應(yīng)鼠標(biāo)左鍵松開(kāi)
cv2.EVENT_RBUTTONUP:該事件對(duì)應(yīng)鼠標(biāo)右鍵松開(kāi)
cv2.EVENT_MBUTTONUP:該事件對(duì)應(yīng)鼠標(biāo)中間鍵松開(kāi)
cv2.EVENT_LBUTTONDBLCLK:該事件對(duì)應(yīng)雙擊鼠標(biāo)左鍵
cv2.EVENT_RBUTTONDBLCLK:該事件對(duì)應(yīng)雙擊鼠標(biāo)右鍵
cv2.EVENT_MBUTTONDBLCLK:該事件隨影雙擊鼠標(biāo)中間鍵

  鼠標(biāo)回調(diào)的標(biāo)志參數(shù)可能是以下事件的按位組合:

cv2.EVENT_FLAG_LBUTTON:該事件對(duì)應(yīng)按下鼠標(biāo)左鍵
cv2.EVENT_FLAG_RBUTTON:該事件對(duì)應(yīng)按下鼠標(biāo)右鍵
cv2.EVENT_FLAG_MBUTTON:該事件對(duì)應(yīng)按下鼠標(biāo)中間鍵
cv2.EVENT_FLAG_CTRLKEY:該事件對(duì)應(yīng)按下Ctrl鍵
cv2.EVENT_FLAG_SHIFTKEY:該事件對(duì)應(yīng)按下Shift鍵
cv2.EVENT_FLAG_ALTKEY:該事件對(duì)應(yīng)按下Alt鍵

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多

    视频一区日韩经典中文字幕| 中文字幕亚洲在线一区| 欧美人妻盗摄日韩偷拍| 欧美国产日韩在线综合| 激情三级在线观看视频| 国产欧美日韩精品一区二区| 冬爱琴音一区二区中文字幕| 国产午夜福利一区二区| 99福利一区二区视频| 国产丝袜女优一区二区三区| 婷婷亚洲综合五月天麻豆 | 91日韩欧美中文字幕| 国产欧美日产中文一区| 亚洲中文字幕在线视频频道| 出差被公高潮久久中文字幕| 国产成人午夜av一区二区| 国产欧美日韩一级小黄片| 蜜臀人妻一区二区三区| 九九热视频网在线观看| 尹人大香蕉中文在线播放| 国内外激情免费在线视频| 在线日韩中文字幕一区| 精品推荐久久久国产av| 欧美日韩黑人免费观看| 亚洲一区二区三区三州| 91欧美日韩国产在线观看| 综合久综合久综合久久| 久久99午夜福利视频| 99国产高清不卡视频| 欧美亚洲91在线视频| 亚洲丁香婷婷久久一区| 午夜福利大片亚洲一区| 国产不卡最新在线视频| 免费午夜福利不卡片在线 视频| 少妇福利视频一区二区| 久久综合狠狠综合久久综合| 欧美日韩在线观看自拍| 黄色三级日本在线观看| 日韩午夜福利高清在线观看| 亚洲夫妻性生活免费视频| 欧洲日韩精品一区二区三区|