カメラ制御」カテゴリーアーカイブ

SeeStarの自動化 SeeStar_alp

SeeStar_alp は、ASCOM Alpacaと組み合わせてSeeStarを自在に制御できる。また、標準のSeeStar APPと同時に併用できる点がすばらしい!

SeeStar_alpはサーバーとして機能し、pythomで記述されたスクリプト群であり、様々なプラットフォームで稼働できる。

https://github.com/smart-underworld/seestar_alp

Installation
Standalone package
Windows/Linux
The easiest way to install and run on Windows is to download a zip file that will allow you to run from one .exe file and everything will come up. If you want to run from source code then you will need to follow the Mac/Source install below.

Download win_seestar_alp.zip or linux_seestar_alp.zip from the lastest release tagged 1.1.0b1PullXXX at: https://github.com/rrowley42/seestar_alp/releases

SeeStar_alpをraspberry Piへインストールする専用のスクリプトが用意されている。

インストールが終わったら、http://SeeStar_alpのアドレス:5432/をブラウザーでアクセス。

ASCOM Alpacaの一般的な設定手順

Cartes du CielでASCOM Alpaca接続の設定画面

Stellariumの設定

流星観測データの処理手順

STEP-1 pythonスクリプト(detectMETEORa.py)でIPカメラから画像を取得し、動体検知のアルゴリズムを中心とした処理で、流星らしい動画(avi形式)を保存する。

STEP-2 記録した個々の動画をstreamlitスクリプト(play.py)でGUI操作で再生し、目視で流星と判断した動画について、COPYボタンをクリックして、1個のaviファイルから1枚のjpg画像を比較明合成アルゴリズムで生成し、同時にavi形式の動画からh264形式の動画(mp4形式)へ変換して保存する。

STEP-3 jpgファイルとmp4ファイルを、Webブラウザーでインタラクティブに閲覧できるよう、あらかじめ用意したフォルダーへCopyする。

ブラウザーで閲覧するためのphpコード ▶ボタンをクリックして、表示されている画像の動画を再生することが可能です。表示対象の画像を月単位で選択できます。

<?php

$day= new DateTime();

if (isset($_POST['month']) && ($_POST['month']!="")){
        $month=$_POST['month'];
        $f_month=str_replace("-","",$month);
} else {
        $month="";
}

echo "<div>";
echo "<H2>動画を再生するには、各画像左下の再生ボタンをクリックして下さい。</H2>";
echo "<LI>画像上へマウスオーバーするとファイル名を表示します。<BR>";
echo "ファイル名[カメラ名_検知フレーム数_総フレーム数_YYYYMMDD_HHmmSS.mp4]<BR>";
echo "<form method =\"POST\">\n";
echo "<BR><LABEL Date>月を変更するには年月欄の右端をクリックしてください。</LABEL>";
echo "<input type=\"month\" name=\"month\" value=$month>";
echo "<input type =\"submit\"  value =\"表示\">";
echo "</form></dev>";
//echo "$f_month<BR>\n";
$images = glob('meteor/COMP/*jpg');
$n=0;
foreach($images as $v) {
        if (strpos($v,$f_month)) {
                $tmp=explode(".",$v);
                $mp4=$tmp[0].".mp4";
                $mp4=str_replace("COMP","BEST2",$mp4);
                //echo "$mp4<BR>";
                $tmp=explode("/",$mp4);
                $title=$tmp[2];
                $msg="<video controls muted title=$title width='480' height='280' src=$mp4 poster=$v></video>";
                echo $msg;
                if ($n % 2 == 1){
                        echo "<BR>\n";
                }
                $n++;
        }
}
?>

ffmpeg -i infielavi -c:v libx264 -c:a copy -y out-file.mp4

Ubuntu22.04でOBS-Studio ( Virtual cameraの問題解決)

Ubuntu22.04でOBS-Studioを使ってみたら問題が発生。VirtualCameraの機能を最初は問題なく起動するが、一旦、VirtualCameraを停止すると、次に開始ボタンをクリックしても起動しない。(OSをリブートすると、再び使えるようになる)

この問題を解消する情報がネット上にあったので、手順を踏んでOKとなった。

https://github.com/obsproject/obs-studio/issues/4808

For Ubuntu users coming here after a recent upgrade to 22.04 LTS who are now running into this issue, the temporary downgrade/workaround discussed above still works:

