2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【OpenCvSharp+ZXing】C#で簡単カメラ起動➡バーコード・QRコード読取

Last updated at Posted at 2024-11-29

カメラで連続読取り
OpenCvSharpとZXingを使用。

前提

カメラがあること。
そして読み取りやすい大きなバーコード・QRコード。
特にバーコードは小さいと読めない。
画質というより接写でのピントが合うカメラがいいだろう。

全体の流れ

1.レイアウト準備
2.パッケージインストール
3.カメラ準備
4.Task処理
5.画像解析

1.レイアウト準備

334e.png

pictureBox × 1
button × 2
label × 1

2.パッケージインストール

※最新バージョンではない
OpenCvSharp 4.5.5.20211231
OpenCvSharp4.Extensions 4.5.5.20211231
ZXing 0.16.8

OpenCvSharpに依存しない方

3.カメラ準備

Form1.cs
using OpenCvSharp;
using OpenCvSharp.Extensions;
using ZXing;
using System.Threading;
using System.Threading.Tasks;

VideoCapture capture;
bool code_request = true;
Task task;

    public Form1()
    {
        //i=カメラの最大数で検索
        //0がインカメ, 1以上がアウトカメラや外部接続カメラ
        //今回はインカメより精度が出そうな外部カメラを優先のため減算
        for(int i = 10; i >= 0; i--)
        {
             capture = new VideoCapture(i); 
             if(capture.IsOpened()) break;
        }
        if(!capture.IsOpened())
        {
            MessageBox.Show("camera was not found!");
            this.Close();
        }
        //後述
        cameraStart();
    }

4.Task

カメラ映像から一枚一枚画像を取り解析している。

    private void cameraStart()
    {
        //画像処理QRコード
        //コードの解析準備
        ZXing.BarcodeReader reader = new ZXing.BarcodeReader();
        reader.Options = new ZXing.Common.DecodingOptions
        {
            TryHarder = true,
            //コードの種類 ※EANは8桁、13桁がある
            PossibleFormats = new[] { BarcodeFormat.QR_CODE, BarcodeFormat.EAN_13 }.ToList()
        };
        task = Task.Run(() =>
        {
            using (Mat normalframe = new Mat())
            while (code_request)
            {
                capture.Read(normalframe);
                if (!normalframe.Empty())
                {
                    this.pictureBox1.Image = normalframe.ToBitmap();
                    //デコーダ処理
                    Result result = reader.Decode(normalframe.ToBitmap());
                    if (result != null)
                    {
                        Console.WriteLine(result.ToString());
                        //処理が早すぎる為待ち時間
                        System.Threading.Thread.Sleep(1000);
                        Invoke(new Action(() =>
                        {
                            label1.Text = result.Text;
                        }));
                    }
                }
            }
        });
    }
    private async void stopCamera()
    {
        if (task.Status == TaskStatus.Running)
        {
            code_request = false;
            await task;
        }
    }
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        stopCamera();
    }
    private void start_button_Click(object sender, EventArgs e)
    {
        code_request = true;
        cameraStart();
    }
    private void stop_button_Click(object sender, EventArgs e)
    {
        stopCamera();
    }

おまけ backgroundWorker

古い手だがbackgroundWorkerを使う手段もある。
Invokeの代わりにProgressChangedでUI処理をする。
5555.PNG

    public Form1()
    {
        //カメラ検索中略
        this.backgroundWorker1.WorkerSupportsCancellation = true;
        backgroundWorker1.RunWorkerAsync();
    }
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        ZXing.BarcodeReader reader = new ZXing.BarcodeReader();
        reader.Options = new ZXing.Common.DecodingOptions
        {
            TryHarder = true,
            PossibleFormats = new[] { BarcodeFormat.QR_CODE,BarcodeFormat.EAN_8 }.ToList()
        };
        using(Mat normalframe = new Mat())
        while(code_request)
        {
            capture.Read(normalframe);
            if(!normalframe.Empty())
            {
                this.pictureBox1.Image = normalframe.ToBitmap();    
                Result result = reader.Decode(normalframe.ToBitmap());
                if(result != null)
                {
                    Console.WriteLine(result.ToString());   
                    // ReportProgressメソッドを使って、ProgressChangedイベントを発生させる
                    this.backgroundWorker1.ReportProgress(0, result);
                    System.Threading.Thread.Sleep(1000);
                }
            }
        }
    }
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        //結果を取得
        Result result = (Result)e.UserState;
        if(!backgroundWorker1.CancellationPending)
        {
            label1.Text = result.Text;
        }
    }
     private void start_button_Click(object sender, EventArgs e)
     {
         code_request = true;
         backgroundWorker1.RunWorkerAsync();
     }
     private void stop_button_Click(object sender, EventArgs e)
     {
         backgroundWorker1.CancelAsync();
         code_request = false;
     }
     private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        backgroundWorker1.CancelAsync();
        code_request = false;
        while (backgroundWorker1.IsBusy);
    }
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?