IC Imaging Control (Python)

  • サンプルプログラムトップページ
  • デバイスのオープンとハンドリング
    • デバイスを開く
    • ダイアログボックスを使用してデバイスを開く
    • デバイスプロパティ設定の保存と復元
    • プロパティの設定方法
    • 接続しているカメラ一覧を表示
    • ROIの設定方法
    • オートフォーカスで焦点を調整する範囲を指定
    • デバイスロストの検出と再接続方法
  • イメージの取得
    • 8bit静止画保存
    • 16bit静止画保存
    • Enterキーを押下したときに画像保存
    • メモリーレコーディング
    • AVIファイル保存
  • 画像処理
    • コールバック関数の設定方法(OpenCVで二値化)
    • OpenCVで画像処理して表示する方法
    • ソフトウェアトリガー・外部トリガーの使用方法
    • ステレオカメラで表示
    • 2つのカメラで取得した画像の輝度値を平均してバーに表示する
  • IC Imaging Control3.5(pythonnet編)
    • Qtを使ったデモアプリ(pythonnet編)
    • カメラで取得した画像の輝度値を平均してバーに表示する
      (pythonnet編)
    • 動画保存(MediaStreamSink コーデック:H.264)
    • 露光時間・ゲインを設定し、静止画保存をする(pythonnet編)
  • リンク集

    ICImagingControl WEB APIリファレンスマニュアル/サンプルプログラム

    :日本語対応済み :日本語化準備中
    開発言語 APIリファレンスマニュアル サンプルプログラム
    C 4.0
    ()
    - - 4.0
    ()
    - -
    C++ 4.0
    ()
    3.5
    ()
    3.4
    ()
    4.0
    ()
    3.5 3.4
    ()
    C#/VB.NET 4.0
    ()
    3.5
    ()
    3.4
    ()
    4.0
    ()
    3.5
    ()
    3.4
    ()
    Python 4.0
    ()
    3.5 3.4
    ()
    4.0
    ()
    3.5 3.4
    ()

ステレオカメラで表示

概要

このプログラムはPCに接続された2台のカメラ映像を同時に表示するための方法について記載しています。このプログラムではGUIアプリケーションを作成するためQtと呼ばれるライブラリを使用しています。

サンプルプログラム

サンプル(Python) qt_stereo_python.zip
pip install opencv-python
pip install numpy
pip install pyqt5

使用するライブラリはOpenCV,Numpy,Qtです。ライブラリのインストールがまだの場合はコンソール画面にて上記のコマンドを実行し、インストールしてください。

サンプルの出力

コード全体

import sys
import time
import ctypes

# GUI表記のために必要
import PyQt5.QtCore
import PyQt5.QtWidgets as qt5

# 画像処理・画像保存に使用

import cv2 as cv2
import numpy as np

#Theimagingsourceカメラを使用するために使用
import tisgrabber as tis

#tisgrabber_x64.dllをインポートする
ic = ctypes.cdll.LoadLibrary("./tisgrabber_x64.dll")
tis.declareFunctions(ic)
ic.IC_InitLibrary(0)

# カメラオブジェクト作成
LeftCamera = ic.IC_CreateGrabber()
RightCamera = ic.IC_CreateGrabber()


class CallbackUserdata(ctypes.Structure):
    """ コールバック関数に渡されるユーザーデータの例"""
    def __init__(self):
        self.width = 0
        self.height = 0
        self.BytesPerPixel = 0
        self.buffer_size = 0
        self.oldbrightness = 0
        self.getNextImage = 0
        self.cvMat = None


def LeftCallback(hGrabber, pBuffer, framenumber, pData):
    """ 左カメラ用:OpenCVを使用した画像処理のコールバック関数の例
     :param:hGrabber:グラバーオブジェクトへのポインター
     :param:pBuffer:最初のピクセルの最初のバイトへのポインタ
     :param:framenumber:ストリームが開始されてからのフレーム数
     :param:pData:追加のユーザーデータ構造へのポインター
    """
    if pData.getNextImage == 1:
        pData.getNextImage = 2
        print("    Left")
        if pData.buffer_size > 0:
            image = ctypes.cast(pBuffer, ctypes.POINTER(ctypes.c_ubyte * pData.buffer_size))

            pData.cvMat = np.ndarray(buffer=image.contents,
                                     dtype=np.uint8,
                                     shape=(pData.height.value,
                                            pData.width.value,
                                            pData.BytesPerPixel))
        pData.getNextImage = 0


