opencv 實(shí)踐入門(mén)2 - 如何利用 VideoCapture截取視頻中的圖像

我只是一名搬磚工削饵,無(wú)意侵犯各位大佬知識(shí)產(chǎn)權(quán)生棍。
最近因項(xiàng)目組需要捧杉,開(kāi)始學(xué)圖像處理
所以記錄一下這個(gè)過(guò)程以及經(jīng)驗(yàn)呈宇,希望能幫到大家

學(xué)習(xí)參考資料:

  1. 《圖像處理的數(shù)學(xué)修養(yǎng)》
  2. github 上的OpenCV-Python-Tutorial

若想系統(tǒng)地學(xué)習(xí),麻煩移步到 github或買(mǎi)書(shū)啃一下


這部分主要講兩個(gè)函數(shù)

  1. cv2.VideoCapture 創(chuàng)建視頻對(duì)象扒俯,負(fù)責(zé)獲取視頻內(nèi)容
  2. cv2.VideoWriter() 創(chuàng)建視頻寫(xiě)入對(duì)象奶卓,用來(lái)錄制/保存視頻

其他

  • cv2.cvtColor() 將 BGR 彩色圖片轉(zhuǎn)為 灰度圖片
  • imwrite() 保存圖片
  • cv2.VideoCapture().isOpened() 檢測(cè)視頻讀取狀態(tài)是否正常
  • cv2.VideoCapture().read() 獲取視頻某一幀,返回兩個(gè)值撼玄,第一個(gè)是布爾值夺姑,表示“這一幀”是否獲取正確;第二個(gè)值是這一幀的內(nèi)容互纯,是一個(gè)矩陣瑟幕。

接下來(lái)看例子

cv2.VideoCapture()

  1. 如果傳的參數(shù)是數(shù)字,表示使用攝像頭留潦。如 cv2.VideoCapture(0)只盹,表示使用計(jì)算機(jī)第一個(gè)攝像頭。
  2. 如果傳的是一個(gè)視頻的地址兔院,則表示讀取本地視頻殖卑。這里我只用第二種,給一個(gè)視頻的絕對(duì)路徑并讀取它

比如:我希望讀取一個(gè)視頻坊萝,截取每一幀圖像并將其轉(zhuǎn)為灰度圖像孵稽,并播放

import cv2 

capture = cv2.VideoCapture('/Users/0.mp4') ##假設(shè)我有個(gè)視頻放在(/Users/ 目錄下许起,我是 mac 玩家,win 玩家自行修改)

while(capture.isOpened()):  ## 檢測(cè)視頻打開(kāi)是否有問(wèn)題
    ret,frame = capture.read()  ## 逐幀讀取視頻
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) ## 灰度轉(zhuǎn)換
    cv2.imshow('frame', gray)  ## (播放)看圖
    if cv2.waitKey(30) == ord('q'): ## 控制退出菩鲜,選中窗口按'q' (大寫(xiě)不行)
        break

capture.release()  ## 清內(nèi)存园细,好習(xí)慣
cv2.destroyAllWindows()  ## 后面這兩句不寫(xiě),看圖的窗口就關(guān)不了
cv2.waitKey(1)
    
### 為了上面好看點(diǎn)接校,我把注釋寫(xiě)在下面了
### capture.isOpened()返回的是布爾值猛频,如果成功讀取這一幀,則為 True; 反之為 False
### ret 其實(shí)就是capture.isOpened(), 而 frame 這是獲取的這一幀圖像的內(nèi)容蛛勉,是矩陣格式
###  cv2.cvtColor()  將 BGR 彩色圖片轉(zhuǎn)為 灰度圖片
### cv2.imshow() 第一個(gè)參數(shù)是打開(kāi)播放圖像窗口的名字鹿寻,自己隨便命名;第二個(gè)參數(shù)是要看的圖像名稱(chēng)诽凌,就是 gray
### cv2.waitKey()毡熏,它的參數(shù)表示暫停時(shí)間,所以這個(gè)值越大侣诵,視頻播放速度越慢痢法,反之,播放速度越快窝趣,通常設(shè)置為25或30疯暑。 ord 是轉(zhuǎn)碼,因?yàn)?opencv 內(nèi)核是 C++哑舒,用的是 ASCⅡ (我不知道這里說(shuō)的對(duì)不對(duì))