Grab v4l2loopback-dkms_0.12.5-1_all.deb from https://packages.debian.org/sid/all/v4l2loopback-dkms/download
Install it: sudo dpkg -i v4l2loopback-dkms_0.12.5-1_all.deb
Hold it back so system updates don't wipe it out: sudo apt-mark hold v4l2loopback-dkms
Remove the hold in the future when upstream gets fixed: sudo apt-mark unhold v4l2loopback-dkms
The last version of v4l2loopback that worked properly is 0.12.5-1 and that's what we're installing above.
(Ubuntu 21.04 includes 0.12.5-1ubuntu1 and Ubuntu 22.04 includes 0.12.5-1ubuntu5)

ASI ZWOカメラをpythonで利用する

最初にASI_linux_mac_SDK_V1.21をインストール

ダウンロードのリンク 

Software and Drivers

ダウンロードして展開すると;

$ls ASI_linux_mac_SDK_V1.21
demo  doc  include  lib  license.txt
$ls ASI_linux_mac_SDK_V1.21/demo
Makefile  bin  main_SDK2_snap.cpp  main_SDK2_video.cpp  main_SDK2_video_mac  main_SDK2_video_mac.cpp  readme.txt

$cat readme.txt
Please install opencv2 at first, for example under Linux x86 OS, run:
make platform=x86
Below options is supported:
x86(Linux 32-bit)
x64(Linux 64-bit)
armv5
armv6
armv7
armv8
mac32
mac64
mac(32-bit and 64-bit)

If libASICamera2.so or (.dylib) can't be found at run time, resolve by delow two ways:
1.Add a .conf file that contains the path of the library to /etc/ld.so.conf.d/, run ldconfig.
2.Add compile option -Wl,-rpath=<library path>

raspberry pi4 64bit OSの場合 armv8

makeに先立って、demo/binの下へarmv8フォルダーを作る。

/usr/includeの下に、opencv2のファイル一式が必要。

root権限なしでカメラをアクセスできるようにするためのルールを追加

設定ファイル ASI_linux_mac_SDK_V1.21lib/asi.rulesをlib/udev/rules.d または/etc/udev/rules.dへCopyして、カメラを抜き差し。

$cd demo
$mkdir demo/bin/armv8
$make platform=armv8

$ ls demo/bin/armv8/
libASICamera2.so  main_SDK2_video_mac  test_gui2_snap  test_gui2_video

libASICamera2.so を参照できるよう、適切なフォルダーへ配置しldconfig

(あまり良い方法ではないが、/lib の下へlibASICamera2.soをCopy)

Pythonから利用できるようにライブラーをインストール

https://github.com/python-zwoasi/python-zwoasi

#!/usr/bin/env python

import argparse
import os
import sys
import time
import zwoasi as asi

env_filename = os.getenv('ZWO_ASI_LIB')

ZWO_ASI_LIBには、次のパスを設定

$ echo $ZWO_ASI_LIB
/home/pi/python-zwoasi/build/lib/zwoasi

$ ls /home/pi/python-zwoasi/build/lib/zwoasi

__init__.py の内容

"""Interface to ZWO ASI range of USB cameras.

Calls to the `zwoasi` module may raise :class:`TypeError` or :class:`ValueError` exceptions if an input argument
is incorrect. Failure conditions from within the module may raise exceptions of type :class:`ZWO_Error`. Errors from
conditions specifically from the SDK C library are indicated by errors of type :class:`ZWO_IOError`; certain
:func:`Camera.capture()` errors are signalled by :class:`ZWO_CaptureError`."""

import ctypes as c
from ctypes.util import find_library
import logging
import numpy as np
import os
import six
import sys
import time
import traceback


__author__ = 'Steve Marple'
__version__ = '0.1.0.1'
__license__ = 'MIT'


def get_num_cameras():
    """Retrieves the number of ZWO ASI cameras that are connected. Type :class:`int`."""
    return zwolib.ASIGetNumOfConnectedCameras()

Seleniumでスクレイピングの準備

$sudo apt-get update
$sudo apt install chromium-chromedriver
$sddo cp /usr/lib/chromium-browser/chromedriver /usr/bin
$pip install selenium
$pip install webdriver_manager

紛らわしい点:webdriver_managerとwebdrivermanagerの両方が存在し、機能が同じではない。webdriver_managerの方が良さそう。

Webサイトのタイトルを取得してみる。

from selenium import webdriver
import time

