mengineer's blog

ニッチなネタばかりですが。

eBUS SDK 使ってみる その2 画像のTimeStamp取得

昨日の続き、今回は接続したカメラから画像を取込みます、
作成したサンプルソフト画面は、こんな感じ。 f:id:mengineer:20190226123811p:plain

上から、ConnectDeveice(button1)でカメラを検出、
検出出来ると、Start(button2)が有効に変わります。

Startを押すと画像取込開始、画像のTimeStamp情報を表示します、
Stop(button3)を押すと、取込停止します。

今回は画像表示は無し、PvGUIDotNetには”DisplayControl”という仕組みが有り、
Form上に貼ればお手軽に表示出来るようなのですが、また後日ということで。

Streamの設定

昨日のbutton1のカメラ検出部分に処理を追加しています、
Create and Open streamより後が追加した部分。

Perform GigE Vision only configurationは、GEVカメラ限定の処理、
NegotiatePacketSize()でパケットサイズを最適化してるのでは?
と推測していますが、今回はUSBカメラなので未検証です。

その後PayLoadSizeを取得し、取込バッファ数だけpVBufferを定義
(サイズはPayLoadSize)、それをmStream.QueueBufferでStreamに定義します。

                // Create and Open stream.
                mStream = PvStream.CreateAndOpen(lDeviceInfo);

                // Perform GigE Vision only configuration
                PvDeviceGEV lDGEV = mDevice as PvDeviceGEV;
                if (lDGEV != null)
                {
                    // Negotiate packet size
                    lDGEV.NegotiatePacketSize();

                    // Set stream destination.
                    PvStreamGEV lSGEV = mStream as PvStreamGEV;
                    lDGEV.SetStreamDestination(lSGEV.LocalIPAddress, lSGEV.LocalPort);
                }

                // Read payload size, preallocate buffers of the pipeline.
                Int64 lPayloadSize = mDevice.PayloadSize;

                // Get minimum buffer count, creates and allocates buffer.
                UInt32 lBufferCount = (mStream.QueuedBufferMaximum < cBufferCount) ? mStream.QueuedBufferMaximum : cBufferCount;
                PvBuffer[] lBuffers = new PvBuffer[lBufferCount];
                for (UInt32 i = 0; i < lBufferCount; i++)
                {
                    lBuffers[i] = new PvBuffer();
                    lBuffers[i].Alloc((UInt32)lPayloadSize);
                }
                // Queue all buffers in the stream.
                for (UInt32 i = 0; i < lBufferCount; i++)
                {
                    mStream.QueueBuffer(lBuffers[i]);
                }
            }
            catch (PvException ex)
            {
                MessageBox.Show(ex.Message, Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            // Enable Start Button
            button2.Enabled = true;
        }
    }
}

取込開始

Start(button2)を押した時の処理です、取込用スレッドを定義して開始、
mDevice.StreamEnable()でStreamを有効にしてから、”AcquisitionStart”を送ります。

private void button2_Click(object sender, EventArgs e)
{
    // Start display thread.
    mThread = new Thread(new ParameterizedThreadStart(ThreadProc));
    Form1 lP1 = this;
    object[] lParameters = new object[] { lP1 };
    mIsStopping = false;
    mThread.Start(lParameters);

    // Enables streaming before sending the AcquisitionStart command.
    mDevice.StreamEnable();

    // Start acquisition on the device
    mDevice.Parameters.ExecuteCommand("AcquisitionStart");

    // Disable Start Button & Enable Stop Button
    button2.Enabled = false;
    button3.Enabled = true;
}

取込スレッドの処理は以下、RetrieveBufferでStreamからデータを取得します、
PvResultは処理結果ですが、IResultとIOperetionResult、2つ見てるようです。
(この辺の詳細は未調査、サンプルソフトそのままです)

両方ともOKで有れば、タイムスタンプを表示させています。
ここでIBufferの中身を参照すれば、生データそのものも扱えそうです。

Stop(button3)を押すとForm1内のmIsStoppingがtrueに設定されることで、
forループを抜けるようになっています。

private static void ThreadProc(object aParameters)
{
    object[] lParameters = (object[])aParameters;
    Form1 lThis = (Form1)lParameters[0];

    for (; ; )
    {
        if (lThis.mIsStopping)
        {
            // Signaled to terminate thread, return.
            return;
        }

        PvBuffer lBuffer = null;
        PvResult lOperationResult = new PvResult(PvResultCode.OK);

        // Retrieve next buffer from acquisition pipeline
        PvResult lResult = lThis.mStream.RetrieveBuffer(ref lBuffer, ref lOperationResult, 100);
        if (lResult.IsOK)
        {
            // Operation result of buffer is OK, display.
            if (lOperationResult.IsOK)
            {
                lThis.label3.Text = lBuffer.Timestamp.ToString();                       
            }

            // We have an image - do some processing (...) and VERY IMPORTANT,
            // re-queue the buffer in the stream object.
            lThis.mStream.QueueBuffer(lBuffer);
        }
    }
}

取込開始すると、TimeStampの値が変わっていくのが判ります。 f:id:mengineer:20190226132519p:plain

取込停止

Stop(button3)を押した時の処理です。

Deviceに"AcquisitionStop"を送ってから、StreamDisable()にします、
mIsStopping = true(→取込スレッドで参照)、mThread.Join()してから、
スレッドをnullにしています、その後Buffer関係の後片付け。

private void button3_Click(object sender, EventArgs e)
{
    try
    {
        PvBuffer lBuffer = null;
        PvResult lOperationResult = new PvResult(PvResultCode.OK);
        PvResult lResult = new PvResult(PvResultCode.OK);

        // Stop acquisition.
        mDevice.Parameters.ExecuteCommand("AcquisitionStop");

        // Disable streaming after sending the AcquisitionStop command.
        mDevice.StreamDisable();

        // Stop display thread.
        mIsStopping = true;
        mThread.Join();
        mThread = null;

        // Abort all buffers in the stream and dequeue
        mStream.AbortQueuedBuffers();
        for (int i = 0; i < mStream.QueuedBufferCount; i++)
        {
            lResult = mStream.RetrieveBuffer(ref lBuffer, ref lOperationResult);
            if (lResult.IsOK)
            {
                lBuffer = null;
            }
        }
    }
    catch (PvException lExc)
    {
        MessageBox.Show(lExc.Message, Text);
    }
    // Enaable Start Button & Disable Stop Button
    button2.Enabled = true;
    button3.Enabled = false;
}

一通りの処理の流れを確認することが出来ました、全体のソースはこちら。
eBUS SDK Sample