如果我想截取某個(gè)時(shí)間點(diǎn)的圖片。
  1. 首先我們得知道幻馁,視頻中的每一幀對(duì)應(yīng)多少時(shí)間洗鸵,
    • 通過(guò)使用的函數(shù)capture.get(propId),可以獲取視頻(/攝像頭的一些屬性)仗嗦,如 分辨率膘滨、亮度、對(duì)比度等稀拐,我們想知道的幀速度也在這里
    • 傳入的參數(shù)是數(shù)字關(guān)鍵詞都可以火邓。propId是從0~18的數(shù)字,代表不同的屬性德撬,完整的屬性列表可以參考: VideoCaptureProperties 铲咨。
    • 如果想修改視頻的屬性,可以用 capture.set(propId,value)來(lái)修改屬性值

github 大佬的經(jīng)驗(yàn)之談:某些攝像頭設(shè)定分辨率等參數(shù)時(shí)會(huì)無(wú)效蜓洪,因?yàn)樗?有固定的分辨率大小支持纤勒,一般可在攝像頭的資料頁(yè)中找到。

import cv2 

capture = cv2.VideoCapture('/Users/0.mp4') 
timepoint = 10  ###(單位:秒) 想截取視頻中 10s 那一幀
timer = 0       ### 用來(lái)計(jì)算幀數(shù)隆檀,
fps = round(capture.get(5))  ### 1 秒有多少幀, 使用的參數(shù)是5,表示幀速 (要用怎么自己查表)
### 一般來(lái)說(shuō)摇天,1 秒 約等于 24 幀粹湃,我這個(gè)視頻是 23.976023976023978, 所以直接用round(), 四舍五入,將其約等于 24.
while(capture.isOpened()):  ## 檢測(cè)視頻打開(kāi)是否有問(wèn)題
    timer += 1  ## 開(kāi)始計(jì)算過(guò)去了多少幀
    ret,frame = capture.read()  ## 逐幀讀取視頻
    if timer == timepoint * fps:  ## 10秒的時(shí)候,開(kāi)始截圖
        cv2.imwrite('/Users/10s.jpg',frame) ## 存圖泉坐,第一個(gè)參數(shù)遞質(zhì)为鳄,第二個(gè)要存的圖是哪個(gè)
        break  ## 退出

capture.release()  ## 清內(nèi)存,好習(xí)慣

如果我看視頻看到某一幀想截圖 (這個(gè)更簡(jiǎn)答了是不是腕让,和第一個(gè)很像)

我們來(lái)個(gè)暗號(hào)济赎,比如 按下鍵盤(pán) ‘s’ 就截圖

import cv2 

capture = cv2.VideoCapture('/Users/0.mp4') 

while(capture.isOpened()):  ## 檢測(cè)視頻打開(kāi)是否有問(wèn)題
    ret,frame = capture.read()  ## 逐幀讀取視頻
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) ## 灰度轉(zhuǎn)換
    cv2.imshow('frame', gray)  ## (播放)看圖
    if cv2.waitKey(30) == ord('s'): ## 控制退出,選中窗口按'q' (大寫(xiě)不行)
        cv2.imwrite('/Users/10s.jpg',frame) ### 其實(shí)就多了這個(gè)
        break

capture.release()  ## 清內(nèi)存记某,好習(xí)慣
cv2.destroyAllWindows()  ## 后面這兩句不寫(xiě)司训,看圖的窗口就關(guān)不了
cv2.waitKey(1)

如果我覺(jué)得截圖不過(guò)癮,想截一段動(dòng)畫(huà)(gif) 或 截一段視頻

這次要加上存視頻的函數(shù) cv2.VideoWriter()
思路還是一樣液南,假設(shè)我們想截 第 5 秒到第 10 秒的視頻