#---------------------------------------------------------------------------------------
# 処理開始
#---------------------------------------------------------------------------------------
# ブラウザをheadlessモード実行
print("\nブラウザを設定")
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',options=options)
driver.implicitly_wait(10)

# サイトにアクセス
print("サイトにアクセス開始")
URL="https://rfsec.ddns.net/db/"
driver.get(URL)
time.sleep(3)
# driver.find_elements_by_css_selector("xxx") 的な処理を自由に
print("サイトのタイトル:", driver.title)

認証があるサイトの場合(中華製ネットワークカメラ)

import time
import base64
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

def get_auth_header(user, password):
    b64 = "Basic " + base64.b64encode('{}:{}'.format(user, password).encode('utf-8')).decode('utf-8')
    return {"Authorization": b64}

# Webdriver ManagerでChromeDriverを取得
driver = webdriver.Chrome(executable_path=ChromeDriverManager().install())

# Authorizationヘッダを付与
driver.execute_cdp_cmd("Network.enable", {})
driver.execute_cdp_cmd("Network.setExtraHTTPHeaders", {"headers": get_auth_header("admin", "")})
# Basic認証が必要なページにアクセス
driver.get('http://192.168.68.128')
time.sleep(5)

driver.close()
driver.quit()

数独の問題サイトから問題を取得して、解く。

#  ここからがseleniumのコード
#  問題サイト http://numberplace.net/
#
from selenium import webdriver
import time
import numpy as np

def disp(results):
    msg=""
    for r in results:
        for y in range(9):
            for x in range(9):
                c = r._values[y][x]
                c = str(c)
                d = row2[y][x]
                if d != 0:
                    msg=msg+'('+ c + ') '
                else:
                    msg=msg+'-'+ c + '- ' 
            msg=msg+"\n"
    print(msg)

#---------------------------------------------------------------------------------------
# 処理開始
#---------------------------------------------------------------------------------------
# ブラウザをheadlessモード実行
print("\nブラウザを設定")
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',options=options)
driver.implicitly_wait(2)

# サイトにアクセス
for num in range(5):
    URL="http://numberplace.net/?no="+str(num+1)
    print("サイトにアクセス開始:",URL)
    driver.get(URL)
    time.sleep(2)
    lines= driver.page_source.splitlines()
    for line in lines:
        if 'toi' in line:
            q = line.split(' ')[3].replace("'","").replace(";","")
            q=list(q)
            #print(q)
            qi = [int(s) for s in q]
            #print(qi)
            q2 = np.array(qi)
            row2=np.array(q2).reshape(-1,9).tolist()
            grid = solver.Grid(row2)
            print(grid)
            results = solver.solve_all(grid)
            disp(results)
            break
print('Done.')

ISSの太陽面通過の撮影

国際宇宙ステーションが、太陽や月面の前を通過する日時・場所を、ISS TRANSIT FINDERで知ることができます。

11月25日に、自宅から少し離れた河川敷公園で、 国際宇宙ステーションの太陽面の通過を観測できそうなので、器材一式(カメラ、小型赤道儀、三脚)を持って撮影にトライしてみました。 今回のタイミングでは、ISSまでの距離が1600Km以上と、かなり遠いためISSらしい機影までは、確認に至りませんでしたが、撮影までの一連の流れを確認できました。下の画面では縮小されて見ずらいので、youtubeで表示した方が見やすいと思います。ISSは、右下から左上方向に移動します。

課題

