LoginSignup
2
0

More than 3 years have passed since last update.

GPUありなしでの、画像キャプチャー・OpenCV速度比較

Last updated at Posted at 2020-09-18

概要

最近、PCを新調しました。
以前、OpenCVで遊んでいたとき、画像処理のfpsが10fps程度しか出なくて、微妙だな~と思っていたので、PCを変えてどんな感じになったのか調べようと思います。
ついでにGPUについて、GTX1660superとIntel内蔵グラフィックで比較します。

すでに、たぶん誰かやってると思うのですが、見つからなかったので書いてます。
ほかに同じことをしている記事があったら教えてください。読みたい。

環境

  • Python3 (anaconda3導入-Spyderで実行)
  • Windows 10 Home 64bit

比較対象PCスペック

旧PC

  • core i5-6200U @2.3GHz 2core-4threads
  • Intel HD Graphics 520
  • 12GBメモリ
  • SSD

新PC-内蔵GPU

  • core i9-9900k @3.6GHz 8core-16threads
  • Intel HD Graphics 630
  • SSD

新PC-GPU

  • core i9-9900k @3.6GHz
  • Zotac GTX1660-super
  • SSD

Cine-bench R20 結果

PC ベンチ結果
旧PC 613
新PC-内蔵GPU 4741
新PC-GPU 4839

GPUには全く依存しません。

FFXV_bench

1920*1080,標準品質

PC ベンチ結果
旧PC 547:動作困難
新PC-内蔵GPU 708:動作困難
新PC-GPU 8379:快適

メモリがギリギリなのと、GPUがないと全然だめですね

画像キャプチャー bench

画像キャプチャー(mssライブラリ利用)

mss というライブラリの中で画面キャプチャができます。

pip install mss

が必要です。
time というライブラリで経過時間$[s]$を取得します。
1000回画面をキャプチャするのにかかった時間を比較します。
どこにボトルネックがあるかはわかりません。画像取得をせずに$while$ループさせると秒レベルでは計測できなかったので、画像キャプチャー部分

sct.grab(monitor)

に時間がかかっているので間違いないと思います。

PC
旧PC 16.7(60fps)
新PC-内蔵GPU 16.7(60fps)
新PC-GPU 16.7(60fps)

PCに接続しているディスプレイのリフレッシュレートが59.94Hzに設定されているため、こうなったと予想されます。

capture_test.py
import cv2          #   OpenCVライブラリ
import numpy as np      #   Numpyライブラリ
from mss import mss
import time

sct = mss()

"""
動作確認用:動作確認後はコメントアウト
"""
#windowName = "capture"
#cv2.namedWindow(windowName)

n= 0
while True:
    if n == 0:
        start_time = time.time()

    if n>= 1000:  #1000回 繰り返した
        end_time = time.time()
        break
    """
    画像取得
    """        
    monitor = {"top": 300, "left": 170, "width": 600, "height": 200}
    img = np.array(sct.grab(monitor))

    """
    動作確認部
    """
    """
    img = img[:,:,0:3]
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    img = np.asarray(img)
    cv2.imshow(windowName,img)
    key = cv2.waitKey(1)
    if key ==ord('q'):                 #       end 処理
        break
    """

    n = n+ 1

cv2.destroyAllWindows()
img[0][0][0] = 1         #一回も使わないと、ダメかなと思い追加

print(end_time-start_time)

画像キャプチャー(pyautoguiライブラリ利用)

有名なライブラリ"pyautogui"でやってみます。

PC
旧PC 68.1(15fpsに近い)
新PC-内蔵GPU 34.1(30fpsに近い)
新PC-GPU 33.4(30fpsに近い)

15,30,60fpsとPCの性能に合わせて切りのいい数になるよう調整している可能性があります。
mssと比べて、GPU,CPUともに負荷が少し高くなりました。キャプチャー範囲の影響はほぼなかったです。どのPCでも負荷率は上限から余裕があるので、なぜ性能差が出るのか不思議です。

ただ、旧PCの15fpsは流石に低すぎて使いにくいです。

capture_test_pyautogui.py
import cv2          #   OpenCVライブラリ
import numpy as np      #   Numpyライブラリ
import pyautogui
import time

"""
動作確認用:動作確認後はコメントアウト
"""
"""
windowName = "capture"
cv2.namedWindow(windowName)
"""
monitor = {"top": 300, "left": 170, "width": 600, "height": 600}
n= 0
while True:
    if n == 0:
        start_time = time.time()

    if n>= 1000:  #100回 繰り返した
        end_time = time.time()
        break
    """
    画像取得
    """        
    home = pyautogui.screenshot(region=(0,0,600,200))
    img = np.asarray(home)
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)

    """
    動作確認部
    """
    """
    img = img[:,:,0:3]
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    img = np.asarray(img)
    cv2.imshow(windowName,img)
    key = cv2.waitKey(1)
    if key ==ord('q'):                 #       end 処理
        break
    """

    n = n+ 1

cv2.destroyAllWindows()
img[0][0][0] = 1         #一回も使わないと、ダメかなと思い追加

