産業用UVCカメラのすすめ 産業用UVCカメラのすすめ

HoneywellのSwiftDecoderエンジンでバーコード自動認識

SwiftDecoderとは

SwiftDecoder®(スイフトデコーダー)とは、バーコード認識を長年開発しているHoneywell社独自の高精度バーコード解読・分析アルゴリズムを使ったデコーディングソフトウェアです。TheImagingSource社のカメラと組み合わせることで低コントラスト、ダメージバーコードを素早く読み取ることができます。このサンプルではTheImagingSource社のカメラとSwiftDecoderを使ったサンプルソフトウェアとなっております。
TheImagingSource社のSDKと組み合わせることでUXに優れたカメラデコーダーアプリの開発が可能です。

SwiftDecoderは、Honeywell社からのライセンスに基づいて入手できます。 SwiftDecoderの主な特徴は非常に短いデコード時間で低分解能でもデコードすることができます。 従来のバーコード、スタックバーコード、マトリックスシンボルなどの様々バーコードをさまざまなアプリケーションに合わせて簡単に調整できます。

※Sweiftdeoderをご利用の場合は以下にお問合せください。
https://imagers.co.jp/products/swift-decoder.html

実行結果

開発環境
動作環境 Windows 10
開発環境 VisualStudio2019
開発言語 C#
ライブラリ SwiftDecoderS_SDK_(5.6.6), IC Imaging Control 3.5

カメラをライブスタート後、カメラから取得したイメージ内にバーコードが含まれる場合、イメージ内にあるバーコードをオーバレイで四角く囲み、バーコードで読み取った数値をテキストボックスにリアルタイムで出力するサンプルとなります。

サンプルコード解説

ファイル構成

SwiftDecoder™S では、サンプルプログラムにC#で利用が可能なラッパークラス(SDクラス)を用意しており、SwiftDecoder™S のライブラリをDllImportする形でC#で使用できるようにしています。 IC Imaging Contorlをインストール後、SwiftDecoderS_SDKに含まれるSD.csファイルをソリューション内に、libid_FlexRelease_x64.dllをexeフォルダに配置します。

下記ではTheImagingSourceが提供しているIC Imaging ControlとHoneywell社が提供しているSwiftDecoderS_SDKを使って制御する方法について簡単に説明をします。

using ディレクティブ
using Honeywell.SwiftDecoder;
using TIS.Imaging;

using ディレクティブ(名前空間の使用)でSwiftDecoderS_SDK_(5.2.18),IC Imaging Control 3.5を指定します。

Form_loadイベントハンドラ
private void Form1_Load_1(object sender, EventArgs e)
{
    icImagingControl1.ShowDeviceSettingsDialog();
    //FrameQueueSinkクラスを使用してカラーフォーマットY800のみ受け入れるコールバックするように設定する
    _sink = new TIS.Imaging.FrameQueueSink((arg) => NewBufferCallback(arg), TIS.Imaging.MediaSubtypes.Y800, 5);
    //使用するシンクを設定
    icImagingControl1.Sink = _sink;

    if (!icImagingControl1.DeviceValid)
    {
        cmdStartLive.Enabled = false;
        cmdSettings.Enabled = false;
    }

    // ディスプレイサイズを変更してビデオをフルコントロールサイズにストレッチします
    icImagingControl1.LiveDisplayDefault = false;
    icImagingControl1.LiveDisplaySize = icImagingControl1.Size;
    icImagingControl1.LiveDisplay = false;

    icImagingControl1.OverlayBitmapPosition = PathPositions.None;
    // license keyを使ってアクティベーションを行う
    string licenseKey = "xxxxxxxx";
    string path = "./";
    EntitlementActivateOnline (path, licenseKey);

}
public static bool EntitlementActivateOnline(string storagePath, string Entitlement_id)
{
    try
    {

        if (SD.RemoteEntitlementActivation(Entitlement_id, storagePath) == 1)
        {
            //license key onlineのアクティベーション成功
            return true;
        }
        else
        {
            //license key onlineのアクティベーション失敗
            return false;
        }
    }
    catch
    {
        MessageBox.Show("オンライン認証失敗\n" + "libid_FlexRelease_x64.dllがないので指定のフォルダに追加してください。");
        return false;
    }
}