def RightCallback(hGrabber, pBuffer, framenumber, pData):
    """ 右カメラ用:OpenCVを使用した画像処理のコールバック関数の例
     :param:hGrabber:グラバーオブジェクトへのポインター
     :param:pBuffer:最初のピクセルの最初のバイトへのポインタ
     :param:framenumber:ストリームが開始されてからのフレーム数
     :param:pData:追加のユーザーデータ構造へのポインター
    """
    if pData.getNextImage == 1:
        pData.getNextImage = 2
        print("    Right")
        if pData.buffer_size > 0:
            image = ctypes.cast(pBuffer, ctypes.POINTER(ctypes.c_ubyte * pData.buffer_size))

            pData.cvMat = np.ndarray(buffer=image.contents,
                                     dtype=np.uint8,
                                     shape=(pData.height.value,
                                            pData.width.value,
                                            pData.BytesPerPixel))

        pData.getNextImage = 0


# コールバック関数のポインタを作成
LeftCallbackfunc = ic.FRAMEREADYCALLBACK(LeftCallback)
RightCallbackfunc = ic.FRAMEREADYCALLBACK(RightCallback)

# CallbackUserdataをインスタンス化
LeftUserData = CallbackUserdata()
RightUserData = CallbackUserdata()

 #コールバック関数を使用する宣言
ic.IC_SetFrameReadyCallback(LeftCamera, LeftCallbackfunc, LeftUserData)
ic.IC_SetFrameReadyCallback(RightCamera, RightCallbackfunc, RightUserData)


##########################################################################
# カメラ関連の関数
def SelectLeftDevice():
    #関数の中からグローバル変数LeftCameraを書き換える
    global LeftCamera

    ic.IC_StopLive(LeftCamera)

    LeftCamera = ic.IC_ShowDeviceSelectionDialog(None)

    if ic.IC_IsDevValid(LeftCamera): 
        ic.IC_SetFrameReadyCallback(LeftCamera, LeftCallbackfunc, LeftUserData)
        ic.IC_SetHWnd(LeftCamera,  LeftVideo.winId())
        startCamera(LeftUserData, LeftCamera)
        ic.IC_SaveDeviceStateToFile(LeftCamera, tis.T("left.xml"))


def ShowLeftProperties():
    #関数の中からグローバル変数LeftCameraを書き換える
    global LeftCamera

    if ic.IC_IsDevValid(LeftCamera):
        ic.IC_ShowPropertyDialog(LeftCamera)
        ic.IC_SaveDeviceStateToFile(LeftCamera, tis.T("left.xml"))

def SelectRightDevice():
    #関数の中からグローバル変数RightCameraを書き換える
    global RightCamera

    ic.IC_StopLive(RightCamera)

    RightCamera = ic.IC_ShowDeviceSelectionDialog(None)

    if ic.IC_IsDevValid(RightCamera): 
        ic.IC_SetFrameReadyCallback(RightCamera, RightCallbackfunc, RightUserData)
        ic.IC_SetHWnd(RightCamera, RightVideo.winId())
        startCamera(LeftUserData, RightCamera)
        ic.IC_SaveDeviceStateToFile(RightCamera, tis.T("right.xml"))


def ShowRightProperties():
    #関数の中からグローバル変数を書き換える
    global RightCamera

    if ic.IC_IsDevValid(RightCamera):
        ic.IC_ShowPropertyDialog(RightCamera)
        ic.IC_SaveDeviceStateToFile(RightCamera, tis.T("right.xml"))


def Close():
    #関数の中からグローバル変数を書き換える
    global RightCamera
    global LeftCamera
    if ic.IC_IsDevValid(LeftCamera):
        ic.IC_StopLive(LeftCamera)

    if ic.IC_IsDevValid(RightCamera):
        ic.IC_StopLive(RightCamera)

    app.quit()


def restorelastuseddevices():
    ''' 最後に使用したデバイスをxmlに保存
    '''
    ic.IC_LoadDeviceStateFromFile(LeftCamera, tis.T("left.xml"))
    if ic.IC_IsDevValid(LeftCamera): 
        startCamera(LeftUserData, LeftCamera)

    ic.IC_LoadDeviceStateFromFile(RightCamera, tis.T("right.xml"))
    if ic.IC_IsDevValid(RightCamera):
        startCamera(RightUserData, RightCamera)