カメラの撮影パラメータの適切化(動画/静止画、Iシャッター速度、撮影モード(連写/高速連写など、、、)

撮影器材

カメラ:NIKON P950、赤道儀:Az-GTi

おまけ:撮影の準備中に航空機が太陽面を通過する映像を記録できました。

streamlitで流星観測データを表示

# -*- coding: utf-8 -*-

import streamlit as st
import time
import datetime
import os
import glob
import cv2
import re
import numpy as np
from PIL import Image
from datetime import datetime, date, time

PATH='/home/metro//DATA/'

def comp_b2(A,B):
# 比較明合成処理
# https://nyanpyou.hatenablog.com/entry/2020/03/20/132937
#
    gray_img1 = cv2.cvtColor(A, cv2.COLOR_BGR2GRAY)
    gray_img2 = cv2.cvtColor(B, cv2.COLOR_BGR2GRAY)
#グレースケールの比較で作成したimg1用のマスク(img1の方が明るい画素を示す)
    mask_img1 = np.where(gray_img1>gray_img2, 255, 0).astype(np.uint8)
#img2用のマスク(0と255を入れ替え)(img2の方が明るい画素を示す)
    mask_img2 = np.where(mask_img1==255, 0, 255).astype(np.uint8)

#作成したマスクを使って元画像から抜き出し
    masked_img1 = cv2.bitwise_and(A, A, mask=mask_img1)
    masked_img2 = cv2.bitwise_and(B, B, mask=mask_img2)

    img3 = masked_img1 + masked_img2
    return img3

def disp(device):
        n=0
        cap = cv2.VideoCapture(device)
        W = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        H = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        W2=int(W/2)
        H2=int(H/2)
        image_loc = st.empty()
        prev=None
        while cap.isOpened:
            ret, img = cap.read()
            if ret:
                if W==1920:
                    img=cv2.resize(img, dsize=(W2, H2))
                #time.sleep(0.01)
                if prev is None:
                    prev = img.copy()
                else:
                    E = comp_b2(prev,img)
                    prev = E
                img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
                image_loc.image(img)
            else:
                break

        cap.release()
        image_loc = st.empty()
        img = Image.fromarray(cv2.cvtColor(prev, cv2.COLOR_BGR2RGB))
        image_loc.image(img)
    #st.button('Replay')

def main():
    st.header("流星観測データの表示")
    col1, col2, col3 = st.columns([1,1,3])
    with col1:
        date=st.date_input('DATE')
    path=PATH+date.strftime("%Y%m%d")
    selected=[]
    f_name=[]
    TL=[]
    if os.path.exists(path):
        files=glob.glob(path+'/*avi')
        # time filter : m[4] is time field.
        if files is not(None):
            for opt in files:
                m=re.split('[_.]',opt)
                TL.append(int(int(m[4])/10000))
            TL=list(set(TL))                        # sortして重複を削除
            # 処理対象の時間帯を選択するセレクトBOXの表示
            with col2:
                selected_item = st.selectbox('TIME',TL)
            selT = int(selected_item)
            for opt in files:
                m=re.split('[_.]',opt)
                if len(m)>=4:
                    t = int(int(m[4])/10000)
            #if not(t>60000 and t<180000):
                    if t==selT:
                        selected.append(opt)

            if selected is not(None):
                for name in selected:
                    f_name.append(name.rsplit('/',1)[1])
                with col3:
                    option = st.selectbox('FILE to DISPLAY',f_name)
            if option is not(None):
                disp(path+'/'+option)
    else:
        st.write('No data exists!')

if __name__ == '__main__':
    main()

streamlitで動画を再生

# -*- coding: utf-8 -*-

import streamlit as st
import time
import datetime
import os
import glob
import cv2
from PIL import Image
from datetime import datetime, date, time

PATH='/home/mars/pWork/DATA/'

def disp(device):
    cap = cv2.VideoCapture(device)
    image_loc = st.empty()
    while cap.isOpened:
        ret, img = cap.read()
        if ret:
            img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
            image_loc.image(img)
        else:
            break

    cap.release()
    st.button('Replay')

def main():
    st.header("流星観測データの表示")
    date=st.date_input('Select date')
    path=PATH+date.strftime("%Y%m%d")
    #st.write(path)
    if os.path.exists(path):
        files=glob.glob(path+'/*avi')
        option = st.selectbox('Select file:',files)
        disp(option)
    else:
        st.write('No data exists!')

if __name__ == '__main__':
    main()

ファイルの選択対象を、様々な条件で絞りこむコードを追加したい。

cudaとThread対応のテスト

複数台のネットワークカメラに対応し、cuda(GPU)とThread機能を活用できるバージョン。

import cv2
import numpy as np
import time
import datetime
import os
import sys
GPU=True
THREAD=True
if len(sys.argv)>1:
    if sys.argv[1]=='A':
        cPATH='rtsp://5173:6703@192.168.68.74/live'
    else:
        cPATH='rtsp://admin:@192.168.68.128:554/1/h264major'
else:
        cPATH='rtsp://5173:6703@192.168.68.74/live'
PATH="/home/mars/pWork/DATA"
#

class ThreadingVideoCapture:
    def __init__(self, src, max_queue_size=256):
        self.video = cv2.VideoCapture(src)
        self.q = queue.Queue(maxsize=max_queue_size)
        self.stopped = False

    def start(self):
        thread = threading.Thread(target=self.update, daemon=True)
        thread.start()
        return self

    def update(self):
        while True:
            if self.stopped:
                return
            if not self.q.full():
                ok, frame = self.video.read()
                self.q.put((ok, frame))
                if not ok:
                    self.stop()
                    return

    def read(self):
        return self.q.get()

    def stop(self):
        self.stopped = True

    def release(self):
        self.stopped = True
        self.video.release()

    def isOpened(self):
        return self.video.isOpened()

    def get(self, i):
        return self.video.get(i)

def key(k):
    global th, tc,track,reverse
    if k == ord('2'):
        th = th - 1
    elif k == ord('3'):
        th = th + 1
    elif k == ord('4'):
        tc = tc -5
    elif k == ord('5'):
        tc = tc +5
    elif k == ord('t'):
        track = not track
    elif k == ord('r'):
        reverse = not reverse

fontFace =cv2.FONT_HERSHEY_SIMPLEX
track, reverse = False,False
avg=None
writer = None
th = 30
tc = 30
x,y=0,0
detect_counts = 0
red,blue,green = (0,0,255),(255,0,0),(0,255,0)
time_start = time.time()
frame=0
log=PATH+'/metro.log'
if cPATH=='rtsp://5173:6703@192.168.68.74/live':
    TITLE="ATOM"
    HEAD ='ATOM'
else:
    TITLE="ONVIF"
    HEAD='ONVIF'

if THREAD:
    import threading
    import queue
    TITLE=TITLE+"-T"
    capture = ThreadingVideoCapture(cPATH)
    capture.start()
    if not capture.isOpened():
        raise RuntimeError
else:
    capture=cv2.VideoCapture(cPATH)

if GPU:
    TITLE=TITLE+"-G"
    img_gpu_src = cv2.cuda_GpuMat() # Allocate device memory only once, as memory allocation seems to take time...
    img_gpu_dst = cv2.cuda_GpuMat()
    img_gpu_gray= cv2.cuda_GpuMat()

W = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
H = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
W2=int(W/2)
H2=int(H/2)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
print('Camera:',cPATH)
print('Size:',W,H)
while(True):
    ret, img = capture.read()
    if ret:
        org = img.copy()
        if GPU:
            img_gpu_src.upload(img)
            img_gpu_dst = cv2.cuda.resize(img_gpu_src, dsize=(W2, H2))
            img_gpu_dst = cv2.cuda_GpuMat(img_gpu_dst,[0,int(H2*0.85)],[0,W2])
            img_gpu_gray=cv2.cuda.cvtColor(img_gpu_dst,cv2.COLOR_BGR2GRAY)
            org_img=img_gpu_dst.download()
            gray = img_gpu_gray.download()
        else:
            org_img = cv2.resize(img, dsize=(W2, H2))
            org_img=img[0:int(H2*0.85),0:W2]
            gray = cv2.cvtColor(org_img, cv2.COLOR_BGR2GRAY)
        if reverse:
            gray=cv2.bitwise_not(gray)
            avg=cv2.bitwise_not(avg)
        if avg is None:
            avg = gray.copy().astype("float")
            continue

        #wtiter,fname = moving(img,avg)
        cv2.accumulateWeighted(gray, avg, 0.5)
        frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))
        thresh = cv2.threshold(frameDelta, th, 255, cv2.THRESH_BINARY)[1]

        contours,hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        detect=False
        for i in range(0,len(contours)):
            if len(contours[i]) > 0:
                 if cv2.contourArea(contours[i]) > tc:
                    detect=True
                    time_start = time.time()
                    if writer is None and track:
                        detect_counts = 0
                        now=datetime.datetime.today()
                        date=now.strftime("%Y%m%d")
                        cDIR=PATH+'/'+date
                        if not(os.path.exists(cDIR)):
                            os.mkdir(cDIR)
                        fname=cDIR+'/'+ HEAD + now .strftime("%Y%m%d_%H%M%S")+".avi"
                        writer = cv2.VideoWriter(fname, fourcc, 15, (int(W), int(H)))
                    rect = contours[i]
                    x, y, w, h = cv2.boundingRect(rect)
                    cv2.rectangle(org_img, (x-w, y-h), (x + w*2, y + h*2), red, 3)
        if detect:
            detect_counts=detect_counts + 1
        if time.time() -  time_start  > 5:
            if writer is not None:
                writer.release()
                new_name=fname.replace(HEAD,HEAD+'_' + f'{detect_counts:04}'+'_')
                os.rename(fname,new_name)
                frame=0
                writer = None
        now=datetime.datetime.today()
        text=now.strftime("%Y%m%d %H%M%S")+' No:'+str(frame)+ ' '+" TH:"+str(th)+" SZ:"+str(tc)
        org_img = cv2.putText(org_img, text, (30,50), fontFace,1,color=green)
        org = cv2.putText(org, text, (30,50), fontFace,1,color=green)
        text1="REC:"+str(track) + "  reverse:" + str(reverse)
        if writer is not None:
            frame=frame+1
            text1=fname+' '+text1
        org_img = cv2.putText(org_img, text1, (30,80), fontFace,1,color=green)
        #cv2.imshow('thresh-level',thresh)

        cv2.imshow(TITLE,org_img)

        if writer is not None:
            writer.write(org)
    else:
        now=datetime.datetime.today()
        date=now.strftime("%Y%m%d_%H%M%S")
        print('reconnect:',date)
        capture.release()
        avg=None
        if THREAD:
            capture = ThreadingVideoCapture(cPATH)
            capture.start()
        else:
            capture = cv2.VideoCapture(cPATH)
    k=cv2.waitKey(1) & 0xFF
    key(k)
    if k== ord('q'):
        break

