0
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?

【C#】カメラでQRコードとバーコード読取-AForge.NET-

Last updated at Posted at 2024-12-10

今回はAForge.NETとdelegateを使うやり方。
delegateの練習にも。使わない方法も追記。
前の記事はOpenCvSharpの古いバージョンに依存中。
(CaptureMat➡Bitmap(pictureBox.Imageと解析用)に変換するのがTask内で簡単にできる)

参考にさせていただきました。

事前準備

以下を追加
 AForge.Video
 AForge.Video.DirectShow
 ZXing.Net

レイアウト
1212.PNG

pictureBox x1
button x2
label1 x1

カメラ・画像解析の準備

Form1.cs
using System;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using ZXing;

FilterInfoCollection videoDevices;
VideoCaptureDevice videoSource;
ZXing.BarcodeReader reader = new ZXing.BarcodeReader();
bool code_request = true;
Bitmap bmp;
delegate void DelegateProcess();
Task task;

     private void Form1_Load(object sender, EventArgs e)
     {
        reader.Options = new ZXing.Common.DecodingOptions
        {
            TryHarder = true,
            //読み取るコードの種類
            PossibleFormats = new[] { BarcodeFormat.QR_CODE, BarcodeFormat.EAN_13 }.ToList()
        };
        videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
        if (videoDevices.Count == 0)
        {
            MessageBox.Show("カメラがありません");
            return;
        }
        //外部カメラ優先
        videoSource = new VideoCaptureDevice(videoDevices[videoDevices.Count-1].MonikerString);
        videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
        videoSource.Start();
     }

    //pictureBoxに反映
    private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
    }

Taskとdelegate

非同期⇔UIときたらdelegateかInvoke。

Form1.cs
    private void Form1_Shown(object sender, EventArgs e)
    {
        //pictureBoxサイズをユーザ側で変更できないならここで一回呼び出す
        bmp= new Bitmap(pictureBox1.Width, pictureBox1.Height);            
        codeRead();
    }
    
    private void codeRead()
    {
        DelegateProcess process = new DelegateProcess(bitMapInput);
        Result result;
        try
        {
            task = Task.Run(() =>
            {
                while (code_request)
                {
                    //そこまでまめにやらなくていい
                    System.Threading.Thread.Sleep(1000);
                    //UI情報取得(pictureBox.ImageをBitmapに変換)
                    this.Invoke(process);
                    result = reader.Decode(bmp);
                    if (result != null)
                    {
                        Console.WriteLine(result.Text);
                        //label(UI)に反映
                        Invoke(new Action(() =>
                        {
                            label1.Text = result.Text;
                        }));
                    }
                }
             });
        }
        catch (Exception e) { Console.WriteLine(e.Message);}
    }
    private void bitMapInput()//UIを取得する処理
    {
        try
        {
            if (pictureBox1.Image != null)
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.DrawImage(pictureBox1.Image, 0, 0);
            }
        }
        catch(InvalidOperationException e) { Console.WriteLine(e.Message); }
    }

仕上げ

Form1.cs
    private async void stopCamera() 
    {
        if (videoSource != null && videoSource.IsRunning)
        {
            code_request = false;
            videoSource.SignalToStop();
            videoSource.WaitForStop();
            
            await task;
        }
    }
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        stopCamera();
    }
    private void stop_button_Click(object sender, EventArgs e)
    {
        stopCamera();
    }
     private void start_button_Click(object sender, EventArgs e)
    {
        code_request = true;
        videoSource.Start();
        codeRead();
    }

おまけ delegateを使わないCopyFromScreen

メイン画面をCaptureしUIへ干渉しなければいい。
ただし画像は大きい。位置情報とサイズの考慮でどうにかなる?
➡なりました(追記)
QRコードは問題ないがバーコードだと解像度を上げるかdelegateを使った方が良い。

    //全体キャプチャ
    //Rectangle bounds = Screen.PrimaryScreen.Bounds;
    Rectangle bounds = pictureBox1.RectangleToScreen(pictureBox1.ClientRectangle);
    Bitmap bmp = new Bitmap(Bounds.Width, bounds.Height);
    Point upperLeftSource = bounds.Location;
    Result result;
    try
    {
        task = Task.Run(() =>
        {
            while (code_request)
            {
                System.Threading.Thread.Sleep(1000);
                using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
                {
                    // Graphicsオブジェクトを使用して画面全体をキャプチャ
                    //using (Graphics g = Graphics.FromImage(bitmap))
                    //{
                        //g.CopyFromScreen(System.Drawing.Point.Empty, System.Drawing.Point.Empty, bounds.Size);
                    //}
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        g.CopyFromScreen(
                        upperLeftSource, System.Drawing.Point.Empty,
                        bounds.Size, CopyPixelOperation.SourceCopy);
                    }
                    Result result = reader.Decode(bitmap);
                    if (result != null)
                    {
                        Invoke(new Action(() =>
                        {
                            label1.Text = result.Text;
                        }));
                    }
                }
            }
        });
    }

参考

0
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
0
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?