OpenCV快速入門之CV寶典

文章目錄

  • OpenCV的基礎應用
    • 一、OpenCV簡介:
      • 1.1 OpenCV 優勢
      • 1.2 OpenCV-Python
    • 二、環境安裝
      • 2.1 環境導入
    • 三、圖像表示
      • 3.1 顏色空間(Color Space)
      • 3.2 具體說明
      • 3.3 圖像在計算機中的表示
    • 四、基本圖像操作
      • 4.1 創建窗口
        • **1. 核心窗口行為控制**
          • `cv.WINDOW_NORMAL`
          • `cv.WINDOW_AUTOSIZE`(默認值)
        • **2. 寬高比控制**
          • `cv.WINDOW_KEEPRATIO`
          • `cv.WINDOW_FREERATIO`
        • **3. 顯示模式**
          • `cv.WINDOW_FULLSCREEN`
        • **4. 渲染與 GUI 樣式**
          • `cv.WINDOW_OPENGL`
          • `cv.WINDOW_GUI_EXPANDED` / `cv.WINDOW_GUI_NORMAL`
        • flags 的組合使用(位運算 `|`)
        • **總結:如何選擇?**
      • 4.2 讀取圖像
        • 參數詳解
        • 關鍵補充:
      • 4.3 顯示圖像
        • 參數解釋:
      • 4.4 保存圖像
        • 參數說明
      • 4.5 創建黑白圖像和隨機圖像
        • 一、創建黑色圖像
        • 二、創建白色圖像
        • 三、創建隨機顏色圖像
        • 四、通用注意事項
      • 4.6 圖像的裁剪(切片)
      • 4.7 圖像大小的調整(縮放)
        • 一、三種圖像尺寸處理方式對比
        • 二、關鍵注意點
        • 三、總結
    • 五、圖像繪制
        • 5.1 繪制直線
        • 5.2 繪制矩形
        • 5.3 繪制圓形
        • 5.4 繪制橢圓
        • 5.5 繪制文本
        • 5.6 繪制多邊形
        • 綜合案例:
        • 難點解析:
          • 1. `cv.polylines()` 對頂點格式的要求
          • 2. 為什么原始 `pts` 不符合要求?
          • 3. `reshape((-1, 1, 2))` 的作用
          • 4. 為什么沒有返回值?
    • 六、視頻讀取與捕捉
      • 6.1 `cv2.VideoCapture()` 方法
      • 6.2 捕獲攝像頭實時視頻
      • 6.3 讀取本地視頻文件
      • 6.4 常用屬性設置與獲取
      • 6.5 難點解析
        • 1.為什么在讀取視頻流的時候不使用`cv2.waitKey(0)`?
      • 🎯 小結:
        • 2.為什么在要使用`&0XFF`來操作?
    • 七、思維導圖

OpenCV的基礎應用


一、OpenCV簡介:

OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和機器學習軟件庫。

OpenCV 由一系列 C 函數和少量 C++ 類構成,同時提供了 Python、Java、MATLAB 等語言的接口。

OpenCV 提供了大量的計算機視覺算法和圖像處理工具,廣泛應用于圖像和視頻的處理、分析以及機器學習領域。

OpenCV 的設計目標是提供一套簡單易用的計算機視覺基礎庫,幫助開發人員快速構建復雜的視覺應用。

1.1 OpenCV 優勢

  • **開源免費:**完全開源,可以自由使用,降低開發成本和技術門檻。

  • **多語言支持:**除C++原生接口外,還支持Java、Python等編程語言。

  • **跨平臺:**支持多種操作系統,Windows、Linux、ios、Android等,方便開發和部署。

  • **豐富API:**完善的傳統計算機視覺算法,涵蓋主流的機器學習算法,同時添加了對深度學習的支持。

1.2 OpenCV-Python

  • C++ 高性能 + Python 簡潔
  • 基于Numpy,易于科學計算、與其他庫進行集成(Scipy、Matplotlib)

二、環境安裝

pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple 

2.1 環境導入

import cv2 as cv

三、圖像表示

在計算機視覺中,圖像是由像素(Pixel)組成的矩陣,每個像素包含了該位置的顏色或灰度信息。

  • 像素:圖像的最小信息單位,通常用 8 位無符號整數表示,取值范圍 0~255
  • 位深:常見圖像是 8 位圖像,即每個像素的每個通道占用 8 位

3.1 顏色空間(Color Space)

顏色空間 是表示顏色的一種方式,決定了像素的含義和顏色的表達方式不同顏色空間適用于不同的圖像處理場景。

顏色空間通道含義典型用途
RGBRed, Green, Blue顯示、繪圖、圖像合成
BGRBlue, Green, RedOpenCV 默認格式
HSVHue, Saturation, Value顏色分割、濾色、目標跟蹤
GRAY灰度邊緣檢測、特征提取
YCrCbLuma + 色度分量視頻壓縮,膚色檢測
LABLightness, a*, b*顏色校正,色彩調整

