[Python]OpenCV 來啟用Cuda加速運算,比較CPU與GPU差異

更新於 發佈於 閱讀時間約 11 分鐘

OpenCV 提供了專門針對 CUDA 優化的模組,這些模組使用 cv2.cuda 命名空間,並且可以直接使用 GPU 進行加速。,cv2.cuda 模塊需要在 OpenCV 編譯時啟用 CUDA 支援才能使用。

本文主要比較經過CMAKE重新編譯OpenCV使其支援Cuda,原OpenCV只支援CPU運算,重新編譯過的OpenCV,某些模組就可支援CUDA使用GPU來運算。


CMAKE重新編譯文章

[OpenCV][Python]Win10+Cmake+VS2022編譯 OpenCV 及opencv_contrib


CUDA 支援的主要 OpenCV 模塊

  1. opencv_cudaimgproc:圖像處理模組,包含濾波、邊緣檢測、幾何轉換等操作。
  2. opencv_cudaarithm:算術運算,提供基本的矩陣和數學運算。
  3. opencv_cudafilters:濾波運算,如高斯模糊、邊緣檢測等。
  4. opencv_cudawarping:圖像幾何轉換,如旋轉、縮放、透視變換等。
  5. opencv_cudafeatures2d:特徵檢測和匹配模組。
  6. opencv_cudaoptflow:光流估算,適合視頻處理中的動態場景分析。
  7. opencv_cudastereo:立體匹配和視差估計。

CUDA 加速的使用限制

  1. 非通用支援:並不是 OpenCV 的所有模組和函數都能夠使用 GPU 進行加速。許多 OpenCV 的函數仍然只支持 CPU。
  2. 專用模塊的使用:要使用 GPU 加速,您必須使用 cv2.cuda 提供的函數。通常來說,這些函數會有 GPU 專屬版本,比如 cv2.cuda_GpuMat 用來替代 cv2.Mat
  3. 深度學習推理的限制:OpenCV 中的 dnn 模塊本身可以進行 CUDA 加速,但其他模型(如 DnnSuperResImpl_create)可能無法直接支持 GPU 加速。

邊緣檢測Canny比較

import cv2
import time

# CPU 版本的 Canny 邊緣檢測
def canny_edge_cpu(image):
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return cv2.Canny(image, 60, 150)

# CUDA 版本的 Canny 邊緣檢測,使用 opencv_cudaimgproc 模組
def canny_edge_cuda(image):
gpu_img = cv2.cuda_GpuMat()

# 如果需要,將圖片轉換為灰階
if len(image.shape) == 3: # 檢查圖片是否為彩色 (BGR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 將圖片上傳到 GPU 記憶體
gpu_img.upload(image)

# 創建 CUDA 版本的 Canny 邊緣檢測器
canny = cv2.cuda.createCannyEdgeDetector(60, 150)

# 執行 Canny 邊緣檢測
edges_gpu = canny.detect(gpu_img)

# 將結果從 GPU 下載回 CPU
result = edges_gpu.download()

return result

# 載入圖片
image = cv2.imread('D:/python/crab/Dnn_superres/111_out.png')

# 測量 CPU 版本 Canny 邊緣檢測的時間
start_time = time.time()
edges_cpu = canny_edge_cpu(image)
cpu_time = time.time() - start_time
print(f"CPU Canny 邊緣檢測時間:{cpu_time} 秒")

# 測量 CUDA 版本 Canny 邊緣檢測的時間
start_time = time.time()
edges_cuda = canny_edge_cuda(image)
cuda_time = time.time() - start_time
print(f"CUDA Canny 邊緣檢測時間:{cuda_time} 秒")

# 保存結果以進行比較
cv2.imwrite('edges_cpu.jpg', edges_cpu)
cv2.imwrite('edges_cuda.jpg', edges_cuda)
raw-image

左邊為CPU運算的結果,右邊為cuda.createCannyEdgeDetector的結果,結果是差不多的,但明顯CPU運算快很多。

raw-image

測試光流圖

將圖片移動X +20在存起來,來計算光流圖

raw-image
import cv2
import numpy as np
import time
import matplotlib.pyplot as plt

def cpu_dense_optical_flow(prev_frame, next_frame):
# 使用 Farneback 光流法進行稠密光流計算
flow = cv2.calcOpticalFlowFarneback(prev_frame, next_frame, None, 0.5, 3, 15, 3, 5, 1.2, 0)
return flow

def cuda_dense_optical_flow(prev_frame, next_frame):
# 將圖像上傳到 GPUMat
gpu_prev_frame = cv2.cuda_GpuMat()
gpu_next_frame = cv2.cuda_GpuMat()
gpu_prev_frame.upload(prev_frame)
gpu_next_frame.upload(next_frame)

# 創建 Farneback 光流實例
farneback = cv2.cuda_FarnebackOpticalFlow.create(5, 0.5, False, 15, 3, 5, 1.2, 0)

# 計算光流
flow = farneback.calc(gpu_prev_frame, gpu_next_frame, None)

# 將結果下載回 CPU
flow_cpu = flow.download()
return flow_cpu

