初識 OpenCV
簡介
OpenCV(Open Source Computer Vision Library)是一個涵蓋了數百種計算機視覺算法的開源算法庫。
OpenCV 具有模塊化結構,這意味著該軟件包包含多個共享或靜態庫。其中包含以下模塊:
-
Core functionality (core):一個定義基本數據結構的基礎模塊,包括密集多維數組 Mat 和所有其他模塊使用的基本函數。
-
Image Processing (imgproc):圖像處理模塊,包括線性和非線性圖像過濾、幾何圖像變換(調整大小、仿射和透視變形、基于通用表的重新映射)、色彩空間轉換、直方圖等。
-
Video Analysis (video):視頻分析模塊,包括運動估計、背景扣除和對象跟蹤算法。
-
Camera Calibration and 3D Reconstruction (calib3d):基本的多視圖幾何算法、單相機和立體相機校準、物體姿態估計、立體對應算法和 3D 重建元素。
-
2D Features Framework (features2d):顯著特征檢測器、描述符和描述符匹配器。
-
Object Detection (objdetect):檢測預定義類的對象和實例(例如,面部、眼睛、杯子、人、汽車等)。
-
High-level GUI (highgui):易于使用的界面和簡單的 UI 功能。
-
Video I/O (videoio): 易于使用的視頻捕獲和視頻編解碼器接口。
-
… 其他一些幫助模塊,例如 FLANN 和 Google 測試包裝器、Python 綁定等。
OpenCV 早期的 API 是使用 C 語言編寫的,然而基于 C 語言的 API 目前已經廢棄。目前 OpenCV API 已經是 C++ 編寫的,因此你可以十分高效的在 C++ 項目中使用 OpenCV。除此之外,OpenCV 官方還提供了其它語言的 API 調用支持,例如 Java、Python 以及 Matlab。當然,你還可以選擇其它的編程語言,例如 JavaScript、Rust 等,這些語言的社區也提供了方案來使用 OpenCV。
在本篇文章中,我們將主要使用 Python 語言來介紹 OpenCV 的一些基礎功能。
下載安裝
在對 OpenCV 有一個基礎的了解之后,我們可以開始嘗試在本地中配置 OpenCV 環境來進行一些簡單的功能測試。
基礎環境
Windows 11 22H2
Visual C++ Redistributable for Visual Studio 2015
Python 3.7.0
首先我們在用戶目錄創建一個文件夾,這里我們將其命名為 OpenCV_Test。隨后我們進入該目錄。
mkdir ~/OpenCV_Test && cd OpenCV_Test
我們需要創建一個 Python 的虛擬環境。
python -m venv .venv
創建完成之后我們直接激活虛擬環境。
.venv/scripts/activate
(可選)確保虛擬環境 pip 版本大于 19.3。
python -m pip install --upgrade pip
在虛擬環境下載 opencv-contrib-python==4.8.1.78
(contrib 為包含了額外模塊的版本)。
pip install opencv-contrib-python==4.8.1.78
至此,我們已經完成了 OpenCV 的環境配置,現在可以在項目根目錄下創建一個 opencv_test.py 文件,并追加以下內容。
import cv2 as cvprint(cv.__version__)
在終端通過 python opencv_test.py
進行測試,如果終端成功輸出版本號則代表安裝成功。
由于在之后的內容中,我們需要使用到一些測試數據,因此我們需要將 OpenCV 倉庫的 samples 拷貝到我們的項目根目錄下。
你可以通過 Github 瀏覽這些數據 - https://github.com/opencv/opencv/tree/4.x/samples/data
然后直接下載壓縮包,并將 samples 拷貝至項目根目錄下。https://github.com/opencv/opencv/archive/refs/heads/4.x.zip
圖像功能測試
該部分主要涉及到圖像的讀取,展示以及寫入 API。
import cv2 as cv
import sys, os# 添加當前目錄下的samples/data作為數據搜索路徑
cv.samples.addSamplesDataSearchPath(os.path.join(os.getcwd(), "samples", "data"))
# 讀取樣例數據中的圖片
img = cv.imread(cv.samples.findFile("starry_night.jpg"))
if img is None:sys.exit("Could not read the image.")
# 展示圖片
cv.imshow("Display window", img)
k = cv.waitKey(0)
# 當按下 s 時,寫入一張新的圖片至當前目錄
if k == ord("s"):cv.imwrite("starry_night1.png", img)
視頻功能測試
從攝像頭捕獲視頻
在該項任務中,我們通過攝像頭捕獲視頻幀,并將其轉為灰度幀展示出來。
import cv2 as cv# 視頻捕獲對象,用于調用系統攝像頭(測試環境為筆記本攝像頭)
cap = cv.VideoCapture(0)
if not cap.isOpened():print("Cannot open camera")exit()
while True:# 逐幀進行視頻捕獲ret, frame = cap.read()# 如果幀被捕獲,ret 為 trueif not ret:print("Can't receive frame (stream end?). Exiting ...")break# 將捕獲的幀轉為灰度gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)# 顯示當前灰度幀cv.imshow('frame', gray)# 當按下 q 鍵時,結束捕獲if cv.waitKey(1) == ord('q'):break
# 釋放捕獲對象
cap.release()
# 銷毀所有窗口
cv.destroyAllWindows()
從文件播放視頻
在該項任務中,我們通過已有文件讀取視頻幀信息,并展示其灰度幀。
import cv2 as cv
import os# 添加樣例資源搜索路徑
cv.samples.addSamplesDataSearchPath(os.path.join(os.getcwd(), "samples", "data"))
# 讀取樣例視頻文件
cap = cv.VideoCapture(cv.samples.findFile('vtest.avi'))while cap.isOpened():# 逐幀讀取視頻ret, frame = cap.read()# 當幀讀取成功,ret 為 trueif not ret:print("Can't receive frame (stream end?). Exiting ...")break# 獲取灰度幀gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)# 展示灰度幀cv.imshow('frame', gray)# 當按下 q 鍵時中斷播放if cv.waitKey(1) == ord('q'):break
# 釋放捕獲對象以及窗口資源
cap.release()
cv.destroyAllWindows()
錄制視頻的保存
在該項任務中,我們將使用攝像頭捕獲視頻幀,并將每幀都垂直翻轉,然后將其保存為新的視頻文件。
import cv2 as cv# 視頻捕獲窗口
cap = cv.VideoCapture(0)
# 定義編碼器與視頻寫入對象
fourcc = cv.VideoWriter_fourcc(*'XVID')
# 輸出名稱,編碼器,幀速率,幀尺寸
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while cap.isOpened():# 逐幀讀取攝像頭信息ret, frame = cap.read()# 正常讀取 ret 為 trueif not ret:print("Can't receive frame (stream end?). Exiting ...")break# 垂直翻轉視頻幀frame = cv.flip(frame, 0)# 寫入翻轉后的幀至輸出文件out.write(frame)# 展示翻轉后的幀信息cv.imshow('frame', frame)if cv.waitKey(1) == ord('q'):break
# 釋放全部資源
cap.release()
out.release()
cv.destroyAllWindows()
圖形的繪制
在該項任務中,我們將通過 OpenCV 繪制不同的幾何圖形。
直線
import numpy as np
import cv2 as cv# 創建一個黑色背景
img = np.zeros((512, 512, 3), np.uint8)
# 在 img 繪制一條粗細為 5 px 的藍色對角線
cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5)cv.imshow("img", img)
cv.waitKeyEx(0)
矩形
# 在 img 繪制一條左上到右下坐標的藍色矩形
cv.rectangle(img, (384,0), (510,128), (0,255,0), 3)
圓
# 在 img 繪制一個基于圓心加半徑的圓
cv.circle(img,(447,63), 63, (0,0,255), -1)
橢圓
# 參數分別為圖片、中心點,主副軸長度,橢圓逆時針旋轉角度,橢圓弧的起始角度,橢圓弧的結束角度,畫筆顏色等
cv.ellipse(img, (256, 256), (100, 50), 0, 0, 180, 255, -1)
多邊形
# 要繪制多邊形,首先需要頂點坐標。將這些點放入形狀為 ROWSx1x2 的數組中,其中 ROWS 是頂點數,其類型應為 int32
pts = np.array([[100, 100], [100, 200], [200, 200], [200, 100]], np.int32)
pts = pts.reshape((-1, 1, 2))
cv.polylines(img, [pts], True, (0, 255, 255))
如果第三個參數為 False,您將得到連接所有點的折線,而不是閉合形狀。
文字
# 參數分別為圖片,文字,坐標,字體,字體縮放,顏色,粗細,線型
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255), 2, cv.LINE_AA)
結語
在結束這篇介紹 OpenCV 的文章之際,我們希望你已經對這一強大的計算機視覺庫有了初步的了解。通過下載和安裝 OpenCV,你已經邁出了探索計算機視覺世界的第一步。
在文章中,我們探討了 OpenCV 的基礎部分,包括圖像處理、視頻處理和圖形繪制等方面的核心 API。這些功能為開發者提供了豐富的工具箱,可以用于解決各種計算機視覺問題,從簡單的圖像處理到復雜的目標檢測和跟蹤。
然而,OpenCV 是一個龐大而靈活的庫,我們只觸及了其中的冰山一角。我們鼓勵你繼續深入學習,探索 OpenCV 更高級的功能和技術。無論是在工業自動化、醫學影像、安防監控還是虛擬現實等領域,OpenCV 都發揮著至關重要的作用。
作為一個開源項目,OpenCV 的社區一直在不斷發展和改進。在進一步的學習之后,你也可以通過參與社區,貢獻你的力量,使這個強大的工具變得更加完善。(提出有效 issues 以及文檔的勘誤也是一份貢獻!)
在這個計算機視覺的精彩世界中,OpenCV 為你打開了大門。希望你能夠在這個旅程中找到樂趣,創造出令人驚嘆的視覺應用。