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

Qtを使ったデモアプリ(pythonnet編)

概要

IC Imaging Control 3.5のWindows専用APIを使用したPythonのプログラムで、GUI上で簡単にデバイスの選択・プロパティの設定・bmpで保存ができる方法について記載しています。

サンプルプログラム

サンプル(Python) pythonnet-qt5-simple.zip

サンプルツールの出力

コード全体

from PyQt5.QtGui import QPixmap, QImage         
from PyQt5.QtWidgets import QWidget,QMainWindow, QLabel, QSizePolicy, QApplication, QAction, QHBoxLayout,QProgressBar
from PyQt5.QtCore import *
import sys,traceback

import ctypes as C
import numpy as np
import cv2

# PyhtonNetをインポートする
import clr
# 同じフォルダ内にあるIC Imaging Control3.5のDllを参照する
clr.AddReference('TIS.Imaging.ICImagingControl35')
clr.AddReference('System')


# IC Imaging Control namespaceを宣言
import TIS.Imaging
from System import TimeSpan


class DisplayBuffer:
    '''
    このクラスは、ビデオウィンドウに表示するために画像をピックスマップにコピーするために必要
    '''
    locked = False
    pixmap = None


    def Copy( self, FrameBuffer):
        if(  int(FrameBuffer.FrameType.BitsPerPixel/8 ) == 4):
            imgcontent = C.cast(FrameBuffer.GetIntPtr().ToInt64(), C.POINTER(C.c_ubyte * FrameBuffer.FrameType.BufferSize))
            qimage = QImage(imgcontent.contents, FrameBuffer.FrameType.Width,FrameBuffer.FrameType.Height, QImage.Format_RGB32).mirrored()
            self.pixmap = QPixmap(qimage)

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


class DisplayFilter(TIS.Imaging.FrameFilterImpl):
    '''
    このフレームフィルターは、着信フレームをDisplayBufferオブジェクトにコピーし、
    新しいバッファーでQApplicationに信号を送ります。
    '''
    __namespace__ = "DisplayFilterClass"
    signals = WorkerSignals() 
    dispBuffer = DisplayBuffer()

    def GetSupportedInputTypes(self, frameTypes):
        frameTypes.Add( TIS.Imaging.FrameType(TIS.Imaging.MediaSubtypes.RGB32))

    def GetTransformOutputTypes(self,inType, outTypes):
        outTypes.Add(inType)
        return True

    def Transform(self, src, dest):
        dest.CopyFrom(src)
        if self.dispBuffer.locked is False:
            self.dispBuffer.locked = True
            self.dispBuffer.Copy(dest)
            self.signals.display.emit(self.dispBuffer)

        return False

####################################################################################
#カメラデバイスの制御

def SelectDevice():
    ic.LiveStop()
    ic.ShowDeviceSettingsDialog()
    if ic.DeviceValid is True:
        ic.LiveStart()
        ic.SaveDeviceStateToFile("device.xml")

def ShowProperties():
    if ic.DeviceValid is True:
        ic.ShowPropertyDialog()
        ic.SaveDeviceStateToFile("device.xml")

def SnapImage():
    '''
    画像をスナップして保存する
    '''
    image = snapsink.SnapSingle(TimeSpan.FromSeconds(1))
    TIS.Imaging.FrameExtensions.SaveAsBitmap(image,"test.bmp")

def Close():
    if ic.DeviceValid is True:
        ic.LiveStop()
    app.quit()

def OnDisplay(dispBuffer):
    videowindow.setPixmap(dispBuffer.pixmap)   
    dispBuffer.locked = False   


################################################
# QtでGUI作成
app =  QApplication(sys.argv)

w = QMainWindow()
w.resize(640, 480)
w.move(300, 300)
w.setWindowTitle('Simple Camera')

# QtでGUI作成
mainMenu = w.menuBar()
fileMenu = mainMenu.addMenu('&ファイル')

exitAct =  QAction("&終了",app)
exitAct.setStatusTip("Exit program")
exitAct.triggered.connect(Close)
fileMenu.addAction(exitAct)

deviceMenu = mainMenu.addMenu('&デバイス')
devselAct =  QAction("&選択",app)
devselAct.triggered.connect(SelectDevice)
deviceMenu.addAction(devselAct)

devpropAct =  QAction("&プロパティ",app)
devpropAct.triggered.connect(ShowProperties)
deviceMenu.addAction(devpropAct)

snapAct =  QAction("bmpで保存",app)
snapAct.triggered.connect(SnapImage)
deviceMenu.addAction(snapAct)

layout = QHBoxLayout()
mainwindow = QWidget()
videowindow = QLabel()
layout.addWidget(videowindow)

mainwindow.setLayout(layout)
w.setCentralWidget(mainwindow)

################################################
#IC ImagingControlの設定

# IC ImagingControlオブジェクトを作成
ic = TIS.Imaging.ICImagingControl()

# ライブ表示用に表示フィルターオブジェクトをインスタンス化します
displayFilter = DisplayFilter()

# ディスプレイ信号ハンドラーをフィルターに接続します
displayFilter.signals.display.connect(OnDisplay)
ic.DisplayFrameFilters.Add( ic.FrameFilterCreate(displayFilter))

# メニューから"bmpで保存"をクリックしたときに画像が保存できるようにするためにsinkを作成
snapsink = TIS.Imaging.FrameSnapSink(TIS.Imaging.MediaSubtypes.RGB32)
ic.Sink = snapsink