3.2 具體說明

  • RGB(紅綠藍)

    • 最常見的顏色空間,圖像以 三通道 存儲,每通道 0~255
    • 適合圖像顯示、繪制、調色板操作
    • 在 OpenCV 中,讀取的彩色圖像是 BGR 順序(注意差別)
  • HSV(色調-飽和度-明度)

    • 色調(H):表示顏色種類(0~179)
    • 飽和度(S):顏色的純度(0~255)
    • 明度(V):亮度(0~255)
    • 適用于顏色分割物體跟蹤,因為顏色分量與光照變化關系較小。
    • 顏色轉換BGR -> HSV
    hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    
  • 灰度圖(Grayscale)

    • 單通道,0 表示黑色,255 表示白色

    • 用于邊緣檢測特征提取圖像二值化

    • 讀取灰度圖:

    gray_img = cv2.imread('path/to/image.jpg', cv2.IMREAD_GRAYSCALE)
    

3.3 圖像在計算機中的表示

  • 彩色圖像:三維 NumPy 數組,形狀 (高度, 寬度, 3)
  • 灰度圖像:二維 NumPy 數組,形狀 (高度, 寬度)
  • 數據類型unit8(0-255)
  • 通道順序
    • OpenCV 默認 BGR
    • 其他庫(如 Matplotlib)通常是 RGB

四、基本圖像操作

4.1 創建窗口

cv.namedWindow(winname,flags)

image-20250722172639533

在 OpenCV 中,cv.namedWindow()flags 參數用于控制窗口的行為(如是否可縮放、是否保持比例、顯示樣式等)。以下是常見 flags 的詳細作用和使用場景:

1. 核心窗口行為控制
cv.WINDOW_NORMAL
  • 作用:允許用戶自由調整窗口大小(可拉伸、縮放),窗口尺寸不受圖像原始大小限制。
  • 場景:需要手動放大 / 縮小窗口查看圖像細節時(如醫學影像、高分辨率圖像)。
cv.WINDOW_AUTOSIZE(默認值)
  • 作用:窗口大小自動適配圖像尺寸,用戶無法手動調整窗口大小。
  • 場景:固定尺寸展示圖像,避免誤操作改變窗口大小(如批量展示圖像預覽)。
2. 寬高比控制
cv.WINDOW_KEEPRATIO
  • 作用:調整窗口大小時,強制保持圖像的寬高比(圖像不會拉伸變形)。

  • 依賴:需與 WINDOW_NORMAL 配合(因為 WINDOW_AUTOSIZE 下窗口不可調整)。

  • 示例

    cv.namedWindow("image", cv.WINDOW_NORMAL | cv.WINDOW_KEEPRATIO)
    

    此時拉伸窗口,圖像會按原始比例縮放,避免變形。

cv.WINDOW_FREERATIO
  • 作用:允許窗口和圖像自由縮放(不保持寬高比),可能導致圖像拉伸變形。
  • 場景:特殊需求(如強制填充窗口,忽略比例)。
3. 顯示模式
cv.WINDOW_FULLSCREEN
  • 作用:直接以全屏模式顯示窗口(覆蓋整個屏幕)。
  • 場景:需要最大化展示圖像(如演示、大屏展示)。
4. 渲染與 GUI 樣式
cv.WINDOW_OPENGL
  • 作用:啟用 OpenGL 渲染支持,利用 GPU 加速繪制(適合復雜圖形渲染,如 3D 可視化結合 OpenCV 窗口)。
cv.WINDOW_GUI_EXPANDED / cv.WINDOW_GUI_NORMAL
  • 作用

    :控制窗口的 GUI 樣式:

    • WINDOW_GUI_EXPANDED:顯示擴展界面(含工具欄、狀態欄,更現代)。
    • WINDOW_GUI_NORMAL:顯示傳統簡潔界面(無額外控件)。
flags 的組合使用(位運算 |)

多個 flags 可通過按位或組合,例如:

# 允許自由調整窗口大小 + 保持圖像寬高比
cv.namedWindow("image", cv.WINDOW_NORMAL | cv.WINDOW_KEEPRATIO)
總結:如何選擇?
需求推薦 flags 組合
固定尺寸展示cv.WINDOW_AUTOSIZE(默認)
可縮放且保持圖像比例`cv.WINDOW_NORMALcv.WINDOW_KEEPRATIO`
全屏展示cv.WINDOW_FULLSCREEN
高性能渲染(如 3D)cv.WINDOW_OPENGL

理解這些 flags 后,可更靈活地控制 OpenCV 窗口的交互性和顯示效果 ?。

4.2 讀取圖像

cv.imread(filename='',flags=cv.IMREAD_COLOR)

image-20250722180427179

參數詳解

filename ='xxx' filename關鍵字參數為要讀取的圖片地址,可以使用絕對地址也可以是相對地址