# 讀取連續兩幀的灰度圖像
prev_frame = cv2.imread(r'D:\python\crab\Dnn_superres\111_out.png', cv2.IMREAD_GRAYSCALE)
next_frame = cv2.imread(r'D:\python\crab\Dnn_superres\111_out_1.png', cv2.IMREAD_GRAYSCALE)

# 計算 CPU 光流
start_time = time.time()
cpu_flow = cpu_dense_optical_flow(prev_frame, next_frame)
cpu_time = time.time() - start_time
print(f"CPU Dense Optical Flow time: {cpu_time} seconds")

# 計算 CUDA 光流
start_time = time.time()
gpu_flow = cuda_dense_optical_flow(prev_frame, next_frame)
gpu_time = time.time() - start_time
print(f"CUDA Dense Optical Flow time: {gpu_time} seconds")

# 計算兩者的差異
difference = np.abs(cpu_flow - gpu_flow)

# 可視化差異圖
plt.figure(figsize=(10, 10))

# 展示 CPU 光流結果
plt.subplot(1, 3, 1)
plt.title("CPU Optical Flow")
plt.imshow(np.sqrt(cpu_flow[..., 0]**2 + cpu_flow[..., 1]**2), cmap='gray')

# 展示 GPU 光流結果
plt.subplot(1, 3, 2)
plt.title("GPU Optical Flow")
plt.imshow(np.sqrt(gpu_flow[..., 0]**2 + gpu_flow[..., 1]**2), cmap='gray')

# 展示差異圖
plt.subplot(1, 3, 3)
plt.title("Difference (CPU - GPU)")
plt.imshow(np.sqrt(difference[..., 0]**2 + difference[..., 1]**2), cmap='hot')

plt.show()
raw-image
  1. CPU 光流圖:第一張圖顯示 CPU 計算的光流。
  2. GPU 光流圖:第二張圖顯示 GPU 計算的光流。
  3. 差異圖:第三張圖顯示 CPU 和 GPU 計算結果之間的差異。

差異圖會用熱圖 (hot colormap) 的形式展示差異,差異越大,顏色越亮。這樣可以很直觀地看到兩者之間的不同。

raw-image

總結:

CUDA 可以顯著加速某些高並行的運算,特別是那些對 GPU 高效能設計有充分利用的任務(如稠密光流、DNN)。

但對於簡單或低並行度的任務,CPU 的執行速度可能會更快,因為它沒有資料傳輸開銷,而且 CPU 的時脈速度通常更快。

因此,是否使用 CUDA 來加速 OpenCV 運算取決於任務的類型、資料量大小、影像解析度以及 GPU 的硬體條件。











