mengineer's blog

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

Basler pylonサンプルソフトを試す(Chunk data編)

前回のpylonネタの続き、pylon Viewerでは良くわからなかったので、
Basler提供のサンプルソフトで、Chunk dataの取り方を調べてみました。

インストールフォルダ下を探していくと、sampleフォルダが有ります。 f:id:mengineer:20170414114331p:plain

このうちC#には、”Basler.Pylon”と”PylonC.NET”の二種類が有りましたが、
今回は後者を開いて動かしてみました。(両者どう違うのかまでは未確認)

f:id:mengineer:20170414114246p:plain

PylonC.NETSamplesの中身

ソリューションを開くと、11種類のサンプルプロジェクトが準備されています、
個人的にですが、VisualStudio2005形式なのは有り難いですね。

f:id:mengineer:20170414114934p:plain

まずSimpleGrabで基本的な使い方を見ると、ざっくり下記の流れになるようです。

1.PylonC.NETへの参照追加

using System;
using System.Collections.Generic;
using PylonC.NET;

2.初期化

/* Before using any pylon methods, the pylon runtime must be initialized. */
Pylon.Initialize();

3.接続されたカメラ検出→カメラが何も認識されなければエラー中断

/* Enumerate all camera devices. You must call
PylonEnumerateDevices() before creating a device. */
numDevices = Pylon.EnumerateDevices();
if (0 == numDevices)
{
    throw new Exception("No devices found.");
}

4.カメラオープン(複数有る場合は先頭のもの)

/* Get a handle for the first device found.  */
hDev = Pylon.CreateDeviceByIndex(0);

/* Before using the device, it must be opened. Open it for configuring
     parameters and for grabbing images. */
Pylon.DeviceOpen(hDev, Pylon.cPylonAccessModeControl | Pylon.cPylonAccessModeStream);

5.カメラを使って所望の処理を行う

6.後片付け

/* Clean up. Close and release the pylon device. */
Pylon.DeviceClose(hDev);
Pylon.DestroyDevice(hDev);

/* Shut down the pylon runtime system. Don't call any pylon method after
     calling Pylon.Terminate(). */
Pylon.Terminate();

Chunk dataを取り出す

次にサンプルのChunksを見てみます、上記流れの5.に該当する部分のみ抜粋。

まず初期設定、ChunkModeActiveをtrueに→ChunkSelectorでFramecounterを選択、
→ChunkEnableをtrueに、という順番で設定していくようです。

/* Before enabling individual chunks, the chunk mode in general must be activated. */
isAvail = Pylon.DeviceFeatureIsWritable(hDev, "ChunkModeActive");
if (!isAvail)
{
    throw new Exception("The device doesn't support the chunk mode.");
}
/* Activate the chunk mode. */
Pylon.DeviceSetBooleanFeature(hDev, "ChunkModeActive", true);

/* Enable some individual chunks... */

/* ... The frame counter chunk feature. */
/* Is the chunk feature available? */
isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "EnumEntry_ChunkSelector_Framecounter");
if (isAvail)
{
     /* Select the frame counter chunk feature. */
     Pylon.DeviceFeatureFromString(hDev, "ChunkSelector", "Framecounter");

     /* Can the chunk feature be activated? */
     isAvail = Pylon.DeviceFeatureIsWritable(hDev, "ChunkEnable");
     if (isAvail)
     {
          /* Activate the chunk feature. */
          Pylon.DeviceSetBooleanFeature(hDev, "ChunkEnable", true);
     }
}

次にChunkParserを設定します、こいつがChunk dataをバラしてくれるみたい。

/* The data block containing the image chunk and the other chunks has a self-descriptive layout.
   A chunk parser is used to extract the appended chunk data from the grabbed image frame.
   Create a chunk parser. */
hChunkParser = Pylon.DeviceCreateChunkParser(hDev);

if (!hChunkParser.IsValid)
{
     /* The transport layer doesn't provide a chunk parser. */
     throw new Exception("No chunk parser available.");
}

画像取込後、取り込んだ画像にChunk dataが付加されているかを判定します、
以下は判定部分だけ抜粋、付加されていた場合の処理はelse以下に続きます。

/* Check to see if we really got image data plus chunk data. */
if (grabResult.PayloadType != EPylonPayloadType.PayloadType_ChunkData)
{
     Console.WriteLine("Received a buffer not containing chunk data?");
}
else

実際のChunk dataを取り出す処理です。(上記のelse以降に記述されている)
ChunkParserが設定されていれば、各Chunk dataは通常のパラメータと同様に、
Pylon.DeviceGetIntegerFeature等で値を取得出来るようですね、簡単。

ここではChunkFramecounterとChunkWidth、ChunkHeightの3つを読んでいますが、
ChunkWidthとChunkHeightは初期設定しなくても読めるのかな?、謎が残りました。

/* Retrieve the frame counter value. */
/* ... Check the availability. */
isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "ChunkFramecounter");
Console.WriteLine("Frame {0} {1} a frame counter chunk.", nGrabs, isAvail ? "contains" : "doesn't contain");
if (isAvail)
{
     /* ... Get the value. */
     long counter;
     counter = Pylon.DeviceGetIntegerFeature(hDev, "ChunkFramecounter");
     Console.WriteLine("Frame counter of frame {0}: {1}.", nGrabs, counter);
}

/* Retrieve the chunk width value. */
/* ... Check the availability. */
isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "ChunkWidth");
Console.WriteLine("Frame {0} {1} a frame width chunk.", nGrabs, isAvail ? "contains" : "doesn't contain");
if (isAvail)
{
     /* ... Get the value. */
     chunkWidth = Pylon.DeviceGetIntegerFeature(hDev, "ChunkWidth");
     Console.WriteLine("Width of frame {0}: {1}.", nGrabs, chunkWidth);
}

/* Retrieve the chunk height value. */
/* ... Check the availability. */
isAvail = Pylon.DeviceFeatureIsAvailable(hDev, "ChunkHeight");

Console.WriteLine("Frame {0} {1} a frame height chunk.", nGrabs, isAvail ? "contains" : "doesn't contain");
if (isAvail)
{
     /* ... Get the value. */
     chunkHeight = Pylon.DeviceGetIntegerFeature(hDev, "ChunkHeight");
     Console.WriteLine("Height of frame {0}: {1}.", nGrabs, chunkHeight);
}

但しChunk dataのCRC checksumだけは例外で、専用処理が要るようです、

bool hasCRC;  
/* Check the CRC checksum. */
hasCRC = Pylon.ChunkParserHasCRC(hChunkParser);

if (hasCRC)
{
     bool isOk = Pylon.ChunkParserCheckCRC(hChunkParser);
     Console.WriteLine("Frame {0} contains a CRC checksum. The checksum {1} ok.", nGrabs, isOk ? "is" : "is not");
}

まだ完全では無いけど、おおまかな流れは判りましたので、今回はここまで。