capture.release()
if writer is not None:
    writer.release()
    new_name=fname.replace(HEAD,HEAD+'_' + f'{detect_counts:04}'+'_')
    os.rename(fname,new_name)
cv2.destroyAllWindows()

jetson nanoでcv2(cuda有効化)

ソースからインストール

python3でcv2をimportすると crashしてコアーダンプ。

問題の解決:export OPENBLAS_CORETYPE=ARMV8

こちらを参照して解決。Jetson NanoのPython3環境でIllegal instruction (cpre dumped)

処理速度の比較測定:約3倍

$ sudo nvpmodel -m 0
$ sudo jetson_clocks
$ python3 opencv_cuda.py
CPU = 2.7655137538909913[msec]
GPU = 1.0501614570617677[msec]
1
$ python3 opencv_cuda.py
CPU = 2.7816075325012206[msec]
GPU = 0.9869620561599731[msec]
1

opencv_cuda.py

import sys
import time
import cv2

### VALUES
NUM_REPEAT = 10000

### Read source image
img_src = cv2.imread("resource/lena.jpg")
cv2.imshow('img_src', img_src)


### Run with CPU
time_start = time.time()
for i in range (NUM_REPEAT):
    img_dst = cv2.resize(img_src, (300, 300))
time_end = time.time()
print ("CPU = {0}".format((time_end - time_start) * 1000 / NUM_REPEAT) + "[msec]")
cv2.imshow('CPU', img_dst)


