Allen's 데이터 맛집

C#과 Basler Pylon을 사용한 비전 코딩: Grab Loop Thread를 이용한 이미지 수집 및 처리 본문

Programming/Pylon .Net API

C#과 Basler Pylon을 사용한 비전 코딩: Grab Loop Thread를 이용한 이미지 수집 및 처리

Allen93 2024. 8. 11. 16:23
C#과 Basler Pylon .NET API를 사용하여 Grab Loop Thread를 통해 이미지를 수집하고 처리하는 방법에 대해 설명하겠습니다. 이 샘플 코드는 Instant Camera 클래스에서 제공하는 Grab Loop Thread를 사용하여 이미지를 수집하고, 이벤트 핸들러를 통해 이미지를 처리합니다.

 

 

코드 설명

 

1. 코드 개요

 

이 샘플 코드 카메라에서 이미지를 비동기적으로 수집하고, 수집된 이미지를 처리하는 과정을 보여줍니다. Grab Loop Thread를 사용하면 이미지를 수집하는 동안 별도의 스레드에서 이미지 처리를 병행할 수 있어 효율적입니다.

using System;
using System.Threading;
using Basler.Pylon;

namespace Grab_UsingGrabLoopThread
{
    class Grab_UsingGrabLoopThread
    {
        // Example of an image event handler.
        static void OnImageGrabbed(Object sender, ImageGrabbedEventArgs e)
        {
            // The grab result is automatically disposed when the event call back returns.
            // The grab result can be cloned using IGrabResult.Clone if you want to keep a copy of it (not shown in this sample).
            IGrabResult grabResult = e.GrabResult;
            // Image grabbed successfully?
            if (grabResult.GrabSucceeded)
            {
                // Access the image data.
                Console.WriteLine("SizeX: {0}", grabResult.Width);
                Console.WriteLine("SizeY: {0}", grabResult.Height);
                byte[] buffer = grabResult.PixelData as byte[];
                Console.WriteLine("Gray value of first pixel: {0}", buffer[0]);
                Console.WriteLine("");

                // Display the grabbed image.
                ImageWindow.DisplayImage(0, grabResult);
                ImagePersistence.Save(ImageFileFormat.Bmp, "test.bmp", grabResult);
            }
            else
            {
                Console.WriteLine("Error: {0} {1}", grabResult.ErrorCode, grabResult.ErrorDescription);
            }
        }

