[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 的硬體條件。











119會員
201內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
發表第一個留言支持創作者!
螃蟹_crab的沙龍 的其他內容
iPhone也有去背的功能,那麼OpenCV能不能做到這件事呢?,答案是可以的 如果圖像背景簡單且與前景有明顯的顏色區分,可以使用 色彩空間轉換 或 閥值分割。 如果背景較為複雜一點點,但你可以提供一個大致的前景位置,則可以使用 GrabCut。 結果圖 但在背景相當複雜的情況下,結果就不太
以下是如何使用 Tesseract OCR 來辨識圖像中的文字的教學。 涵蓋了安裝 Tesseract、基本使用方法,以及如何在 Python 中進行整合。 1. 安裝 Tesseract 首先,需要安裝 Tesseract OCR 工具。這裡提供針對 Windows、macOS 和 Linu
本文主要介紹使用cv2.findContours找到圖像中最大物件的輪廓,再用cv2.minAreaRect取得該輪廓的最小矩形與旋轉角度,並將這些資訊印上圖像中的右上角。
在OpenCV中可以利用 cv2.findContours 判斷物件的形狀,可以通過計算輪廓的某些特徵來實現的。 本文主要利用cv2.arcLength與cv2.approxPolyDP來判斷三角形,正方形,矩形。檢查是否為圓形,則用通過輪廓面積和邊界框面積的比率來判斷。
先前文章有使用連通域分析來印出物件的位置及高寬面積及達成物件定位等功能。 [OpenCV應用][Python]利用連通域分析達成物件定位 [OpenCV基礎][Python]connectedComponent連通域分析 [OpenCV][Python]印出圖像中OCR面積及位置 這次我們將
本文主要使用pyzbar 與pylibdmtx來讀取條碼,並用靜態方法將這兩個套件的讀碼功能包裝起來,因應不同需求,調用相對應的方法來讀取QR code,一維條碼,Data Matrix。最後再將讀到的條碼資料與框選條碼位子於原圖上。
iPhone也有去背的功能,那麼OpenCV能不能做到這件事呢?,答案是可以的 如果圖像背景簡單且與前景有明顯的顏色區分,可以使用 色彩空間轉換 或 閥值分割。 如果背景較為複雜一點點,但你可以提供一個大致的前景位置,則可以使用 GrabCut。 結果圖 但在背景相當複雜的情況下,結果就不太
以下是如何使用 Tesseract OCR 來辨識圖像中的文字的教學。 涵蓋了安裝 Tesseract、基本使用方法,以及如何在 Python 中進行整合。 1. 安裝 Tesseract 首先,需要安裝 Tesseract OCR 工具。這裡提供針對 Windows、macOS 和 Linu
本文主要介紹使用cv2.findContours找到圖像中最大物件的輪廓,再用cv2.minAreaRect取得該輪廓的最小矩形與旋轉角度,並將這些資訊印上圖像中的右上角。
在OpenCV中可以利用 cv2.findContours 判斷物件的形狀,可以通過計算輪廓的某些特徵來實現的。 本文主要利用cv2.arcLength與cv2.approxPolyDP來判斷三角形,正方形,矩形。檢查是否為圓形,則用通過輪廓面積和邊界框面積的比率來判斷。
先前文章有使用連通域分析來印出物件的位置及高寬面積及達成物件定位等功能。 [OpenCV應用][Python]利用連通域分析達成物件定位 [OpenCV基礎][Python]connectedComponent連通域分析 [OpenCV][Python]印出圖像中OCR面積及位置 這次我們將
本文主要使用pyzbar 與pylibdmtx來讀取條碼,並用靜態方法將這兩個套件的讀碼功能包裝起來,因應不同需求,調用相對應的方法來讀取QR code,一維條碼,Data Matrix。最後再將讀到的條碼資料與框選條碼位子於原圖上。
你可能也想看
Google News 追蹤
Thumbnail
接下來第二部分我們持續討論美國總統大選如何佈局, 以及選前一週到年底的操作策略建議 分析兩位候選人政策利多/ 利空的板塊和股票
Thumbnail
🤔為什麼團長的能力是死亡筆記本? 🤔為什麼像是死亡筆記本呢? 🤨作者巧思-讓妮翁死亡合理的幾個伏筆
Thumbnail
本文將延續上一篇文章,經由訓練好的VAE模型其中的解碼器,來生成圖片。 [深度學習]訓練VAE模型用於生成圖片_訓練篇 輸入產生的隨機雜訊,輸入VAE的解碼器後,生成的圖片
Thumbnail
呈上篇文章,針對單排的圖像文字增加間隔,但如果文字是雙排呢 [OpenCV][Python]OCR分割及增加間隔[單排文字]
Thumbnail
在影像辨識中,若遇到物件與背景難以分辨的狀況下,先做一下色彩分析,知道了色彩強度階層上的像素數,有助於了解後續需要做什麼處理,比較好分割出辨識物。 若想辨識的物件與背景的RGB值過於接近,也比較好說明此狀況,為什麼較難分割出物件。 成果呈現 第一張圖:左邊為原圖,右邊為分析結果的圖,用其他顏
Thumbnail
此篇為上一篇文章的延伸,先辦別是螺絲還是螺母才擷取出影像。 [OpenCV應用][Python]利用findContours辨識螺絲還是螺母 因為可能會需要另外處理螺絲與螺母才可以準確地去做量測,所以第一步就是先分割出這兩種的圖像。
Thumbnail
常見的圖像銳利化方法: 銳化濾波器 增強對比度 Unsharp Masking
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和影像處理庫,它提供了豐富的功能和工具,可用於開發各種視覺應用程式。 OpenCV最初是用C++編寫的,但它也提供了Python、Java等多種程式語言的接口,方便不同語言的開發者使用。
Thumbnail
大部分在求物件的寬度及高度,都會想到用OpenCV的findContours函式來做,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度 [OpenCV應用][Python]利用findContours找出物件邊界框求出寬度及高度 本文將用不同的方法,利用Numpy
Thumbnail
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉
Thumbnail
接下來第二部分我們持續討論美國總統大選如何佈局, 以及選前一週到年底的操作策略建議 分析兩位候選人政策利多/ 利空的板塊和股票
Thumbnail
🤔為什麼團長的能力是死亡筆記本? 🤔為什麼像是死亡筆記本呢? 🤨作者巧思-讓妮翁死亡合理的幾個伏筆
Thumbnail
本文將延續上一篇文章,經由訓練好的VAE模型其中的解碼器,來生成圖片。 [深度學習]訓練VAE模型用於生成圖片_訓練篇 輸入產生的隨機雜訊,輸入VAE的解碼器後,生成的圖片
Thumbnail
呈上篇文章,針對單排的圖像文字增加間隔,但如果文字是雙排呢 [OpenCV][Python]OCR分割及增加間隔[單排文字]
Thumbnail
在影像辨識中,若遇到物件與背景難以分辨的狀況下,先做一下色彩分析,知道了色彩強度階層上的像素數,有助於了解後續需要做什麼處理,比較好分割出辨識物。 若想辨識的物件與背景的RGB值過於接近,也比較好說明此狀況,為什麼較難分割出物件。 成果呈現 第一張圖:左邊為原圖,右邊為分析結果的圖,用其他顏
Thumbnail
此篇為上一篇文章的延伸,先辦別是螺絲還是螺母才擷取出影像。 [OpenCV應用][Python]利用findContours辨識螺絲還是螺母 因為可能會需要另外處理螺絲與螺母才可以準確地去做量測,所以第一步就是先分割出這兩種的圖像。
Thumbnail
常見的圖像銳利化方法: 銳化濾波器 增強對比度 Unsharp Masking
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和影像處理庫,它提供了豐富的功能和工具,可用於開發各種視覺應用程式。 OpenCV最初是用C++編寫的,但它也提供了Python、Java等多種程式語言的接口,方便不同語言的開發者使用。
Thumbnail
大部分在求物件的寬度及高度,都會想到用OpenCV的findContours函式來做,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度 [OpenCV應用][Python]利用findContours找出物件邊界框求出寬度及高度 本文將用不同的方法,利用Numpy
Thumbnail
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