Allen's 데이터 맛집
C#과 Basler Pylon을 사용한 비전 코딩: Grab Loop Thread를 이용한 이미지 수집 및 처리 본문
Programming/Pylon .Net API
C#과 Basler Pylon을 사용한 비전 코딩: Grab Loop Thread를 이용한 이미지 수집 및 처리
Allen93 2024. 8. 11. 16:23C#과 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 #코딩팁 #개발자