【CV】OpenCV 入门之旅
OpenCV 是一個強大的圖片處理工具,尤其是隨著人工智能、圖片識別等行業(yè)的興起,這個第三方庫也越來越受到重視,今天我們就一起來開啟 OpenCV 之旅
計算機視覺
我們先來看下到底什么是計算機視覺
其實這個是一個比較大的問題了,我們先來簡化下問題,思考如下場景
相信很多朋友都會使用微博來曬出自己的旅游照片,當然照片中會包含自己和家人朋友等等。那么該怎么快速的識別出照片中不同的人并標注出來呢,這個時候就可以用到計算機視覺的知識了
計算機視覺是一個跨學(xué)科領(lǐng)域,涉及如何使計算機從數(shù)字圖像或視頻中獲得高級別的理解,并使得計算機能夠識別諸如人臉、燈柱甚至雕像之類的物體
計算機如何讀取圖像
比如說下面這張圖片,計算機是怎么展示的呢
計算機會將任何圖像讀取為 0 到 255 之間的范圍值
對于任何彩色圖像,都有 3 個主要通道——紅色、綠色和藍色,它的工作原理非常簡單:
“
為每種原色形成一個矩陣,然后這些矩陣組合起來為各個 R、G、B 顏色提供像素值,然后矩陣的每個元素提供與像素亮度強度有關(guān)的數(shù)據(jù)
”
文字有些抽象,我們來看下面這張圖片
如圖所示,此處圖像的大小可以計算為 B x A x 3
注意:對于黑白圖像,只有一個通道
了解了前置基礎(chǔ)知識后,接下來讓我們看看 OpenCV 到底是什么
OpenCV 是什么
OpenCV 是一個 Python 庫,用于解決計算機視覺問題。OpenCV 最初由 Intel 于 1999 年開發(fā),后來得到 Willow Garage 的支持,從而發(fā)展的更加迅速
OpenCV 支持多種編程語言,如 C++、Python、Java 等,同時也支持多種平臺,包括 Windows、Linux 和 MacOS
OpenCV Python 只不過是與 Python 一起使用的原始 C++ 庫的包裝類,所有 OpenCV 數(shù)組結(jié)構(gòu)都會被轉(zhuǎn)換為 NumPy 數(shù)組
這使得 OpenCV 更容易與其他使用 NumPy 的庫集成,例如,SciPy 和 Matplotlib 等
接下來讓我們看看使用 OpenCV 執(zhí)行的一些基本操作
OpenCV 基本操作
載入圖像
Import?cv2#?彩色圖片Img?=?cv2.imread?(Penguins.jpg,1)#?黑白圖片Img_1?=?cv2.imread?(Penguins.jpg,0)如上一段代碼所示,首先我們需要導(dǎo)入 OpenCV 模塊
然后我們可以使用 imread 模塊讀取圖像,參數(shù)中的1表示是彩色圖像。如果該參數(shù)為 0 而不是 1,則表示導(dǎo)入的圖像是黑白圖像
圖像形狀/分別率
我們可以利用 shape 子函數(shù)來打印出圖像的形狀
Import?cv2Img?=?cv2.imread?(Penguins.jpg,0)Print(img.shape)圖像的形狀是指 NumPy 數(shù)組的形狀,從執(zhí)行代碼可以看出,矩陣由 768 行和 1024 列組成
展示圖像
import?cv2Img?=?cv2.imread(Penguins.jpg,0)cv2.imshow(Penguins,?Img)cv2.waitKey(0)#?cv2.waitKey(2000)cv2.destroyAllWindows()我們首先使用 imread 導(dǎo)入圖像
接下來使用 imshow 函數(shù)通過打開一個窗口來顯示圖像,imshow 函數(shù)有兩個參數(shù),分別是窗口的名稱和要顯示的圖像對象
然后我們等待用戶事件,waitKey 使窗口保持靜態(tài),直到用戶按下某個鍵,傳遞的參數(shù)是以毫秒為單位的時間
最后,我們使用 destroyAllWindows 根據(jù) waitForKey 參數(shù)關(guān)閉窗口
調(diào)整圖像大小
調(diào)整圖像大小也很容易
import?cv2img?=?cv2.imread(Penguins.jpg,0)resized_image?=?cv2.resize(img,?(650,500))cv2.imshow(Penguins,?resized_image)cv2.waitKey(0)cv2.destroyAllWindows()在這里,resize 函數(shù)用于將圖像調(diào)整為所需的形狀,這里的參數(shù)是新調(diào)整大小的圖像的形狀
我們注意到,圖像對象從 img 變?yōu)?resized_image,因為現(xiàn)在圖像對象發(fā)生了變化
還有另一種方法可以將參數(shù)傳遞給 resize 函數(shù)
Resized_image?=?cv2.resize(img,?int(img.shape[1]/2),?int(img.shape[0]/2)))這樣,我們得到的新圖像形狀會是原始圖像形狀的一半
接下來讓我們進入實戰(zhàn)部分,使用 OpenCV 執(zhí)行人臉檢測
人臉檢測
人臉檢測?乍一看似乎很復(fù)雜,但是通過 OpenCV 就非常容易了,只需要三步走即可!
第 1 步:我們首先拿到一個圖像,然后創(chuàng)建一個級聯(lián)分類器,它最終會給出我們?nèi)四樀奶卣?/p>
第 2 步:這一步涉及使用 OpenCV,它將讀取圖像和特征文件,主要就是操作 NumPy 數(shù)組
我們需要做的就是搜索人臉 NumPy ndarray 的行和列值,這是帶有人臉矩形坐標的數(shù)組
第 3 步:使用矩形人臉框顯示圖像
首先,我們創(chuàng)建一個 CascadeClassifier 對象來提取人臉的特征,參數(shù)就是包含面部特征的 XML 文件的路徑
下一步是讀取帶有人臉的圖像,并使用 COLOR_BGR2GREY 將其轉(zhuǎn)換為黑白圖像,接著,我們搜索圖像的坐標,這是使用 detectMultiScale 來完成的
什么是坐標呢?就是面部矩形的坐標。scaleFactor 用于將形狀值減少 5%,直到找到人臉。因此,總的來說 -- 值越小,準確性越高
最后展示圖像
添加人臉框
一個比較簡單的邏輯處理
我們定義了使用 cv2.rectangle 通過傳遞圖像對象、框輪廓的 RGB 值和矩形的寬度等參數(shù)來創(chuàng)建矩形的方法。
讓我們看看人臉檢測的完整代碼:
import?cv2#?Create?a?CascadeClassifier?Object face_cascade?=?cv2.CascadeClassifier("haarcascade_frontalface_default.xml")#?Reading?the?image?as?it?is img?=?cv2.imread("photo.jpg")#?Reading?the?image?as?gray?scale?image gray_img?=?cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#?Search?the?co-ordintes?of?the?image faces?=?face_cascade.detectMultiScale(gray_img,?scaleFactor?=?1.05,minNeighbors=5) for?x,y,w,h?in?faces:img?=?cv2.rectangle(img,?(x,y),?(x+w,y+h),(0,255,0),3)resized?=?cv2.resize(img,(int(img.shape[1]/7),int(img.shape[0]/7)))cv2.imshow("Gray",?resized)cv2.waitKey(0)cv2.destroyAllWindows()接下來看看如何使用 OpenCV 捕獲帶有計算機網(wǎng)絡(luò)攝像頭的視頻
使用 OpenCV 捕獲視頻
使用 OpenCV 捕獲視頻也非常簡單
一張一張地讀取圖像,由于幀的快速處理已經(jīng)我們眼睛的機制(生物學(xué)范疇?)使單個圖像移動起來,就生成了視頻
首先,我們先導(dǎo)入 OpenCV 庫,接下來我們使用一個名為 VideoCapture 的方法,用于創(chuàng)建 VideoCapture 對象,該方法用于觸發(fā)用戶機器上的攝像頭。此函數(shù)的參數(shù)表示程序應(yīng)使用內(nèi)置攝像頭還是附加攝像頭,“0”表示內(nèi)置攝像頭
最后的釋放方法用于在幾毫秒內(nèi)釋放系統(tǒng)相機
但是當我們嘗試執(zhí)行上面的代碼時,會注意到相機燈亮起一秒鐘然后關(guān)閉這是因為沒有時間延遲來保持相機功能
我們來增加延遲
我們增加了3秒鐘的延遲,網(wǎng)絡(luò)攝像頭將開啟 3 秒鐘
添加一個窗口來顯示視頻輸出
在這里,我們定義了一個 NumPy 數(shù)組,我們用它來表示視頻捕獲的第一張圖像——存儲在幀數(shù)組中
我們還有一個 check 變量——這是一個布爾數(shù)據(jù)類型,如果 Python 能夠訪問和讀取 VideoCapture 對象,那么它返回 True
下面是代碼的輸出情況
我們得到的輸出為 True,并打印了幀數(shù)組的一部分
但是我們需要從讀取視頻的第一幀開始,以此,我們需要首先創(chuàng)建一個幀對象,它將讀取 VideoCapture 對象的圖像
如上所示, imshow 方法用于捕獲視頻的第一幀
直接捕獲視頻
為了捕獲視頻,我們將使用 while 循環(huán)
我們使用 cvtColor 函數(shù)將每一幀轉(zhuǎn)換為灰度圖像
waitKey(1) 將確保在每毫秒間隔后生成一個新幀
這里還有一個用戶事件觸發(fā)器,一旦用戶按下“q”鍵,程序窗口就會關(guān)閉
下面我們看看如何使用 OpenCV 做一個非常有趣的運動檢測器
基于 OpenCV 的運動檢測器
問題場景:通過一個網(wǎng)絡(luò)攝像頭,可以檢測到攝像頭前任何運動物體,并且返回一個圖表,這個圖表包含人/物體在相機前面的時間
問題場景示意圖如下:
下面我們來思考下解決方案
首先我們將圖像保存在特定幀中
接下來將圖像轉(zhuǎn)換為高斯模糊圖像,這樣做是為了確保我們計算出模糊圖像和實際圖像之間的明顯差異
此時,圖像仍然不是對象,我們定義了一個閾值來去除圖像中的瑕疵,例如陰影和其他噪聲等等
再接下來定義對象的邊框,我們在對象周圍添加一個矩形框
最后,我們計算對象出現(xiàn)和退出幀的時間
思路還是蠻清晰的
我們首先導(dǎo)入包并創(chuàng)建 VideoCapture 對象以確保我們使用網(wǎng)絡(luò)攝像頭捕獲視頻。
while 循環(huán)遍歷視頻的各個幀,我們將彩色幀轉(zhuǎn)換為灰度圖像,然后將此灰度圖像轉(zhuǎn)換為高斯模糊模型
我們使用 if 語句來存儲視頻的第一個圖像
接下來我們繼續(xù)深入
我們使用 absdiff 函數(shù)來計算第一個出現(xiàn)的幀與所有其他幀之間的差異
閾值函數(shù)提供閾值,將小于30的差值轉(zhuǎn)換為黑色。如果差異大于 30,它會將這些像素轉(zhuǎn)換為白色
之后我們使用 findContours 函數(shù)來定義圖像的輪廓區(qū)域
就像前面說的,contourArea 函數(shù)可去除噪聲和陰影。為簡單起見,將只保留那部分為白色,其面積大于我們?yōu)榇硕x的 1000 像素
幀每 1 毫秒更改一次,當用戶輸入“q”時,循環(huán)中斷并關(guān)閉窗口
最后計算對象在相機前的時間
我們使用 DataFrame 來存儲對象檢測和移動出現(xiàn)在幀中的時間值
在這里我們定義了一個狀態(tài)標志位,我們在錄制開始時使用此狀態(tài)為零,因為對象最初不可見
當檢測到對象時,我們將狀態(tài)標志更改為 1
我們將列出每個掃描幀的狀態(tài),如果發(fā)生更改以及發(fā)生更改的位置,則在列表中使用 datetime 記錄日期和時間
我們將時間值存儲在 DataFrame 中并寫入 CSV 文件
繪制運動檢測圖
最后一步是顯示結(jié)果
首先,我們從 motion_detector.py 文件中導(dǎo)入DataFrame
接下來將時間轉(zhuǎn)換為可以解析的可讀字符串格式
最后,使用散景圖在瀏覽器上繪制時間值的圖表
好了,這就是今天的 OpenCV 入門實戰(zhàn),怎么樣,看過之后是不是有一種動手的沖動呢,一起玩起來吧!
往期精彩回顧適合初學(xué)者入門人工智能的路線及資料下載機器學(xué)習(xí)及深度學(xué)習(xí)筆記等資料打印機器學(xué)習(xí)在線手冊深度學(xué)習(xí)筆記專輯《統(tǒng)計學(xué)習(xí)方法》的代碼復(fù)現(xiàn)專輯 AI基礎(chǔ)下載黃海廣老師《機器學(xué)習(xí)課程》視頻課黃海廣老師《機器學(xué)習(xí)課程》711頁完整版課件本站qq群955171419,加入微信群請掃碼:
總結(jié)
以上是生活随笔為你收集整理的【CV】OpenCV 入门之旅的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机搜狗浏览器怎么样
- 下一篇: WeX5 Model 里data ,ba