以下是 cv.imread()flags 參數的核心說明(表格形式,按功能分類):

標志常量核心作用典型場景 & 補充說明
基礎色彩模式
cv.IMREAD_GRAYSCALE灰度圖 讀取(單通道,uint8 類型)需黑白處理時使用;忽略顏色信息,計算更快。
cv.IMREAD_COLOR彩色圖 讀取(BGR 三通道,uint8 類型,默認行為)忽略 Alpha 通道(透明層);OpenCV 默認存儲為 BGR(而非 RGB)。
cv.IMREAD_UNCHANGED讀取 原始圖像(保留所有通道,包括 Alpha 通道,如 PNG 透明層)處理帶透明背景的圖像(輸出為 4 通道:BGR+Alpha)。
深度與格式兼容
cv.IMREAD_ANYCOLOR允許 任意顏色模式 讀取(不強制轉換為 BGR,保留文件原始色彩格式)靈活處理特殊格式圖像(如 CMYK 等非 RGB 格式)。
cv.IMREAD_ANYDEPTH允許讀取 高深度圖像(如 16 位灰度圖,普通圖像為 8 位)醫學影像(CT)、遙感圖像等場景;需配合格式支持。
降采樣(快速預覽)
cv.IMREAD_REDUCED_COLOR_2彩色圖 + 尺寸縮小為 1/2(降采樣,加速加載)后綴 _4(1/4)、_8(1/8)同理;適合大圖像快速預覽。
cv.IMREAD_REDUCED_GRAYSCALE_2灰度圖 + 尺寸縮小為 1/2同上,后綴數字表示縮小倍數(2? 倍)。
特殊處理
cv.IMREAD_IGNORE_ORIENTATION忽略 EXIF 方向信息(如手機拍照的旋轉標記,強制原始方向)避免自動旋轉圖像,保持像素原始排列。
cv.IMREAD_LOAD_GDAL使用 GDAL 庫 加載(支持 TIFF、GeoTIFF 等地理 / 遙感圖像格式)需提前安裝 GDAL 庫;處理專業地理數據場景。
關鍵補充:
  1. 組合使用:多個標志可通過 按位或 | 組合,例如:

    # 灰度圖 + 尺寸縮小1/2
    img = cv.imread("img.jpg", cv.IMREAD_GRAYSCALE | cv.IMREAD_REDUCED_2)
    
  2. 默認行為:若不指定 flags,等價于 cv.IMREAD_COLOR(但建議顯式指定,避免版本差異)。

  3. 返回值:若圖像讀取失敗(路徑錯誤、格式不支持),返回 None,需提前判斷。

通過合理選擇 flags,可靈活控制圖像的讀取方式(色彩、通道、尺寸、深度等),適配不同業務場景 ?。

4.3 顯示圖像

cv.imshow(winname,mat)
參數解釋:

winname:顯示圖像的窗口名,以字符串類型表示,如果你的窗口之前沒有定義會自動創建一個默認的窗口屬性(cv.WINDOW_AUTOSIZE)

mat:為你要顯示的圖像,也可以是numpy數組。

cv.imshow('win', img)
cv.waitKey(0)
cv.destroyAllWindows()

image-20250722182022047

注意:在調用顯示圖像的API后,要調用cv2.waitKey(0)給圖像繪制留下時間,否則窗口會出現無響應情況,并且圖像無法顯示出來。

  • cv.waitKey(0):表示無限期地等待任何鍵盤按鍵。這種用法常見于圖像顯示窗口中,確保圖像在窗口中顯示直到用戶決定關閉它。

  • cv.waitKey(n):n>0,意味著程序將等待n毫秒。這種方式常用于視頻播放或實時攝像頭捕獲場景,以便控制每一幀停留的時間,同時允許用戶通過按鍵來中斷循環或發出命令。

    cv.destroyAllWindows([winname])
    
    • cv.destroyAllWindows():會在當前程序執行到該語句時立即銷毀打開的窗口,并釋放與這些窗口相關的資源。
    • winname:窗口名,關閉指定名稱的窗口。可省略,銷毀所有已打開的窗口。
    • 使用任意的按鍵就可以退出程序。

4.4 保存圖像