留言
avatar-img
留言分享你的想法!
小松鼠-avatar-img
2024/10/10
謝謝螃蟹支持,假期愉快~
螃蟹_crab-avatar-img
發文者
2024/10/10
小松鼠 這一定要的~ :) 假期愉快
avatar-img
螃蟹_crab的沙龍
145會員
253內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
螃蟹_crab的沙龍的其他內容
2025/03/24
在影像處理或機器學習的應用中,我們常常需要將影片逐幀擷取出來,進一步進行辨識或分析。 本篇教學將示範如何使用 Python + OpenCV 來: ✅ 讀取 MP4 影片 測試影片可由下方超連結下載,從file-examples.com下載 file-examples.com 是一個 免費提
Thumbnail
2025/03/24
在影像處理或機器學習的應用中,我們常常需要將影片逐幀擷取出來,進一步進行辨識或分析。 本篇教學將示範如何使用 Python + OpenCV 來: ✅ 讀取 MP4 影片 測試影片可由下方超連結下載,從file-examples.com下載 file-examples.com 是一個 免費提
Thumbnail
2024/10/11
本文將指導你如何修改現有的 OpenCV 程式碼,使其利用 CUDA 加速進行深度神經網絡(DNN)推理,如超分辨率圖像放大任務。這將顯著提升運行速度,特別是在高分辨率圖像處理中。 在CMake上這選項要開,才可支援DNN模組。 CMake編譯OpenCV教學文 連結 [OpenCV][Py
Thumbnail
2024/10/11
本文將指導你如何修改現有的 OpenCV 程式碼,使其利用 CUDA 加速進行深度神經網絡(DNN)推理,如超分辨率圖像放大任務。這將顯著提升運行速度,特別是在高分辨率圖像處理中。 在CMake上這選項要開,才可支援DNN模組。 CMake編譯OpenCV教學文 連結 [OpenCV][Py
Thumbnail
2024/10/02
iPhone也有去背的功能,那麼OpenCV能不能做到這件事呢?,答案是可以的 如果圖像背景簡單且與前景有明顯的顏色區分,可以使用 色彩空間轉換 或 閥值分割。 如果背景較為複雜一點點,但你可以提供一個大致的前景位置,則可以使用 GrabCut。 結果圖 但在背景相當複雜的情況下,結果就不太
Thumbnail
2024/10/02
iPhone也有去背的功能,那麼OpenCV能不能做到這件事呢?,答案是可以的 如果圖像背景簡單且與前景有明顯的顏色區分,可以使用 色彩空間轉換 或 閥值分割。 如果背景較為複雜一點點,但你可以提供一個大致的前景位置,則可以使用 GrabCut。 結果圖 但在背景相當複雜的情況下,結果就不太
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
CUDA(Compute Unified Device Architecture) 是由 NVIDIA公司開發的並行計算平台 和 程式設計模型,主要用於利用 GPU(圖形處理器)的強大運算能力來加速通用計算任務。以下是其核心概念與應用: 一、核心概念 GPU 加速計算: 傳統上 G
Thumbnail
CUDA(Compute Unified Device Architecture) 是由 NVIDIA公司開發的並行計算平台 和 程式設計模型,主要用於利用 GPU(圖形處理器)的強大運算能力來加速通用計算任務。以下是其核心概念與應用: 一、核心概念 GPU 加速計算: 傳統上 G
Thumbnail
CUDA Core(通用計算單元) 是 NVIDIA GPU(圖形處理器)中的基本計算單元,專門設計用來執行並行計算任務。它們是 NVIDIA CUDA 平台的核心部分,用來處理圖形渲染和一般計算任務,特別是那些需要大規模數據運算的應用,例如遊戲圖形、科學模擬和人工智慧(AI)。 1. CUD
Thumbnail
CUDA Core(通用計算單元) 是 NVIDIA GPU(圖形處理器)中的基本計算單元,專門設計用來執行並行計算任務。它們是 NVIDIA CUDA 平台的核心部分,用來處理圖形渲染和一般計算任務,特別是那些需要大規模數據運算的應用,例如遊戲圖形、科學模擬和人工智慧(AI)。 1. CUD
Thumbnail
本文說明在安裝實體具有多核 GPU 的環境下,可以透過 Python 「多執行緒的」程式,讓 CPU 及 GPU 依照特性,各自同時進行運算,得到最好的算力配置。
Thumbnail
本文說明在安裝實體具有多核 GPU 的環境下,可以透過 Python 「多執行緒的」程式,讓 CPU 及 GPU 依照特性,各自同時進行運算,得到最好的算力配置。
Thumbnail
在上一篇文章,使用CUDA加速運行OpenCV發現一個異常,抽絲剝繭找到原因了。 [Python]在 OpenCV 中啟用 CUDA 加速來運行 DNN 超分辨率模型 錯誤描述: Could not locate cublas64_11.dll. Please make sure it i
Thumbnail
在上一篇文章,使用CUDA加速運行OpenCV發現一個異常,抽絲剝繭找到原因了。 [Python]在 OpenCV 中啟用 CUDA 加速來運行 DNN 超分辨率模型 錯誤描述: Could not locate cublas64_11.dll. Please make sure it i
Thumbnail
本文將指導你如何修改現有的 OpenCV 程式碼,使其利用 CUDA 加速進行深度神經網絡(DNN)推理,如超分辨率圖像放大任務。這將顯著提升運行速度,特別是在高分辨率圖像處理中。 在CMake上這選項要開,才可支援DNN模組。 CMake編譯OpenCV教學文 連結 [OpenCV][Py
Thumbnail
本文將指導你如何修改現有的 OpenCV 程式碼,使其利用 CUDA 加速進行深度神經網絡(DNN)推理,如超分辨率圖像放大任務。這將顯著提升運行速度,特別是在高分辨率圖像處理中。 在CMake上這選項要開,才可支援DNN模組。 CMake編譯OpenCV教學文 連結 [OpenCV][Py
Thumbnail
OpenCV 提供了專門針對 CUDA 優化的模組,這些模組使用 cv2.cuda 命名空間,並且可以直接使用 GPU 進行加速。,cv2.cuda 模塊需要在 OpenCV 編譯時啟用 CUDA 支援才能使用。 本文主要比較經過CMAKE重新編譯OpenCV使其支援Cuda,原OpenCV只支援
Thumbnail
OpenCV 提供了專門針對 CUDA 優化的模組,這些模組使用 cv2.cuda 命名空間,並且可以直接使用 GPU 進行加速。,cv2.cuda 模塊需要在 OpenCV 編譯時啟用 CUDA 支援才能使用。 本文主要比較經過CMAKE重新編譯OpenCV使其支援Cuda,原OpenCV只支援
Thumbnail
你還沒有編譯 OpenCV,那麼你需要先完成 OpenCV 的編譯過程,這樣才能生成 OpenCVConfig.cmake 文件。下面是一步一步的指南,幫助你在 Windows 上編譯 OpenCV。 本文主要介紹使用Cmake + VS2022來編譯OpenCV,最後目的是讓OpenCV可以利用
Thumbnail
你還沒有編譯 OpenCV,那麼你需要先完成 OpenCV 的編譯過程,這樣才能生成 OpenCVConfig.cmake 文件。下面是一步一步的指南,幫助你在 Windows 上編譯 OpenCV。 本文主要介紹使用Cmake + VS2022來編譯OpenCV,最後目的是讓OpenCV可以利用
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News