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
    ()

2つのカメラで取得した画像の輝度値を平均してバーに表示する

概要

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

サンプルプログラム

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

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

サンプルの出力

コード全体

import os
import sys
import ctypes 

# GUI表記のために必要
import PyQt5.QtCore
import PyQt5.QtWidgets as qt5
from PyQt5.QtCore import pyqtSignal, QTimer, QObject

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

import tisgrabber as tis

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


class WorkerSignals(QObject):
    newimage = pyqtSignal(object)


class CallbackUserdata(ctypes.Structure):
    """ コールバック関数に渡されるユーザーデータの例"""
    _namespace__ = "userdata"
    signals = WorkerSignals() 

    def __init__(self, index):
        self.index = index
        self.cvMat = None


def frameReadyCallback(hGrabber, pBuffer, framenumber, pData):
    """
    OpenCVを使用した画像処理のコールバック関数の例
    pBufferの画像データはcv Matrixに変換され、cv.mean()を使用して画像の平均輝度が測定されます。
     :param: hGrabber:グラバーオブジェクトへのポインター
     :param: pBuffer : 最初のピクセルの最初のバイトへのポインタ
     :param: framenumber:ストリームが開始されてからのフレーム数
     :param: pData:追加のユーザーデータ構造へのポインター
     """

    # print("camera {}". format(pData.index))
    Width = ctypes.c_long()
    Height = ctypes.c_long()
    BitsPerPixel = ctypes.c_int()
    colorformat = ctypes.c_int()

    # 画像の値を取得する
    ic.IC_GetImageDescription(hGrabber, Width, Height, BitsPerPixel, colorformat)

    # バッファサイズを計算
    bpp = int(BitsPerPixel.value/8.0)
    buffer_size = Width.value * Height.value * bpp

    if buffer_size > 0:
        image = ctypes.cast(pBuffer, 
                            ctypes.POINTER(
                                ctypes.c_ubyte * buffer_size))

        pData.cvMat = np.ndarray(buffer=image.contents,
                                dtype=np.uint8,
                                shape=(Height.value,
                                        Width.value,
                                        bpp))

        pData.signals.newimage.emit(pData)


# コールバック関数のポインタを作成
frameReadyCallbackfunc = ic.FRAMEREADYCALLBACK(frameReadyCallback)


class Camera():
    def __init__(self, index, winID, OnNewImageHandler):
        """
         新しいカメラオブジェクトを作成
          :param index:カメラを識別するために使用されます。
          :param winID:QTウィジェットウィンドウID
        """
        self.hGrabber = ic.IC_CreateGrabber()
        self.userdata = CallbackUserdata(index)
        self.userdata.signals.newimage.connect(OnNewImageHandler)
        self.winID = winID
        self.loadDeviceState()

    def showDeviceSelectionDlg(self):
        ic.IC_StopLive(self.hGrabber)
        self.hGrabber = ic.IC_ShowDeviceSelectionDialog(None)

        if ic.IC_IsDevValid(self.hGrabber):
            self.startCamera()
            ic.IC_SaveDeviceStateToFile(self.hGrabber,
                                        tis.T("camera{}.xml".format(self.userdata.index)))

    def showPropertyDlg(self):
        if ic.IC_IsDevValid(self.hGrabber):
            ic.IC_ShowPropertyDialog(self.hGrabber)
            ic.IC_SaveDeviceStateToFile(self.hGrabber,
                                        tis.T("camera{}.xml".format(self.userdata.index)))

    def loadDeviceState(self):
        if os.path.exists("camera{}.xml".format(self.userdata.index)):
            ic.IC_LoadDeviceStateFromFile(self.hGrabber, tis.T("camera{}.xml".format(self.userdata.index)))
            self.startCamera()

    def startCamera(self):
        """カメラを起動しライブスタート
         :paramUserDataカメラに接続されているユーザーデータ
         :paramCamera開始するカメラ
        """
        if ic.IC_IsDevValid(self.hGrabber):
            ic.IC_SetHWnd(self.hGrabber, self.winID)
            ic.IC_SetFrameReadyCallback(self.hGrabber, frameReadyCallbackfunc, self.userdata)
            ic.IC_SetContinuousMode(self.hGrabber, 0)
            ic.IC_StartLive(self.hGrabber, 1)

    def stopCamera(self):
        """カメラを停止
         :paramUserDataカメラに接続されているユーザーデータ
         :paramCamera停止するカメラ
        """
        if ic.IC_IsDevValid(self.hGrabber):
            ic.IC_StopLive(self.hGrabber)

##########################################################################


def selectDevice(cam):
    cameras[cam].showDeviceSelectionDlg()


def showProperties(cam):
    cameras[cam].showPropertyDlg()


def Close():
    for camera in cameras:
        camera.stopCamera()        

    app.quit()


def OnNewImage(userdata):
    print("camera {}".format(userdata.index))
    # 画像の平均輝度を計算する
    gray = cv2.cvtColor(userdata.cvMat, cv2.COLOR_BGR2GRAY)
    mean = cv2.mean(gray)
    brightnessbars[userdata.index].setValue(int(mean[0]))

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

#接続しているすべてのカメラのオブジェクトを作成
cameracount = ic.IC_GetDeviceCount()     # カメラの数を取得
videowindows = []
brightnessbars = []
cameras = []

# Qtを使用するのに必ず作らなければいけないオブジェクト
app = PyQt5.QtWidgets.QApplication(sys.argv)