def CreateUserData(ud, camera):
    ''' 渡されたカメラのコールバック用のユーザーデータを作成します
     :param ud:作成するユーザーデータ
     :param camera:ユーザーデータに接続されているカメラ
    '''
    ud.width = ctypes.c_long()
    ud.height = ctypes.c_long()
    iBitsPerPixel = ctypes.c_int()
    colorformat = ctypes.c_int()

    # 画像の値を取得する
    ic.IC_GetImageDescription(camera, ud.width, ud.height, iBitsPerPixel, colorformat)
    # バッファサイズを計算
    ud.BytesPerPixel = int(iBitsPerPixel.value / 8.0)
    ud.buffer_size = ud.width.value * ud.height.value * ud.BytesPerPixel
    ud.getNextImage = 0


def startCamera(UserData, camera):
    '''カメラを起動
     :param UserData user:カメラに接続されているユーザーデータ
     :param Camera:ライブスタートするカメラ
    '''
    ic.IC_SetContinuousMode(camera, 0)
    ic.IC_StartLive(camera, 1)
    CreateUserData(UserData, camera)


def OnSnapImagePair():
    '''
    左右のカメラから取得した画像を同時に保存
    '''
    print("wait")
    RightUserData.getNextImage = 1
    LeftUserData.getNextImage = 1
    while RightUserData.getNextImage != 0 or LeftUserData.getNextImage != 0:
        time.sleep(0.005)

    print("done")
    # OpenCVでimwriteとして保存するためにnumpyデータとして変換された画像を使用
    cv2.imwrite("Left.bmp", cv2.flip(LeftUserData.cvMat, 0))
    cv2.imwrite("right.bmp", cv2.flip(RightUserData.cvMat, 0))

#######################################################
# Qtを使ってGUI作成
# コンソール画面にて「pip install pyqt5」でPyQt5をインストールしてください。

# 必ず作らなければいけないオブジェクト
app = PyQt5.QtWidgets.QApplication(sys.argv)

# ウインドウを作る
w = PyQt5.QtWidgets.QMainWindow()
w.resize(1280, 480)
w.move(300, 300)
w.setWindowTitle('ステレオカメラ')

# メニューバーの作成
mainMenu = w.menuBar()

#fileメニュー
fileMenu = mainMenu.addMenu('&ファイル')
#exitメニュー
exitAct = PyQt5.QtWidgets.QAction("&終了", app)
exitAct.setStatusTip("終了")
exitAct.triggered.connect(Close)
fileMenu.addAction(exitAct)
#######################################################
#Qtを使ってGUI作成 左カメラのメニュー
LeftMenu = mainMenu.addMenu('&左カメラ')
devselAct = PyQt5.QtWidgets.QAction("&デバイスを選択", app)
devselAct.triggered.connect(SelectLeftDevice)
LeftMenu.addAction(devselAct)

devpropAct = PyQt5.QtWidgets.QAction("&プロパティを設定", app)
devpropAct.triggered.connect(ShowLeftProperties)
LeftMenu.addAction(devpropAct)

######################################################
#Qtを使ってGUI作成 カメラのメニュー
RightMenu = mainMenu.addMenu('&右カメラ')
devselAct = PyQt5.QtWidgets.QAction("&デバイスを選択", app)
devselAct.triggered.connect(SelectRightDevice)
RightMenu.addAction(devselAct)

devpropAct = PyQt5.QtWidgets.QAction("&プロパティを設定", app)
devpropAct.triggered.connect(ShowRightProperties)
RightMenu.addAction(devpropAct)

######################################################
# Qtを使ってGUI作成 画面のレイアウト作成

# 2つのビデオウィンドウでウィンドウレイアウトを作成する
MainWindow = PyQt5.QtWidgets.QWidget()
#縦方向に画面を配置する
vboxlayout = qt5.QVBoxLayout()
#横方向に画面を配置する
hboxlayout = qt5.QHBoxLayout()

LeftVideo = qt5.QWidget()
RightVideo = qt5.QWidget()

# カメラの映像は縦並び
hboxlayout.addWidget(LeftVideo)
hboxlayout.addWidget(RightVideo)

vboxlayout.addLayout(hboxlayout)
SnapButton = qt5.QPushButton("2つのカメラの画像を同時に保存")
#ボタンをクリックしたとき左右のカメラから取得した画像を同時に保存
SnapButton.clicked.connect(OnSnapImagePair)