カメラのフレームを取得する度毎にコールバックされる関数NewBufferCallbackを定義しています。
バーコードを読み出すときにモノクロである必要があるのでここではY800のカラーフォーマットを指定しています。
後はデバイスの設定を行い、ライセンス認証のためにSwiftDecoderのAPI:EntitlementActivateOnlineメソッドを呼び出すだけで準備が完了します。

コールバック関数
  private static System.Drawing.Bitmap _image;
  private static IFrameQueueBuffer _currentlyDisplayedBuffer;
  private FrameQueueSink _sink;
  private FrameQueuedResult NewBufferCallback(IFrameQueueBuffer buffer)
  {
    try
    {
        //取得したイメージバッファをSystem.Drawing.Bitmapオブジェクトに渡す。
        _image = buffer.CreateBitmapWrap();

        //デコード処理(SwiftDecoderでフレームを処理)
        barcodedecode(_image);
        //SwiftDecoderがデコードしたバーコードの周りを囲った
        //イメージバッファを画面に表示する
        _currentlyDisplayedBuffer = buffer;
        icImagingControl1.DisplayImageBuffer(buffer);

    }
    catch (Exception ex)
    {
        System.Diagnostics.Trace.WriteLine(ex.Message);
    }
    return FrameQueuedResult.ReQueue;
  }
}

コールバック関数では取得したイメージをbitmap形式にしてメモリに格納します。
その後、デコード処理を行い、デコードされたバーコードを囲うラインをディスプレイに表示するようにします。

デコード処理
static List<byte[]> resultList;
static List<String> propertyList;
private int handle = 0;
private void barcodedecode(System.Drawing.Bitmap buffer)
{

    try
    {

        // デコードされた文字列を格納するリストを作成
        resultList = new List<byte[]>();

        // カメラで取得したイメージバッファを渡す
        System.Drawing.Bitmap image = buffer;
        // 画像が正しい形式であることを確認
        if (image.PixelFormat != System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
        {
            throw new System.ApplicationException("File is not 8 bit grayscale image");
        }

        // 画像データへのポインタを取得します
        System.Drawing.Rectangle imageSize;
        imageSize = new System.Drawing.Rectangle(0, 0, image.Width, image.Height);
        System.Drawing.Imaging.BitmapData imageData = image.LockBits(imageSize, System.Drawing.Imaging.ImageLockMode.ReadOnly, image.PixelFormat);


        // SwiftDecoderオブジェクトを作成する
        handle = SD.Create();

        // SwiftDecoderのバージョンを取得
        Vitals(handle);

        // 画像の解像度・ピクセル データのアドレスなどを設定する
        SD.Set(handle, SD.PROP_IMAGE_POINTER, imageData.Scan0);
        SD.Set(handle, SD.PROP_IMAGE_WIDTH, imageData.Width);
        SD.Set(handle, SD.PROP_IMAGE_LINE_DELTA, imageData.Stride);
        SD.Set(handle, SD.PROP_IMAGE_HEIGHT, imageData.Height);

        //Unattended operating modeにする
        //Manual operating modeの場合コメントアウトにしてください。
        IntPtr pnum = new IntPtr(SD.CONST_UNOP);
        SD.Set(handle, SD.PROP_MISC_OP_MODE, pnum);


        // コールバックポインタで結果を取得
        SD.Callback callback = new SD.Callback(ResultCallback);
        SD.Set(handle, SD.PROP_CALLBACK_RESULT, callback);

        // Code 128 と Code 39を使用する
        SD.Set(handle, SD.PROP_C128_ENABLED, SD.CONST_ENABLED);
        SD.Set(handle, SD.PROP_C39_ENABLED, SD.CONST_ENABLED);

        //ファイルに設定したプロパティリストを書き込む
        propertyList = new List<String>();
        WritePropDumpFile(handle);

        // デコード実施

        SD.Decode(handle);


        // SwiftDecoderオブジェクトを破棄
        SD.Destroy(handle);

        // メモリから Bitmap のロックを解除
        image.UnlockBits(imageData);

        // リソースの解放
        image.Dispose();

        // テキストボックスに結果を入れる
        foreach (byte[] resultString in resultList)
        {
            _text += "Result:" + System.Text.Encoding.ASCII.GetString(resultString) + "\r\n";

        }


    }
    catch (Exception ex)
    {
        System.Diagnostics.Trace.WriteLine(ex.Message);
    }
    finally
    {

        if (handle!=0)
        {
            SD.Destroy(handle);
        }

    }

}

ここでは取得したイメージからイメージ内にあるバーコード結果を取得する関数となります。
まず、カメラから取得したイメージバッファ上のバーコードを読み取るためにはカラーフォーマットは8bitのGrayScaleである必要がありますのでチェックをかけます。SDクラスのCreateメソッドを使えば簡単に取得したイメージに対してデコード処理を適用することができます。

次にデコードのモードを選択します。デコード処理は下記の2種類のモードが用意されております。

1)Unattended operating mode