# ウインドウを作る
w = PyQt5.QtWidgets.QMainWindow()
w.resize(1280, 480)
w.move(300, 300)
w.setWindowTitle('2つのカメラで取得した画像の輝度値を平均してバーに表示する')

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

#fileメニュー
fileMenu = mainMenu.addMenu('&ファイル')
#exitメニュー
exitAct = PyQt5.QtWidgets.QAction("&終了", app)
exitAct.setStatusTip("終了")
exitAct.triggered.connect(Close)
fileMenu.addAction(exitAct)
##接続しているすべてのカメラのカメラメニュー
cameraMenu = mainMenu.addMenu('&カメラ')
for i in range(0, cameracount):
    devselAct = PyQt5.QtWidgets.QAction("&デバイス選択 {}".format(i+1), app)
    devselAct.triggered.connect(lambda checked, index=i:  selectDevice(index))
    cameraMenu.addAction(devselAct)

#接続しているすべてのカメラのプロパティメニュー
propertiesMenu = mainMenu.addMenu('&プロパティ')
for i in range(0, cameracount):
    devselAct = PyQt5.QtWidgets.QAction("&カメラ {}".format(i+1), app)
    devselAct.triggered.connect(lambda checked, index=i: showProperties(index))
    propertiesMenu.addAction(devselAct)

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

# 接続しているカメラと同じ数のビデオウィンドウを追加します。
for i in range(0, cameracount):
    vvboxlayout = qt5.QVBoxLayout()
    videowindow = qt5.QWidget()

    brightnessbar = qt5.QProgressBar()
    brightnessbar.setRange(0, 256)
    brightnessbar.setOrientation(PyQt5.QtCore.Qt.Horizontal)
    brightnessbar.setValue(25)

    vvboxlayout.addWidget(videowindow)
    vvboxlayout.addWidget(brightnessbar)

    hboxlayout.addLayout(vvboxlayout)
    videowindows.append(videowindow)
    brightnessbars.append(brightnessbar)


MainWindow.setLayout(hboxlayout)
w.setCentralWidget(MainWindow)

w.show()

# カメラオブジェクトを作成
for i in range(0, cameracount):
    cameras.append(Camera(i, videowindows[i].winId(), OnNewImage))

app.exec()

解説

カメラクラスの定義
class Camera():
    def __init__(self, index, winID, OnNewImageHandler):
        """
         新しいカメラオブジェクトを作成
          :param index:カメラを識別するために使用されます。
          :param winID:QTウィジェットウィンドウID
        """
        self.hGrabber = ic.IC_CreateGrabber()
        self.userdata = CallbackUserdata(index)
        self.userdata.signals.newimage.connect(OnNewImageHandler)
        self.winID = winID
        self.loadDeviceState()

    def showDeviceSelectionDlg(self):
        ic.IC_StopLive(self.hGrabber)
        self.hGrabber = ic.IC_ShowDeviceSelectionDialog(None)

        if ic.IC_IsDevValid(self.hGrabber):
            self.startCamera()
            ic.IC_SaveDeviceStateToFile(self.hGrabber,
                                        tis.T("camera{}.xml".format(self.userdata.index)))

    def showPropertyDlg(self):
        if ic.IC_IsDevValid(self.hGrabber):
            ic.IC_ShowPropertyDialog(self.hGrabber)
            ic.IC_SaveDeviceStateToFile(self.hGrabber,
                                        tis.T("camera{}.xml".format(self.userdata.index)))

    def loadDeviceState(self):
        if os.path.exists("camera{}.xml".format(self.userdata.index)):
            ic.IC_LoadDeviceStateFromFile(self.hGrabber, tis.T("camera{}.xml".format(self.userdata.index)))
            self.startCamera()

    def startCamera(self):
        """カメラを起動しライブスタート
         :paramUserDataカメラに接続されているユーザーデータ
         :paramCamera開始するカメラ
        """
        if ic.IC_IsDevValid(self.hGrabber):
            ic.IC_SetHWnd(self.hGrabber, self.winID)
            ic.IC_SetFrameReadyCallback(self.hGrabber, frameReadyCallbackfunc, self.userdata)
            ic.IC_SetContinuousMode(self.hGrabber, 0)
            ic.IC_StartLive(self.hGrabber, 1)

    def stopCamera(self):
        """カメラを停止
         :paramUserDataカメラに接続されているユーザーデータ
         :paramCamera停止するカメラ
        """
        if ic.IC_IsDevValid(self.hGrabber):
            ic.IC_StopLive(self.hGrabber)
            

上記のようにクラスを定義すると簡単に複数のカメラ制御を行うことができます。

# カメラオブジェクトを作成
for i in range(0, cameracount):
    cameras.append(Camera(i, videowindows[i].winId(), OnNewImage))

OnNewImageコールバック関数をもったカメラの台数分(cameracount)のCameraオブジェクトを使用することができます。

コールバック関数(OpenCVの処理)
def OnNewImage(userdata):
    print("camera {}".format(userdata.index))
    # 画像の平均輝度を計算する
    gray = cv2.cvtColor(userdata.cvMat, cv2.COLOR_BGR2GRAY)
    mean = cv2.mean(gray)
    brightnessbars[userdata.index].setValue(int(mean[0]))

フレームを受けたタイミングで発火するコールバック関数は上記の通りです。受け取った画像データはユーザーデータに保存されており、ユーザーデータをOpenCVでモノクロ化(cvtColorを使用)し、mean変数にて輝度値の平均値を取得します。

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

Copyright © ARGO Corporation. All Rights Reserved.