vboxlayout.addWidget(SnapButton)

MainWindow.setLayout(vboxlayout)
w.setCentralWidget(MainWindow)

w.show()

# カメラから取得した画像を表示するためにウィンドウハンドルを左右のカメラに渡す
ic.IC_SetHWnd(LeftCamera,  LeftVideo.winId())
ic.IC_SetHWnd(RightCamera,  RightVideo.winId())

#xmlファイルに左右のカメラの設定情報を保存
restorelastuseddevices()

app.exec()

解説

# GUI表記のために必要
import PyQt5.QtCore
import PyQt5.QtWidgets as qt5

# 画像処理・画像保存に使用
import cv2 as cv2
import numpy as np

ライブラリをインストールしたうえで上記のOpenCV,Numpy,Qtを使用する宣言を行ってください。

カメラオブジェクトの作成

# カメラオブジェクト作成
LeftCamera = ic.IC_CreateGrabber()
RightCamera = ic.IC_CreateGrabber()

#-----------省略-----------

# CallbackUserdataをインスタンス化
LeftUserData = CallbackUserdata()
RightUserData = CallbackUserdata()

# コールバック関数のポインタを作成
LeftCallbackfunc = ic.FRAMEREADYCALLBACK(LeftCallback)
RightCallbackfunc = ic.FRAMEREADYCALLBACK(RightCallback)

 #コールバック関数を使用する宣言
ic.IC_SetFrameReadyCallback(LeftCamera, LeftCallbackfunc, LeftUserData)
ic.IC_SetFrameReadyCallback(RightCamera, RightCallbackfunc, RightUserData)

左右のカメラオブジェクトを作成し、それぞれにカメラの情報をユーザーデータとして持たせています。
LeftCallback、RightCallbackのコールバックが呼ばれるように定義しています。

  • IC_SetFrameReadyCallback(グラバーのポインタ, コールバック関数の関数ポインタ, ユーザーデータ)
  • IC_SetContinuousMode(グラバーのポインタ, 0)

コールバック関数内(上記の例ではFrameCallback)はカメラから画像が送られるたびごとに関数が呼び出されます。

コールバック関数

def CreateUserData(ud, camera):
    ''' 渡されたカメラのコールバック用のユーザーデータを作成します
     :param ud:作成するユーザーデータ
     :param camera:ユーザーデータに接続されているカメラ
    '''
    ud.width = ctypes.c_long()
    ud.height = ctypes.c_long()
    iBitsPerPixel = ctypes.c_int()
    colorformat = ctypes.c_int()

    # 画像の値を取得する
    ic.IC_GetImageDescription(camera, ud.width, ud.height, iBitsPerPixel, colorformat)
    # バッファサイズを計算
    ud.BytesPerPixel = int(iBitsPerPixel.value / 8.0)
    ud.buffer_size = ud.width.value * ud.height.value * ud.BytesPerPixel
    ud.getNextImage = 0

上記の関数はカメラをスタートした後に呼び出されるメソッドです。カメラのパラメータを渡して、カメラのユーザーデータとして解像度やバッファサイズを取得します。また、【ud.getNextImage = 0】とすることで画像バッファの初期化をしています。

def LeftCallback(hGrabber, pBuffer, framenumber, pData):
    """ 左カメラ用:OpenCVを使用した画像処理のコールバック関数の例
     :param:hGrabber:グラバーオブジェクトへのポインター
     :param:pBuffer:最初のピクセルの最初のバイトへのポインタ
     :param:framenumber:ストリームが開始されてからのフレーム数
     :param:pData:追加のユーザーデータ構造へのポインター
    """
    if pData.getNextImage == 1:
        pData.getNextImage = 2
        print("    Left")
        if pData.buffer_size > 0:
            image = ctypes.cast(pBuffer, ctypes.POINTER(ctypes.c_ubyte * pData.buffer_size))

            pData.cvMat = np.ndarray(buffer=image.contents,
                                     dtype=np.uint8,
                                     shape=(pData.height.value,
                                            pData.width.value,
                                            pData.BytesPerPixel))
        pData.getNextImage = 0

OpenCVで画像を処理するために型をuint8に変更します。uint8に変更するためには画像のnumpyライブラリのndarrayを使用する必要があります。OpenCVを使った例は【コールバック関数の設定方法(OpenCVで二値化)】をご確認ください。

▲ このページの先頭に戻る

Copyright © ARGO Corporation. All Rights Reserved.