### Run with GPU
img_gpu_src = cv2.cuda_GpuMat() # Allocate device memory only once, as memory allocation seems to take time...
img_gpu_dst = cv2.cuda_GpuMat()
time_start = time.time()
for i in range (NUM_REPEAT):
    img_gpu_src.upload(img_src)
    img_gpu_dst = cv2.cuda.resize(img_gpu_src, (300, 300))
    img_dst = img_gpu_dst.download()
time_end = time.time()
print ("GPU = {0}".format((time_end - time_start) * 1000 / NUM_REPEAT) + "[msec]")
cv2.imshow('GPU', img_dst)


key = cv2.waitKey(0)
cv2.destroyAllWindows()

print(cv2.cuda.getCudaEnabledDeviceCount())

cudaで利用できる機能を表示してみる

import cv2
cv2.__version__
dir(cv2.cuda)
['ALPHA_ATOP',
 'ALPHA_ATOP_PREMUL',
 'ALPHA_IN',
 'ALPHA_IN_PREMUL',
 'ALPHA_OUT',
 'ALPHA_OUT_PREMUL',
 'ALPHA_OVER',
 'ALPHA_OVER_PREMUL',
 'ALPHA_PLUS',
 'ALPHA_PLUS_PREMUL',
 'ALPHA_PREMUL',
 'ALPHA_XOR',
 'ALPHA_XOR_PREMUL',
 'BroxOpticalFlow_create',
 'COLOR_BAYER_BG2BGR_MHT',
 'COLOR_BAYER_BG2GRAY_MHT',
 'COLOR_BAYER_BG2RGB_MHT',
 'COLOR_BAYER_GB2BGR_MHT',
 'COLOR_BAYER_GB2GRAY_MHT',
 'COLOR_BAYER_GB2RGB_MHT',
 'COLOR_BAYER_GR2BGR_MHT',
 'COLOR_BAYER_GR2GRAY_MHT',
 'COLOR_BAYER_GR2RGB_MHT',
 'COLOR_BAYER_RG2BGR_MHT',
 'COLOR_BAYER_RG2GRAY_MHT',
 'COLOR_BAYER_RG2RGB_MHT',
 'COLOR_BayerBG2BGR_MHT',
 'COLOR_BayerBG2GRAY_MHT',
 'COLOR_BayerBG2RGB_MHT',
 'COLOR_BayerGB2BGR_MHT',
 'COLOR_BayerGB2GRAY_MHT',
 'COLOR_BayerGB2RGB_MHT',
 'COLOR_BayerGR2BGR_MHT',
 'COLOR_BayerGR2GRAY_MHT',
 'COLOR_BayerGR2RGB_MHT',
 'COLOR_BayerRG2BGR_MHT',
 'COLOR_BayerRG2GRAY_MHT',
 'COLOR_BayerRG2RGB_MHT',
 'CascadeClassifier_create',
 'DEVICE_INFO_COMPUTE_MODE_DEFAULT',
 'DEVICE_INFO_COMPUTE_MODE_EXCLUSIVE',
 'DEVICE_INFO_COMPUTE_MODE_EXCLUSIVE_PROCESS',
 'DEVICE_INFO_COMPUTE_MODE_PROHIBITED',
 'DYNAMIC_PARALLELISM',
 'DensePyrLKOpticalFlow_create',
 'DescriptorMatcher_createBFMatcher',
 'DeviceInfo_ComputeModeDefault',
 'DeviceInfo_ComputeModeExclusive',
 'DeviceInfo_ComputeModeExclusiveProcess',
 'DeviceInfo_ComputeModeProhibited',
 'EVENT_BLOCKING_SYNC',
 'EVENT_DEFAULT',
 'EVENT_DISABLE_TIMING',
 'EVENT_INTERPROCESS',
 'Event_BLOCKING_SYNC',
 'Event_DEFAULT',
 'Event_DISABLE_TIMING',
 'Event_INTERPROCESS',
 'Event_elapsedTime',
 'FEATURE_SET_COMPUTE_10',
 'FEATURE_SET_COMPUTE_11',
 'FEATURE_SET_COMPUTE_12',
 'FEATURE_SET_COMPUTE_13',
 'FEATURE_SET_COMPUTE_20',
 'FEATURE_SET_COMPUTE_21',
 'FEATURE_SET_COMPUTE_30',
 'FEATURE_SET_COMPUTE_32',
 'FEATURE_SET_COMPUTE_35',
 'FEATURE_SET_COMPUTE_50',
 'FarnebackOpticalFlow_create',
 'FastFeatureDetector_create',
 'GLOBAL_ATOMICS',
 'GpuMat_defaultAllocator',
 'GpuMat_setDefaultAllocator',
 'HOG_create',
 'HOST_MEM_PAGE_LOCKED',
 'HOST_MEM_SHARED',
 'HOST_MEM_WRITE_COMBINED',
 'HostMem_PAGE_LOCKED',
 'HostMem_SHARED',
 'HostMem_WRITE_COMBINED',
 'NATIVE_DOUBLE',
 'NVIDIA_OPTICAL_FLOW_1_0_NV_OF_PERF_LEVEL_FAST',
 'NVIDIA_OPTICAL_FLOW_1_0_NV_OF_PERF_LEVEL_MAX',
 'NVIDIA_OPTICAL_FLOW_1_0_NV_OF_PERF_LEVEL_MEDIUM',
 'NVIDIA_OPTICAL_FLOW_1_0_NV_OF_PERF_LEVEL_SLOW',
 'NVIDIA_OPTICAL_FLOW_1_0_NV_OF_PERF_LEVEL_UNDEFINED',
 'NvidiaOpticalFlow_1_0_NV_OF_PERF_LEVEL_FAST',
 'NvidiaOpticalFlow_1_0_NV_OF_PERF_LEVEL_MAX',
 'NvidiaOpticalFlow_1_0_NV_OF_PERF_LEVEL_MEDIUM',
 'NvidiaOpticalFlow_1_0_NV_OF_PERF_LEVEL_SLOW',
 'NvidiaOpticalFlow_1_0_NV_OF_PERF_LEVEL_UNDEFINED',
 'NvidiaOpticalFlow_1_0_create',
 'ORB_create',
 'OpticalFlowDual_TVL1_create',
 'SHARED_ATOMICS',
 'SURF_CUDA_ANGLE_ROW',
 'SURF_CUDA_HESSIAN_ROW',
 'SURF_CUDA_LAPLACIAN_ROW',
 'SURF_CUDA_OCTAVE_ROW',
 'SURF_CUDA_ROWS_COUNT',
 'SURF_CUDA_SIZE_ROW',
 'SURF_CUDA_X_ROW',
 'SURF_CUDA_Y_ROW',
 'SparsePyrLKOpticalFlow_create',
 'StereoBeliefPropagation_estimateRecommendedParams',
 'StereoConstantSpaceBP_estimateRecommendedParams',
 'Stream_Null',
 'TargetArchs_has',
 'TargetArchs_hasBin',
 'TargetArchs_hasEqualOrGreater',
 'TargetArchs_hasEqualOrGreaterBin',
 'TargetArchs_hasEqualOrGreaterPtx',
 'TargetArchs_hasEqualOrLessPtx',
 'TargetArchs_hasPtx',
 'WARP_SHUFFLE_FUNCTIONS',
 '__doc__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 'abs',
 'absSum',
 'absdiff',
 'add',
 'addWeighted',
 'alphaComp',
 'bilateralFilter',
 'bitwise_and',
 'bitwise_not',
 'bitwise_or',
 'bitwise_xor',
 'blendLinear',
 'buildWarpAffineMaps',
 'buildWarpPerspectiveMaps',
 'calcAbsSum',
 'calcHist',
 'calcNorm',
 'calcNormDiff',
 'calcSqrSum',
 'calcSum',
 'cartToPolar',
 'compare',
 'copyMakeBorder',
 'countNonZero',
 'createBackgroundSubtractorMOG',
 'createBackgroundSubtractorMOG2',
 'createBoxFilter',
 'createBoxMaxFilter',
 'createBoxMinFilter',
 'createCLAHE',
 'createCannyEdgeDetector',
 'createColumnSumFilter',
 'createContinuous',
 'createConvolution',
 'createDFT',
 'createDerivFilter',
 'createDisparityBilateralFilter',
 'createGaussianFilter',
 'createGeneralizedHoughBallard',
 'createGeneralizedHoughGuil',
 'createGoodFeaturesToTrackDetector',
 'createHarrisCorner',
 'createHoughCirclesDetector',
 'createHoughLinesDetector',
 'createHoughSegmentDetector',
 'createLaplacianFilter',
 'createLinearFilter',
 'createLookUpTable',
 'createMedianFilter',
 'createMinEigenValCorner',
 'createMorphologyFilter',
 'createRowSumFilter',
 'createScharrFilter',
 'createSeparableLinearFilter',
 'createSobelFilter',
 'createStereoBM',
 'createStereoBeliefPropagation',
 'createStereoConstantSpaceBP',
 'createTemplateMatching',
 'cvtColor',
 'demosaicing',
 'dft',
 'divide',
 'drawColorDisp',
 'ensureSizeIsEnough',
 'equalizeHist',
 'evenLevels',
 'exp',
 'findMinMax',
 'findMinMaxLoc',
 'flip',
 'gammaCorrection',
 'gemm',
 'getCudaEnabledDeviceCount',
 'getDevice',
 'histEven',
 'histRange',
 'integral',
 'log',
 'magnitude',
 'magnitudeSqr',
 'max',
 'meanShiftFiltering',
 'meanShiftProc',
 'meanShiftSegmentation',
 'meanStdDev',
 'merge',
 'min',
 'minMax',
 'minMaxLoc',
 'mulAndScaleSpectrums',
 'mulSpectrums',
 'multiply',
 'norm',
 'normalize',
 'phase',
 'polarToCart',
 'pow',
 'printCudaDeviceInfo',
 'printShortCudaDeviceInfo',
 'pyrDown',
 'pyrUp',
 'rectStdDev',
 'reduce',
 'registerPageLocked',
 'remap',
 'reprojectImageTo3D',
 'resetDevice',
 'resize',
 'rotate',
 'setBufferPoolConfig',
 'setBufferPoolUsage',
 'setDevice',
 'split',
 'sqr',
 'sqrIntegral',
 'sqrSum',
 'sqrt',
 'subtract',
 'sum',
 'threshold',
 'transpose',
 'unregisterPageLocked',
 'warpAffine',
 'warpPerspective']