ic.LiveDisplay = True

try:
    ic.LoadDeviceStateFromFile("device.xml",True)
    if ic.DeviceValid is True:
        ic.LiveStart()

except Exception as ex:
    print(ex)
    pass


w.show()

app.exec()

解説

オブジェクト作成

ic = TIS.Imaging.ICImagingControl()
displayFilter = DisplayFilter()

IC Imaging ControlのAPIを使用するためにオブジェクトの作成しDisplayFilterクラスからオブジェクトを作成します。

ディスプレイ表示のAPIとGUIを紐づけるための処理

■【シグナル】と【スロット】について
GUIプログラミングでは、GUI を構成する要素やオブジェクトの状態が変わった際に何かしらの処理を行うために、他の要素やオブジェクトに通知するイベントハンドラやコールバックのような仕組みが必要となります。Qtでは【シグナル】と【スロット】と呼ばれるオブジェクト間のやり取りをの仕組みが設けられています。

シグナル 要素やオブジェクトの状態が変わったときに他の要素やオブジェクトに通知するための関数
スロット シグナルに反応して実行される関数

Qtのプログラムでは【シグナル】と【スロット】を接続して使用し、シグナルが発生した際にスロットが自動的に実行されます。例:ボタンをクリックしたというシグナルを設定した場合には、メッセージボックスを表示するという【スロット】をセットにすることで、ボタンをクリック時にメッセージボックスを表示することができます。

displayFilter.signals.display.connect(OnDisplay)
ic.DisplayFrameFilters.Add( ic.FrameFilterCreate(displayFilter))

displayFilterで表示する【シグナル】とGUIに表示させるためのOnDisplayメソッドを呼び出す【スロット】を結びつけて、カメラから送られてくる画像をリアルタイムにウィンドウ上に表示させます。

def OnDisplay(dispBuffer):
    videowindow.setPixmap(dispBuffer.pixmap)   
    dispBuffer.locked = False   

OnDisplayメソッドは上記の通り、バッファメモリ上にある画像データをウィンドウ上に表示しています。

ディスプレイ表示するためにバッファメモリを処理する

class DisplayFilter(TIS.Imaging.FrameFilterImpl):
    '''
    このフレームフィルターは、着信フレームをDisplayBufferオブジェクトにコピーし、
    新しいバッファーでQApplicationに信号を送ります。
    '''
    __namespace__ = "DisplayFilterClass"
    signals = WorkerSignals() 
    dispBuffer = DisplayBuffer()

    def GetSupportedInputTypes(self, frameTypes):
        frameTypes.Add( TIS.Imaging.FrameType(TIS.Imaging.MediaSubtypes.RGB32))

    def GetTransformOutputTypes(self,inType, outTypes):
        outTypes.Add(inType)
        return True

    def Transform(self, src, dest):
        dest.CopyFrom(src)
        if self.dispBuffer.locked is False:
            self.dispBuffer.locked = True
            self.dispBuffer.Copy(dest)
            #スロットにシグナルを送信する。
            self.signals.display.emit(self.dispBuffer)

        return False


class DisplayBuffer:
    '''
    このクラスは、ウィンドウに表示するために画像をバッファにコピーするために必要
    '''
    locked = False
    pixmap = None


    def Copy( self, FrameBuffer):
        if(  int(FrameBuffer.FrameType.BitsPerPixel/8 ) == 4):
            imgcontent = C.cast(FrameBuffer.GetIntPtr().ToInt64(), C.POINTER(C.c_ubyte * FrameBuffer.FrameType.BufferSize))
            qimage = QImage(imgcontent.contents, FrameBuffer.FrameType.Width,FrameBuffer.FrameType.Height, QImage.Format_RGB32).mirrored()
            self.pixmap = QPixmap(qimage)

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

DisplayFilterはFrameFilterImplのクラスを継承し、下記を定義しています。

GetSupportedInputTypes 変換フィルタが入力タイプとしてカラーフォーマットRGB32を使用することを定義
GetTransformOutputTypes 利用可能な出力タイプを定義
Transform ソースにあるフレームをコピーし、画面表示のためのバッファメモリを受け取ったタイミングで発火するように定義

DisplayFilterはDisplayBufferクラスとWorkerSignalsクラスの内部クラスがあり、それぞれの役割は下記の通りです。

DisplayBufferクラス ウィンドウに表示するために画像をバッファにコピーします。
WorkerSignals スロットがシグナルを検知するためにシグナルを定義します。

上記のように定義することでカメラから送られてくるフレームをバッファメモリ取込、バッファメモリをGUIに表示することが可能です。

bmpで画像を保存する

snapsink = TIS.Imaging.FrameSnapSink(TIS.Imaging.MediaSubtypes.RGB32)
ic.Sink = snapsink

FrameSnapSinkは"bmpで保存"をクリックしたタイミングでフレームを取得するための画像の受け皿(sink)です。

def SnapImage():
    '''
    画像をスナップして保存する
    '''
    image = snapsink.SnapSingle(TimeSpan.FromSeconds(1))
    TIS.Imaging.FrameExtensions.SaveAsBitmap(image,"test.bmp")


#省略#

#GUIメニュー
snapAct =  QAction("bmpで保存",app)
snapAct.triggered.connect(SnapImage)
deviceMenu.addAction(snapAct)

QAction"bmpで保存"が押されたとき、シグナル関数SnapImageが発生するようにしています。

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

Copyright © ARGO Corporation. All Rights Reserved.