cv.imwrite(cv.imwrite(filename='output.png', img=img1)
參數說明
  1. filename(必填)
    • 類型:字符串(str
    • 作用:指定保存的文件路徑和文件名(需包含擴展名,如 .png.jpg.bmp 等)。
    • 示例:"output.png"(保存在當前目錄)、"./images/result.jpg"(保存在指定文件夾)。
  2. img(必填)
    • 類型:NumPy 數組(numpy.ndarray
    • 作用:需要保存的圖像數據,必須符合 OpenCV 圖像格式要求:
      • 維度:2 維(灰度圖,(height, width))或 3 維(彩色圖,(height, width, 3),BGR 通道順序)。
      • 數據類型:通常為 uint8(像素值范圍 0-255)。

4.5 創建黑白圖像和隨機圖像

import cv2 as cv
import numpy as npheight = 360
width = 480
channels = 3
# 創建一個全0數組,表示黑色圖像
black = np.zeros((360, 480, 3), dtype=np.uint8)
# black = np.zeros((height,width,channels),dtype=np.uint8)
cv.imshow("black", black)# 使用np.full()創建白色圖像
white = np.full((height, width, channels), 255, dtype=np.uint8)
cv.imshow("white", white)
# 使用np.ones()創建白色圖像,利用廣播機制
white_img = np.ones((512, 512, 3), dtype=np.uint8) * 255# 索引修改像素值,表示白色圖像
black[:, :, :] = 255
# black[:,:] = 255 # 利用廣播機制
# black[:] = 255 # 利用廣播機制
cv.imshow("trans_black", black)
cv.imshow("trans_white", white_img)
# 使用np.random.randint()創建隨機顏色圖像 [low,high)
random_color = np.random.randint(0, 256, (height, width, channels), dtype=np.uint8)
cv.imshow("random_color", random_color)cv.waitKey(0)
cv.destroyAllWindows()
一、創建黑色圖像

核心原理:所有像素值為 0(BGR 三通道均為 0)

# 方法:使用np.zeros()初始化全0數組
black = np.zeros((height, width, channels), dtype=np.uint8)
  • 適用場景:需要純黑色背景時
  • 特點:直接創建,無需額外計算,效率最高
二、創建白色圖像

核心原理:所有像素值為 255(BGR 三通道均為 255)

  1. 方法 1:np.full () 直接填充

    white = np.full((height, width, channels), 255, dtype=np.uint8)
    
    • 特點:一步到位,直接指定填充值
  2. 方法 2:np.ones () + 廣播乘法

    white_img = np.ones((height, width, channels), dtype=np.uint8) * 255
    
    • 特點:利用廣播機制,先創建全 1 數組再放大到 255
  3. 方法 3:索引切片修改現有數組

    # 先創建黑色圖像,再通過切片整體修改
    black = np.zeros((height, width, channels), dtype=np.uint8)
    black[:, :, :] = 255  # 三種等價寫法
    # black[:,:] = 255   # 利用廣播省略最后一維
    # black[:] = 255     # 利用廣播省略后兩維
    
    • 適用場景:需要在已有圖像基礎上修改時
三、創建隨機顏色圖像

核心原理:每個像素的 BGR 通道值隨機生成(0-255)

# 方法:np.random.randint()生成隨機整數
random_color = np.random.randint(0, 256, (height, width, channels), dtype=np.uint8)
  • 特點:左閉右開區間 [0,256) 剛好覆蓋 0-255 的像素值范圍
  • 適用場景:測試、隨機背景生成等
四、通用注意事項
  1. 數組形狀:必須是(height, width, channels),符合 OpenCV 的圖像格式要求
  2. 數據類型:固定使用np.uint8(8 位無符號整數),對應像素值 0-255 的范圍
  3. 通道順序:OpenCV 默認使用 BGR 格式(藍、綠、紅),與 RGB 不同但不影響純色圖像創建

4.6 圖像的裁剪(切片)

  • Opencv中,圖像切片用于從圖像中提取一個子區域(矩形區域)。

  • 假設你有一個圖像img,它的類型是numpy.ndarrayimg[y:y+h,x:x+w]的含義如下:

    • x:子區域左上角的x坐標
    • y:子區域左上角的y坐標
    • w:子區域的寬度
    • h:子區域的高度
  • 切片操作

    • img[y:y+h,x:x+w]提取的是從(x,y)開始,高度為h,寬度為w的矩形區域
import cv2 as cv# 讀取圖像
cat = cv.imread("./images/1.jpg", cv.IMREAD_COLOR)
# 切片 arr[h1:h2, w1:w2] h2 = h1 + h, w2 = w1 + w
# (291,242) (353,288) #shape() 返回的是(h,w,c)
eye = cat[242:288,291:353]
leg = cat[99:341,82:271] #(82,99) (271,341)
# cv.imshow("cat", cat)cv.imshow("eye", eye)
cv.imshow("leg", leg)cv.waitKey(0)
cv.destroyAllWindows()

image-20250722184638972

4.7 圖像大小的調整(縮放)

import cv2 as cv
import numpy as np
from PIL import Image
# 讀取圖像
pig = cv.imread('./images/pig.png', cv.IMREAD_COLOR)print(pig.shape)
cv.imshow("pig", pig)
# 調整圖像大小 cv.resize(img, (width, height))
pig2 =cv.resize(pig,(480,520))
print(pig2.shape) #(height, width, channel)pig3 = np.reshape(pig,(1080,650,3))
print(pig3.shape)pig.shape = (1080,650,3)
# 顯示圖像
cv.imshow("pig2", pig2)
cv.imshow("pig3", pig3)pig4 = Image.open('./images/pig.png')
pig4 = pig4.resize((480,520))
pig4.show()# 等待按鍵按下
cv.waitKey(0)
# 釋放窗口
cv.destroyAllWindows()
一、三種圖像尺寸處理方式對比
方法原理效果 / 特點是否推薦用于圖像縮放
cv.resize(pig, (480, 520))OpenCV 內置縮放,通過插值算法重新計算像素生成平滑的縮放圖像,尺寸為 (520, 480, 3)(高 × 寬 × 通道),顯示正常? 推薦
np.reshape/pig.shape = ...僅修改數組維度,不改變像素值和總數若像素總數不匹配則報錯;若匹配則像素排列混亂,圖像嚴重撕裂、失真? 不推薦
PIL.Image.resize((480, 520))PIL 庫的縮放,同樣通過插值重新計算像素生成平滑的縮放圖像,尺寸為 (480, 520)(寬 × 高),顯示正常(PIL 默認 RGB 格式,但縮放邏輯正確)? 推薦
二、關鍵注意點
  1. OpenCV 與 PIL 的坐標順序差異

    • OpenCV 中 cv.resize(img, (width, height)) 的尺寸參數是 (寬, 高),但返回圖像的 shape(高, 寬, 通道)(如 (520, 480, 3))。
    • PIL 中 Image.resize((width, height)) 的尺寸參數同樣是 (寬, 高),且返回圖像的尺寸直接是 (寬, 高)(如 (480, 520)),與視覺直觀感受一致。

    兩者的縮放邏輯相同(都是重采樣生成新像素),只是返回的尺寸表示方式略有差異(OpenCV 更貼近數組的 (行, 列) 邏輯)。

  2. NumPy 維度修改的問題依然存在
    代碼中的 pig3 = np.reshape(pig, (1080, 650, 3))pig.shape = (1080, 650, 3) 仍然面臨之前的問題:

    • 若原始圖像的總像素數(高×寬×3)不等于 1080×650×3,會直接報 ValueError
    • 即使像素總數恰好匹配,圖像也會因像素排列混亂而撕裂(例如原本連續的像素被強行拆分到不同行,導致線條斷裂、色彩錯位)。
三、總結
  • 圖像縮放的正確方式:使用 cv.resize()(OpenCV)或 Image.resize()(PIL),兩者都通過插值算法重新計算像素,保證圖像平滑不失真。
  • NumPy 維度修改的正確用途:僅用于不改變像素總數的維度重組(例如將 (h, w, 3) 展平為 (h×w, 3)),絕對不能用于改變圖像的實際寬高(縮放)。

[!NOTE]

PIL庫的Image.resize()方法的參數有哪些?

除了這三種方式,還有哪些方法可以調整圖像大小?

如何在保持圖像比例的同時調整圖像大小?


五、圖像繪制

5.1 繪制直線
cv2.line(img, start_point, end_point, color, thickness)
  • img:要繪制的圖像
  • start_pointend_point:起點、終點坐標 (x, y)
  • color:線條顏色 (B, G, R)
  • thickness:線寬,像素值

5.2 繪制矩形
cv2.rectangle(img, top_left, bottom_right, color, thickness)
  • top_leftbottom_right:左上角與右下角坐標
  • color:顏色
  • thickness:線寬,-1 表示填充

5.3 繪制圓形
cv2.circle(img, center, radius, color, thickness[, lineType])
  • center:圓心
  • radius:半徑
  • lineType:線型(cv2.LINE_AA 抗鋸齒,推薦)

5.4 繪制橢圓
cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness)
  • axes:長軸半徑,短軸半徑 (長, 短)
  • angle:橢圓旋轉角度
  • startAngleendAngle:起始角度,結束角度

5.5 繪制文本
cv2.putText(img, text, org, fontFace, fontScale, color, thickness[, lineType])
  • org:文本左下角坐標
  • fontFace:字體樣式(如 cv2.FONT_HERSHEY_COMPLEX
  • fontScale:字體大小縮放系數
  • lineTypecv2.LINE_AA 抗鋸齒

5.6 繪制多邊形
cv2.polylines(img, [pts], isClosed, color, thickness)
  • pts:多邊形頂點數組,形狀必須是 (-1, 1, 2)
  • isClosed:是否閉合
  • color:顏色
  • thickness:線寬
綜合案例:
import cv2 as cv
import numpy as npcat  = cv.imread('./images/1.jpg')
# 繪制直線 cv.line(img,start,end,color,thickness) (w,h)
cv.line(cat,(50,40),(80,40),(188,100,25),2)#繪制矩形 cv.rectangle(img,start(左上角),end(右下角),color,thickness(等于-1表示填充))
cv.rectangle(cat,(78,106),(237,306),(0,255,0),-1)#繪制圓形 cv.circle(img,center,radius,color,thickness)
# cv.LINE_AA 反走樣技術 抗鋸齒技術 平滑 默認使用的是LINE_8
cv.circle(cat,(325,269),30,(0,0,255),-1,cv.LINE_AA)#繪制橢圓形 cv.ellipse(img,center(中心點),axes(設置寬,高),angle,startAngle,endAngle,color,thickness)
cv.ellipse(cat,(550,550),(100,50),0,0,270,(255,0,0),3)#繪制文本 cv.putText(img,text,start,font,fontScale,color,thickness)
cv.putText(cat,'hello world',(10,500),cv.FONT_HERSHEY_COMPLEX,1,(255,255,255),2)#繪制多邊形 cv.polylines(img,points,isClosed,color,thickness)
pts = np.array([[10,5],[20,30],[70,20],[50,10]],np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(cat,[pts],True,(0,255,255),3)cv.imshow('cat',cat)
cv.waitKey(0)
cv.destroyAllWindows()

image-20250722191756670

難點解析:

在使用 cv.polylines() 時對 pts 進行 reshape((-1, 1, 2)) 轉換,是為了滿足 OpenCV 對多邊形頂點數據格式的硬性要求。具體原因如下:

1. cv.polylines() 對頂點格式的要求

cv.polylines()points 參數需要傳入一個形狀為 (N, 1, 2) 的 NumPy 數組,其中:

  • N 表示多邊形的頂點數量(例如你的例子中有 4 個頂點,N=4);
  • 中間的 1 是一個固定的維度(可理解為每個頂點被包裹在一個單元素數組中);
  • 最后的 2 表示每個頂點的 (x, y) 坐標。

這種格式本質上是 “頂點數組的數組”,即把每個頂點作為一個獨立的子數組,整體構成一個三維數組。

2. 為什么原始 pts 不符合要求?

你的原始頂點定義是:

pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)

此時 pts 的形狀是 (4, 2)(二維數組),表示 “4 個頂點,每個頂點有 x、y 兩個坐標”。但 OpenCV 不直接接受這種二維格式,必須轉換為三維格式 (4, 1, 2)

3. reshape((-1, 1, 2)) 的作用
  • -1 表示 “自動計算該維度的大小”(這里會自動計算為頂點數量 4);
  • 12 固定,強制將二維數組 (4, 2) 轉換為三維數組 (4, 1, 2)
4. 為什么沒有返回值?

在 OpenCV 中,繪圖函數(如 cv.linecv.rectanglecv.circle 等)的一個重要特性是:直接在原圖上進行修改,不返回新圖像。這是 OpenCV 設計上的一個核心特點,具體原因和細節如下:

  • 原地操作(In-place Operation)
    OpenCV 的繪圖函數會直接修改輸入的圖像數組(如代碼中的 cat),所有繪制的圖形(多邊形、線條等)都會直接 “畫” 在原圖上,因此不需要返回新圖像。
    這種設計的好處是節省內存—— 如果每次繪圖都返回新圖像,會額外占用一倍的內存空間(尤其對大圖像或批量處理不友好)。

  • 與 NumPy 數組的特性一致
    圖像在 OpenCV 中以 NumPy 數組的形式存儲,而 NumPy 數組的很多操作(如切片修改、數值更新)也是原地修改(不返回新數組)。繪圖函數遵循這一特性,保持了與數組操作邏輯的一致性。


六、視頻讀取與捕捉

6.1 cv2.VideoCapture() 方法

用于從攝像頭、視頻文件或視頻流中捕獲視頻

cap = cv2.VideoCapture(source[, apiPreference])
  • source:輸入源
    • 0:默認攝像頭
    • 12:外接攝像頭(編號遞增)
    • 'video.mp4':視頻文件路徑
    • 'rtsp://... ':RTSP/網絡視頻流
  • apiPreference(可選):指定使用的后端API(通常可省略)
    • cv2.CAP_DSHOW:Windows DirectShow
    • cv2.CAP_V4L2:Linux V4L2
    • cv2.CAP_FFMPEG:使用FFmpeg解碼

6.2 捕獲攝像頭實時視頻

cap = cv2.VideoCapture(0)  # 打開默認攝像頭while True:ret, frame = cap.read()  # 逐幀讀取if not ret:break  # 讀取失敗時退出cv2.imshow('camera', frame)# 按 q 鍵退出if cv2.waitKey(10) & 0xFF == ord('q'):breakcap.release()  # 釋放攝像頭
cv2.destroyAllWindows()  # 關閉窗口

6.3 讀取本地視頻文件

cap = cv2.VideoCapture('video.mp4')  # 替換自己本地的視頻文件while True:ret, frame = cap.read()if not ret:break  # 視頻結束或讀取失敗cv2.imshow('video', frame)if cv2.waitKey(30) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()

6.4 常用屬性設置與獲取

可以使用 cap.get()cap.set() 方法對視頻流參數進行讀取與修改

方法說明
cap.get(cv2.CAP_PROP_FRAME_WIDTH)獲取幀寬度
cap.get(cv2.CAP_PROP_FRAME_HEIGHT)獲取幀高度
cap.get(cv2.CAP_PROP_FPS)獲取幀率
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)設置幀寬度
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)設置幀高度

6.5 難點解析

1.為什么在讀取視頻流的時候不使用cv2.waitKey(0)?
  • cv2.waitKey(0) 的作用是

    無限等待,直到用戶按下任意鍵

  • 如果你寫在視頻播放循環里,會導致:

    • 第一幀暫停等待按鍵
    • 你不按鍵,程序就卡死在那里
    • 按下后,繼續下一幀,再次等待,變成每一幀都要你按鍵

🛑 這顯然不符合連續播放視頻的邏輯

🎯 小結:

用法場景
cv2.waitKey(0)靜態圖像,等待用戶操作
cv2.waitKey(n) (n > 0)視頻播放,循環內控制幀間隔,n越小刷新越快,越流暢
2.為什么在要使用&0XFF來操作?
  • cv2.waitKey() 返回的鍵值,有些系統/后端會返回 32位整數
  • 其中 低8位 才是實際的按鍵 ASCII 編碼

所以:

if cv2.waitKey(10) & 0xFF == ord('q'):break

是為了 屏蔽高位影響,確保兼容性

💡 示例說明:

  • 假設 cv2.waitKey() 返回了 0x00000071
  • ord('q') = 0x71
  • (0x00000071) & 0xFF = 0x71 ? 正常檢測

如果不加 & 0xFF,有的環境判斷就會失敗,保證鍵值兼容,避免系統差異

七、思維導圖

image-20250722195459380

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90371.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90371.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90371.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LangChain4j 兩種類型API

LangChain4j operates on two levels of abstraction: LangChain4j 提供了兩種類型API抽象Low level. At this level, you have the most freedom and access to all the low-level components such as ChatModel, UserMessage, AiMessage, EmbeddingStore, Embedd…

CLI 與 IDE 編碼代理比較:提升開發效率的兩種路徑

引言 在當今快速發展的軟件開發領域,人工智能編碼助手已成為開發者工具箱中不可或缺的一部分。根據行業報告,使用AI編碼助手可以將開發速度提高55%以上,同時顯著提升代碼質量。目前市場上主要有兩種類型的編碼代理:集成在IDE中的代…

【STM32】FreeRTOS 任務的創建(二)

這篇文章在于 詳細解釋 FreeRTOS 中任務的創建過程,包括任務創建的本質過程、API 詳解、兩種創建方式(動態/靜態)、任務函數規范、常見錯誤及實踐建議。 這里參照:RTOS官方文檔:https://www.freertos.org/zh-cn-cmn-s…

軟考 系統架構設計師系列知識點之面向服務架構設計理論與實踐(9)

接前一篇文章:軟考 系統架構設計師系列知識點之面向服務架構設計理論與實踐(8) 所屬章節: 第15章. 面向服務架構設計理論與實踐 第3節 SOA的參考架構 15.3 SOA的參考架構 IBM的Websphere業務集成參考架構(如圖15-2所示,以下簡稱參考架構)是典型的以服務為中心的企業集…

分區域材料設計:主承重區 / 次承重區 / 足弓區的彈性參數與刺激強度匹配

你是否總在為足部酸痛、膝蓋不適或腰背僵硬煩惱?穿了昂貴的緩震跑鞋,用了定制矯形器,問題卻反復出現?今天,我們要顛覆一個流傳百年的“常識”——腳不是脆弱的“需要被保護的對象”,而是被錯誤的設計“慣壞…

使用Qt下QAudioOutput播放聲音

導讀本項目目的是使用QAudioOutput播放聲音 ,音頻數據來源為ffmpeg解碼后的音頻數據。Qt音頻播放類說明 QAudioFormatQAudioFormat是Qt多媒體框架中用于定義音頻格式的核心類,用于設置音頻數據的參數,確保與硬件設備兼容。其主要功能和參數如…

日語學習-日語知識點小記-構建基礎-JLPT-N3階段(9):ようなN

日語學習-日語知識點小記-構建基礎-JLPT-N3階段(9):ようなN 1、前言(1)情況說明(2)工程師的信仰2、知識點(1)復習(2)復習&…

洛谷P1512 伊甸園日歷游戲

一開始,我發現有“必勝策略”,就知道是博弈論,然后看了兩種操作(月份1和天數1),于是想到用記憶化搜索找出所有的可能性 ,但不知道怎么判斷當前是否為先手必勝/必敗態,使用了TJ方法后…

Kafka——消費者組到底是什么?

引言在分布式系統中,消息中間件的核心價值在于高效地連接生產者與消費者,實現數據的可靠傳遞。然而,傳統消息引擎面臨一個兩難困境:如何在“消息不重復消費”與“系統可擴展性”之間找到平衡?點對點模型(如…

新mac電腦軟件安裝指南(前端開發用)

1. 下載git 未下載git直接下載homebrew也會提示你下載git 2. 下載homebrew 介紹: Homebrew 是 macOS 和 Linux 系統的開源包管理器?,通過命令行實現軟件的快速安裝、更新和管理,極大簡化了開發者及普通用戶的工作流程。 命令:…

【HarmonyOS】ArkUI 布局與容器組件

目錄前言一、線性布局(Column/Row)1.先布局后內容2.元素在主軸上的排列方式3.元素在交叉軸上的排列方式二、層疊布局(Stack)1.開發布局2.對齊方式三、彈性布局(Flex)四、創建列表(List)五、創建輪播(Swiper)1.基本用法2.常用屬性3.樣式自定義六、選項卡Tabs1.基本用法2.常用屬性…

MCNN-BiLSTM-Attention分類預測模型等!

MCNN-BiLSTM-Attention分類預測模型基于多尺度卷積神經網絡(MCNN)雙向長短期記憶網絡(BiLSTM)注意力機制(Attention)的分類預測模型,matlab代碼,直接運行使用!1、模型介紹:針對傳統方法在噪聲環境下診斷精度低的問題,提…

【Luogu】每日一題——Day12. P3149 排序 (樹狀數組 + 逆序對)

鏈接&#xff1a;P3149 排序 - 洛谷 題目&#xff1a; 思路&#xff1a; 經典搭配了 首先我們來分析以下操作的作用&#xff0c;如果我們選了 a[k]&#xff0c;那么對逆序對有什么影響呢&#xff1f; ①.對于 x y&#xff0c;且 x > a[k]&#xff0c;y < a[k] 由于 x…

電商項目_秒殺_架構升級

1. 秒殺當前架構設計nginx節點和訂單服務都可以方便的擴容&#xff08;增加機器&#xff09;redis擴容需則需要考慮架構設計當前架構面臨的痛點&#xff1a;秒殺系統redis是單節點&#xff08;主從&#xff09;部署&#xff0c;讀redis時并發量會成為瓶頸。所以考慮將增加redis…

CodeBuddy IDE發布:編程新時代的顛覆者?

開場&#xff1a;編程界的 “新風暴” 來襲 你能想象&#xff0c;不用敲一行代碼就能開發軟件嗎&#xff1f;這個曾經只存在于科幻電影里的場景&#xff0c;如今已經成為現實&#xff01;就在最近&#xff0c;編程界迎來了一場 “新風暴”——CodeBuddy IDE 重磅發布&#xff…

深度分析Java類加載機制

Java 的類加載機制是其實現平臺無關性、安全性和動態性的核心基石。它不僅僅是簡單地將 .class 文件加載到內存中&#xff0c;而是一個精巧、可擴展、遵循特定規則的生命周期管理過程。以下是對其深度分析&#xff1a; 一、核心概念與生命周期 一個類型&#xff08;Class 或 In…

神經網絡實戰案例:用戶情感分析模型

在當今數字化時代&#xff0c;用戶評論和反饋成為企業了解產品滿意度的重要渠道。本項目將通過神經網絡構建一個情感分析模型&#xff0c;自動識別用戶評論中的情感傾向。我們將使用真實的產品評論數據&#xff0c;從數據預處理到模型部署&#xff0c;完整展示神經網絡在NLP領域…

now能減少mysql的壓力嗎

是否用數據庫的 NOW() 能減少 MySQL 的壓力&#xff1f;?答案是否定的——使用 NOW() 不僅不會降低壓力&#xff0c;反而可能略微增加 MySQL 的負載。以下是詳細分析&#xff1a;&#x1f50d; 性能對比&#xff1a;NOW() vs. Java 傳參?指標??Java 傳參 (e.g., new Date()…

數據結構01:鏈表

數據結構 鏈表 鏈表和數組的區別 1. 存儲方式 數組&#xff1a; 元素在內存中連續存儲&#xff0c;占用一塊連續的內存空間元素的地址可以通過索引計算&#xff08;基地址 索引 元素大小&#xff09;大小固定&#xff0c;在創建時需要指定容量 鏈表&#xff1a; 元素&#xf…

【Java學習|黑馬筆記|Day21】IO流|緩沖流,轉換流,序列化流,反序列化流,打印流,解壓縮流,常用工具包相關用法及練習

標題【Java學習|黑馬筆記|Day20】 今天看的是黑馬程序員的《Java從入門到起飛》下部的95-118節&#xff0c;筆記包含IO流中的字節、字符緩沖流&#xff0c;轉換流&#xff0c;序列化流反序列化流&#xff0c;打印流&#xff0c;解壓縮流&#xff0c;常用工具包相關用法及練習 …