cv2.VideoWriter()
先說(shuō)說(shuō)這個(gè)函數(shù)壳猜,它需要四個(gè)參數(shù)
cv2.VideoWriter(filename, fourcc, fps, resolution)

  • 第一個(gè)參數(shù) 是文件名,如‘output.avi’ (絕對(duì)路徑滑凉,你保存文件的位置)
  • 第二個(gè)參數(shù) 是編碼方式统扳,這里選的是 FourCC碼 (我也沒(méi)搞懂,反正先用著吧)
  • 第三個(gè)參數(shù)是幀率 FPS (又叫幀速)畅姊,一般和原視頻一樣咒钟,24,有興趣的可以試試更大或更小的數(shù)字若未,發(fā)現(xiàn)新世界
  • 第四個(gè)是分辨率 (每英寸像素Pixel per inch, ppi)
    • 480P: 720×480 (寬 × 高
    • 720p: 1280×720
    • 1080p: 1920×1080
    • 可以試試原畫(huà)是 480P 轉(zhuǎn) 1080P 輸出會(huì)變什么樣子 (查原視頻分辨率用 .get(3) 寬朱嘴,.get(4) 高

還有一個(gè)FourCC是用來(lái)指定視頻編碼方式的四字節(jié)碼,所有的編碼可參考 Video Codecs 粗合。如MJPG編碼可以這樣寫(xiě): cv2.VideoWriter_fourcc(*’MJPG’)或cv2.VideoWriter_fourcc(‘M’,’J’,’P’,’G’)
(這個(gè)我也不懂萍嬉,先用著吧)

那開(kāi)始干吧

import cv2 

capture = cv2.VideoCapture('/Users/test.mp4')


time1 = 5   ###(單位:秒) 截取開(kāi)始時(shí)間 第5秒
time2 = 10  ###(單位:秒) 截取結(jié)束時(shí)間 第10秒
timer = 0   ### 用來(lái)計(jì)算幀數(shù),
fps = round(capture.get(5))  ### 獲取 1 秒有多少幀

### 定義編碼方式并創(chuàng)建VideoWriter對(duì)象
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
outfile = cv2.VideoWriter('/Users/test_5s.avi',fourcc, 24, (640, 360))  ###我這邊測(cè)試視頻 幀頻是24隙疚,分辨率是640×360, 可以分別用.get(5), .get(3)和.get(4)獲取, 當(dāng)然你也可以改動(dòng)一下試試看什么效果

while(capture.isOpened()):  ## 檢測(cè)視頻打開(kāi)是否有問(wèn)題
    timer += 1  ## 開(kāi)始計(jì)算過(guò)去了多少幀
    ret,frame = capture.read()  ## 逐幀讀取視頻

    if time1 * fps >= timer: ## 小于 5 秒時(shí)壤追,跳過(guò) (為什么要? 因?yàn)闆](méi)有這個(gè)會(huì)直接跳到 else,break 就結(jié)束了)
        pass
    elif time1 * fps < timer and timer < time2 * fps:  ## 大于 5 秒供屉,小于 10 秒時(shí)行冰,開(kāi)始截視頻
        outfile.write(frame) ## outfile 就是創(chuàng)建VideoWriter對(duì)象
    else: ## 大于 10 秒的時(shí)候,停止
        print('finished')
        break  ## 退出

capture.release()  ## 清內(nèi)存伶丐,好習(xí)慣

OK 啦悼做,是不是很簡(jiǎn)單,快來(lái)試試吧

最后說(shuō)說(shuō)改變一些參數(shù)的結(jié)果

  1. 幀速撵割,這個(gè)顧名思義贿堰,幀速越大,視頻播放的速度越快啡彬,比如原本1秒是24幀羹与,如果你改成240幀故硅,相當(dāng)于你1秒的時(shí)間播放了原本10秒時(shí)間的內(nèi)容,將幀速改小同理纵搁。
  2. 分辨率, 別想了吃衅,只要改動(dòng)分辨率,就會(huì)保存失敗(空白文件)腾誉,這也很容易懂徘层,不可能讓你那么容易就提高視頻的清晰度嘛,(降低也不行 doge)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末利职,一起剝皮案震驚了整個(gè)濱河市趣效,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猪贪,老刑警劉巖跷敬,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異热押,居然都是意外死亡西傀,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)桶癣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拥褂,“玉大人,你說(shuō)我怎么就攤上這事牙寞〗染椋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵碎税,是天一觀的道長(zhǎng)尤慰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)雷蹂,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任杯道,我火速辦了婚禮匪煌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘党巾。我一直安慰自己萎庭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布齿拂。 她就那樣靜靜地躺著驳规,像睡著了一般。 火紅的嫁衣襯著肌膚如雪署海。 梳的紋絲不亂的頭發(fā)上吗购,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天医男,我揣著相機(jī)與錄音,去河邊找鬼捻勉。 笑死镀梭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踱启。 我是一名探鬼主播报账,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼埠偿!你這毒婦竟也來(lái)了透罢?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤冠蒋,失蹤者是張志新(化名)和其女友劉穎羽圃,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體浊服,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡统屈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牙躺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愁憔。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖孽拷,靈堂內(nèi)的尸體忽然破棺而出吨掌,到底是詐尸還是另有隱情,我是刑警寧澤脓恕,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布膜宋,位于F島的核電站,受9級(jí)特大地震影響炼幔,放射性物質(zhì)發(fā)生泄漏秋茫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一乃秀、第九天 我趴在偏房一處隱蔽的房頂上張望肛著。 院中可真熱鬧,春花似錦跺讯、人聲如沸枢贿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)局荚。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耀态,已是汗流浹背轮傍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茫陆,地道東北人金麸。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像簿盅,于是被迫代替她去往敵國(guó)和親挥下。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容