        internal static void Main()
        {
            // The exit code of the sample application.
            int exitCode = 0;

            try
            {
                // Create a camera object that selects the first camera device found.
                // More constructors are available for selecting a specific camera device.
                using (Camera camera = new Camera(CameraSelectionStrategy.FirstFound))
                {
                    // Print the model name of the camera.
                    Console.WriteLine("Using camera {0}.", camera.CameraInfo[CameraInfoKey.ModelName]);

                    // Set the acquisition mode to software triggered continuous acquisition when the camera is opened.
                    camera.CameraOpened += Configuration.SoftwareTrigger;

                    // Open the connection to the camera device.
                    camera.Open();

                    // Set a handler for processing the images.
                    camera.StreamGrabber.ImageGrabbed += OnImageGrabbed;

                    // Start grabbing using the grab loop thread. This is done by setting the grabLoopType parameter
                    // to GrabLoop.ProvidedByStreamGrabber. The grab results are delivered to the image event handler OnImageGrabbed.
                    // The default grab strategy (GrabStrategy_OneByOne) is used.
                    camera.StreamGrabber.Start(GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);

                    // Wait for user input to trigger the camera or exit the loop.
                    // Software triggering is used to trigger the camera device.
                    Char key;
                    do
                    {
                        Console.WriteLine("Press 't' to trigger the camera or 'e' to exit.");

                        key = Console.ReadKey(true).KeyChar;
                        if ((key == 't' || key == 'T'))
                        {
                            // Execute the software trigger. Wait up to 100 ms until the camera is ready for trigger.
                            if (camera.WaitForFrameTriggerReady(100, TimeoutHandling.ThrowException))
                            {
                                camera.ExecuteSoftwareTrigger();
                            }
                        }
                    }
                    while ((key != 'e') && (key != 'E'));

                    // Stop grabbing.
                    camera.StreamGrabber.Stop();

                    // Close the connection to the camera device.
                    camera.Close();
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("Exception: {0}", e.Message);
                exitCode = 1;
            }
            finally
            {
                // Comment the following two lines to disable waiting on exit.
                Console.Error.WriteLine("\nPress enter to exit.");
                Console.ReadLine();
            }

            Environment.Exit(exitCode);
        }
    }
}

 

 

2. 주요 구성 요소 및 기능

 

a. 이미지 이벤트 핸들러 설정

static void OnImageGrabbed(Object sender, ImageGrabbedEventArgs e)
{
    IGrabResult grabResult = e.GrabResult;
    if (grabResult.GrabSucceeded)
    {
        Console.WriteLine("SizeX: {0}", grabResult.Width);
        Console.WriteLine("SizeY: {0}", grabResult.Height);
        byte[] buffer = grabResult.PixelData as byte[];
        Console.WriteLine("Gray value of first pixel: {0}", buffer[0]);
        Console.WriteLine("");

        ImageWindow.DisplayImage(0, grabResult);
        ImagePersistence.Save(ImageFileFormat.Bmp, "test.bmp", grabResult);
    }
    else
    {
        Console.WriteLine("Error: {0} {1}", grabResult.ErrorCode, grabResult.ErrorDescription);
    }
}
  • 이벤트 핸들러 설정: OnImageGrabbed 메서드는 이미지가 수집될 때 호출되는 이벤트 핸들러입니다.
  • 이미지 데이터 접근: 이미지의 크기와 첫 번째 픽셀의 그레이 값을 출력합니다.
  • 이미지 저장 및 표시: 수집된 이미지를 BMP 형식으로 저장하고, 화면에 표시합니다.

 

b. 메인 메서드

internal static void Main()
{
    int exitCode = 0;

    try
    {
        using (Camera camera = new Camera(CameraSelectionStrategy.FirstFound))
        {
            Console.WriteLine("Using camera {0}.", camera.CameraInfo[CameraInfoKey.ModelName]);

            camera.CameraOpened += Configuration.SoftwareTrigger;

            camera.Open();

            camera.StreamGrabber.ImageGrabbed += OnImageGrabbed;

            camera.StreamGrabber.Start(GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);

            Char key;
            do
            {
                Console.WriteLine("Press 't' to trigger the camera or 'e' to exit.");

                key = Console.ReadKey(true).KeyChar;
                if ((key == 't' || key == 'T'))
                {
                    if (camera.WaitForFrameTriggerReady(100, TimeoutHandling.ThrowException))
                    {
                        camera.ExecuteSoftwareTrigger();
                    }
                }
            }
            while ((key != 'e') && (key != 'E'));

            camera.StreamGrabber.Stop();

            camera.Close();
        }
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("Exception: {0}", e.Message);
        exitCode = 1;
    }
    finally
    {
        Console.Error.WriteLine("\nPress enter to exit.");
        Console.ReadLine();
    }

    Environment.Exit(exitCode);
}
  • 카메라 객체 생성 및 초기화: Camera 객체를 생성하고, 소프트웨어 트리거 연속 촬영 모드로 설정합니다.
  • 이미지 이벤트 핸들러 설정: OnImageGrabbed 이벤트 핸들러를 등록합니다.
  • 그랩 루프 스레드 시작: camera.StreamGrabber.Start 메서드를 호출하여 그랩 루프 스레드를 시작합니다.
  • 사용자 입력 처리: 사용자가 't' 키를 눌러 카메라 트리거를 실행하거나, 'e' 키를 눌러 프로그램을 종료할 수 있도록 합니다.
  • 그랩 중지 및 카메라 연결 종료: 이미지 수집을 중지하고, 카메라와의 연결을 종료합니다.

 

이 샘플 코드는 Basler Pylon .NET API를 사용하여 Grab Loop Thread를 통해 이미지를 수집하고 처리하는 방법을 보여줍니다. 이벤트 기반 비동기 이미징을 통해 이미지 수집과 처리를 병렬로 수행하여 효율성을 높일 수 있습니다. 이를 통해 실시간 모니터링 시스템이나 산업 자동화 시스템에서 매우 유용하게 사용할 수 있습니다.

해시태그

#CSharp #BaslerPylon #비동기처리 #이미지처리 #비전코딩 #프로그래밍 #오픈소스 #GitHub #코딩팁 #개발자