このモードは特別モードとなります。画像の中のバーコード位置がランダムで、且つ、対象物が動いている場合、Manual operating modeよりも読み取りパフォーマンスが飛躍的に伸びます。「Unattended operating mode」にするにはコールバック関数を呼ぶ前に下記の2文を入れることによって、すべてのデコード対象のシンボル(例えばEANやQRなど)に「Unattended operating mode」を適用されます。

IntPtr pnum = new IntPtr(SD.CONST_UNOP);
SD.Set(handle, SD.PROP_MISC_OP_MODE, pnum);
2)Manual operating mode

こちらは標準モードとなります。画像の比較的中心にバーコードがある場合は、こちらのモードの使用を推奨いたします。

次にデコードする内容を設定します。ここでは設定するデコードの種類を指定Code128とCode39とします。 なお、Code128とCode39以外にもQRコードやOCR読み込みなど豊富にそろえております。
その他のデコーダーについてはSwiftDecoderS_SDKに付属されているマニュアルに記載がありますのでマニュアルを参考にしてください。

SD.Set(handle, SD.PROP_C128_ENABLED, SD.CONST_ENABLED);
SD.Set(handle, SD.PROP_C39_ENABLED, SD.CONST_ENABLED);

次にデコード処理を行います。デコードは下記の一文だけで処理が可能です。

SD.Decode(handle);

読み込んだ画像に該当するデコードできる情報(バーコードの情報など)があれば、下記のコールバック関数が呼び出され実行されます。

static  unsafe void ResultCallback(int handle)
{
    int length = 0;
    byte[] resultString;

    SD.STRUCT_BOUNDS Bounds= new SD.STRUCT_BOUNDS() ;

    // 長さを取得
    SD.Get(handle, SD.PROP_RESULT_LENGTH, out length);

    resultString = new byte[length];

    // 文字列を取得
    SD.Get(handle, SD.PROP_RESULT_STRING, resultString);
    SD.Get(handle, SD.PROP_RESULT_BOUNDS, ref Bounds);


    // デコードの位置を取得
    RECT Region;
    if (Bounds.Point0.Y <= Bounds.Point2.Y)
    {
        Region.Top = Bounds.Point0.Y;
        Region.Bottom = Bounds.Point2.Y;
    }
    else
    {
        Region.Top = Bounds.Point2.Y;
        Region.Bottom =  Bounds.Point0.Y;
    }
    if (Bounds.Point0.X <= Bounds.Point2.X)
    {

        Region.Left = Bounds.Point0.X;
        Region.Right = Bounds.Point2.X;
    }
    else
    {

        Region.Left = Bounds.Point2.X;
        Region.Right = Bounds.Point0.X;

    }

    //デコードの位置を四角で囲む
    DrawRectangleY8(_currentlyDisplayedBuffer, Region);

    // resultlistに追加
    resultList.Add(resultString);
}

デコードエンジンでバーコードなどのシンボルを検知したときに上記のコールバック関数が呼び出されます。 検知されたバーコードの位置・文字数値情報はをこの関数内ですべて取得できます。
上記ではDrawRectangleY8を使って検知したバーコードをオーバレイで表示しています。
SD.Get()メソッドで取得した結果をresultListに格納することでデコードが完了となります。

一部のメソッド・関数等については一部省略しておりますが、お問い合わせいただければソリューションファイルをご提供することも可能ですのでお気軽にお問い合わせください。