print(end_time-start_time)

OpenCV bench

試してみたい関数を列挙します。

  • $cv2.matchTemplate$
  • $cv2.circle$
  • カメラキャプチャ(使用カメラは30fps)
  • $cv2.imshow$
  • $cv2.minMaxLoc$

基本的に、画像認識をしたいのでこんな感じです。

cv2.imshow

"同じ"画像を繰り返し表示するので、”違う画像”ではちょっと違う結果になるかもしれません。
画像の大きさに大きく影響を受けていました。
CPU負荷が高い気がします


画像サイズ100*100

PC
旧PC
新PC-内蔵GPU 0.015~0.017
新PC-GPU 0.017

画像サイズ300*300

PC
旧PC
新PC-内蔵GPU 0.08
新PC-GPU 0.083~0.084

画像サイズ800*800

PC
旧PC
新PC-内蔵GPU 1.20~1.23
新PC-GPU 1.11~1.13

画像サイズ2000*2000

PC
旧PC
新PC-内蔵GPU 8.5~8.9
新PC-GPU 8.0~8.2

結果

  • GPUの影響はほぼなく、CPU依存
  • 画面サイズの影響を強く受ける

ベンチコード

opencv_imshow.py
import cv2          #   OpenCVライブラリ
import numpy as np      #   Numpyライブラリ
import time

windowName = "capture"
cv2.namedWindow(windowName)

img = np.zeros((2000,2000,3))

n= 0
while True:
    if n == 0:
        start_time = time.time()

    if n>= 1000:  #100回 繰り返した
        end_time = time.time()
        break

    cv2.imshow(windowName,img)
    """
    #動作テスト
    key = cv2.waitKey(1)
    if key ==ord('q'):                 #       end 処理
        break
    """
    n = n+ 1

cv2.destroyAllWindows()
img[0][0][0] = 1         #一回も使わないと、ダメかなと思い追加

print(end_time-start_time)

cv2.circle

PC
旧PC 0.0239~0.0269
新PC-内蔵GPU 0.012
新PC-GPU 0.013

全然負荷はかからないようです。

opencv_circle.py
import cv2          #   OpenCVライブラリ
import numpy as np      #   Numpyライブラリ
import time

windowName = "capture"
cv2.namedWindow(windowName)

img = np.zeros((500,500,3))

n= 0
while True:
    if n == 0:
        start_time = time.time()

    if n>= 1000:  #100回 繰り返した
        end_time = time.time()
        break

    cv2.circle(img, (int(n*0.5),50), 10, (0, 0, 255), 4)

    """
    動作確認部
    """
    """
    cv2.imshow(windowName,img)
    key = cv2.waitKey(1)
    if key ==ord('q'):                 #       end 処理
        break
    """


    n = n+ 1

cv2.destroyAllWindows()
img[0][0][0] = 1         #一回も使わないと、ダメかなと思い追加

print(end_time-start_time)

cv2.matchTemplate

この処理は一番処理が重いイメージがあります。
また、画像サイズの影響を強く受けました。

PC 100回実行するのにかかった秒
旧PC
新PC-内蔵GPU
新PC-GPU 4.413

import cv2          #   OpenCVライブラリ
import numpy as np      #   Numpyライブラリ
import time

windowName = "capture"
cv2.namedWindow(windowName)

x = 100
y = 100
depth = 3
img = np.zeros((1000,1000,depth),dtype = np.uint8)
object1 = np.random.randint(0,255,(x,y,depth),dtype = np.uint8)

n= 0
while True:
    if n == 0:
        start_time = time.time()

    if n>= 100:  #100回 繰り返した
        end_time = time.time()
        break

    img_ccoeff = cv2.matchTemplate(img, object1, cv2.TM_CCOEFF_NORMED)

    n = n+ 1

cv2.destroyAllWindows()

print(end_time-start_time)

カメラキャプチャ(使用カメラは30fps)

cv2.minMaxLoc

PC 1000回実行するのにかかった秒
旧PC
新PC-内蔵GPU
新PC-GPU 0.255

まったく時間がかかっていないことがわかります。

minmaxLoc_bench.py
import cv2          #   OpenCVライブラリ
import numpy as np      #   Numpyライブラリ
import time

windowName = "capture"
cv2.namedWindow(windowName)

x = 100
y = 100
depth = 3
img = np.zeros((1000,1000,depth),dtype = np.uint8)
object1 = np.random.randint(0,255,(x,y,depth),dtype = np.uint8)
img_ccoeff = cv2.matchTemplate(img, object1, cv2.TM_CCOEFF_NORMED)

n= 0
while True:
    if n == 0:
        start_time = time.time()

    if n>= 1000:  #100回 繰り返した
        end_time = time.time()
        break

    cMin, cMax1, pMin, pMax1 = cv2.minMaxLoc(img_ccoeff)
    n = n+ 1

cv2.destroyAllWindows()

print(end_time-start_time)

すみません.dbdが楽しすぎてそれどころではなくなったので,とりあえず今はこれで公開して,余裕のある時に更新します.

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0