4.1 Winform 프로젝트 만들기

  •  Basler 솔루션 안에 BaslerMultiCameraGrab이라는 이름으로 Windows Forms 앱 (.NET Framework) 프로젝트를 만들고 C#작업환경 만들기를 참조하여 Basler.Pylon.dll을 참조 추가한다.

2024.02.08 - [Basler] - 1. c# 작업 환경 만들기

 

1. c# 작업 환경 만들기

Basler 홈페이지에서 제공하는 Pylon Viewer를 설치한다 현재 내가 PC에 설치한 6.2.0 기준으로 (Pylon Viewer 설치 경로)\pylon 6\Development\Assemblies\Basler.Pylon\ 하위에 x64, x86폴더로 나눠져 있고 이중에 자기 os

machinevision-story.tistory.com

 

4.2 UI 디자인

 

  • 도구 상자에서 Button 8개와 PictureBox 2개를 드래그 하여 Form1에 위치 시킨다

 

 

  • button과 Name속성과 button의 Text속성을 아래 표와 같이 변경한다.
컨트롤 이름 속성
button1 Name BtnOpenCam0
Text Connect
button2 Name BtnGrabStartCam0
Text GrabStart
button3 Name BtnGrabStopCam0
Text GrabStop
button4 Name BtnCloseCam0
Text Disconnect
button5 Name BtnOpenCam1
Text Connect
button6 Name BtnGrabStartCam1
Text GrabStart
button7 Name BtnGrabStopCam1
Text GrabStop
button8 Name BtnCloseCam1
Text Disconnect

 

4.3 코드 입력

 

  • 각 버튼을 더블클릭하여 이벤트를 생성한 후 코드를 입력한다.
using Basler.Pylon;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BaslerMultiCameraGrab
{
    public partial class Form1 : Form
    {
        List<ICamera> cameras = new List<ICamera>();
        private PixelDataConverter converter = new PixelDataConverter();
        public Form1()
        {
            InitializeComponent();
            List<ICameraInfo> cameraInfos = CameraFinder.Enumerate();
            for (int i = 0; i < cameraInfos.Count; i++)
            {
                Camera camera = new Camera(cameraInfos[i]);
                camera.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed;
                camera.StreamGrabber.UserData = i;
                cameras.Add(camera);
            }
        }

        private void BtnOpenCam0_Click(object sender, EventArgs e)
        {
            cameras[0].Open();
            cameras[0].Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
        }

        private void BtnGrabStartCam0_Click(object sender, EventArgs e)
        {
            cameras[0].StreamGrabber.Start(GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);
        }

        private void BtnGrabStopCam0_Click(object sender, EventArgs e)
        {
            cameras[0].StreamGrabber.Stop();
        }

        private void BtnCloseCam0_Click(object sender, EventArgs e)
        {
            cameras[0].Close();
        }

        private void BtnOpenCam1_Click(object sender, EventArgs e)
        {
            cameras[1].Open();
            cameras[1].Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
        }

        private void BtnGrabStartCam1_Click(object sender, EventArgs e)
        {
            cameras[1].StreamGrabber.Start(GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);
        }

        private void BtnGrabStopCam1_Click(object sender, EventArgs e)
        {
            cameras[1].StreamGrabber.Stop();
        }

        private void BtnCloseCam1_Click(object sender, EventArgs e)
        {
            cameras[1].Close();
        }

        private void StreamGrabber_ImageGrabbed(object sender, ImageGrabbedEventArgs e)
        {
            IStreamGrabber cam = sender as IStreamGrabber;
            int camIndex = (int)cam.UserData;
            PictureBox pictureBox = null;
            if (camIndex == 0)
            {
                pictureBox = pictureBox1;
            }
            if (camIndex == 1)
            {
                pictureBox = pictureBox2;
            }
            IGrabResult grabResult = e.GrabResult;
            if (grabResult.GrabSucceeded)
            {
                Bitmap bitmap = ConvertResultToBitmap(grabResult);
                if (InvokeRequired)
                {
                    BeginInvoke(new Action(() =>
                    {
                        Bitmap bitmapOld = pictureBox.Image as Bitmap;
                        pictureBox.Image = bitmap;
                        if (bitmapOld != null)
                        {
                            bitmapOld.Dispose();
                        }
                    }));
                }
            }
        }

        private Bitmap ConvertResultToBitmap(IGrabResult grabResult)
        {
            Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
            BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
            IntPtr ptrBmp = bmpData.Scan0;
            converter.OutputPixelFormat = PixelType.BGRA8packed;
            converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
            bitmap.UnlockBits(bmpData);
            return bitmap;
        }
    }
}

 

4.4 구문 설명

 

List<ICameraInfo> cameraInfos = CameraFinder.Enumerate();
  • 카메라가 2대 이상일 경우 CameraFinder를 사용하면 보다 편리하게 ICameraInfo 리스트를 얻을 수 있다.
  • 현재 접속되어 있는 카메라를 받아오는 함수이며 특정 Device 타입만 불러오고 싶다면 DeviceType이라는 static 클래스를 매개변수로 넣어주면 해당 타입만 받아올 수 있다. (ex. GigE, Usb ..)
for (int i = 0; i < cameraInfos.Count; i++)
{
    Camera camera = new Camera(cameraInfos[i]);
    camera.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed;
    camera.StreamGrabber.UserData = i;
    cameras.Add(camera);
}
  • Camera 클래스 생성자에 ICameraInfo 변수를 넣으면 특정 카메라 인스턴스를 생성할 수 있다.
  • 반복문을 돌려서 List<Camera> 클래스에 Add하는 구문이다.
  • UserData 항목은 StreamGrabber_ImageGrabbed 함수내부에서 sender인 카메라를 구분하기 위한 Index역할이다.

 

<StreamGrabber_ImageGrabbed>

IStreamGrabber cam = sender as IStreamGrabber;
int camIndex = (int)cam.UserData;
PictureBox pictureBox = null;
if (camIndex == 0)
{
    pictureBox = pictureBox1;
}
if (camIndex == 1)
{
    pictureBox = pictureBox2;
}
  • 앞 장의 StreamGrabber_ImageGrabbed함수와 구조는 동일하나 카메라 여러대가 하나의 이벤트 함수를 사용하기 때문에 어떤 카메라에서 발생한 이벤트인지 알기 위해서 매개변수인 sender의 UserData를 camera index로 참조한다.
  • 앞서 Camera 인스턴스를 생성하는 구문에서 넣어둔 UserData가 사용된다.
  • UserData를 원래 타입이었던 int로 형변환 한 후 인덱스가 0,1일때 해당 카메라가 연결되는 picturebox를 할당해서 Image를 넣는다.
IGrabResult grabResult = e.GrabResult;
if (grabResult.GrabSucceeded)
{
    Bitmap bitmap = ConvertResultToBitmap(grabResult);
    if (InvokeRequired)
    {
        BeginInvoke(new Action(() =>
        {
            Bitmap bitmapOld = pictureBox.Image as Bitmap;
            pictureBox.Image = bitmap;
            if (bitmapOld != null)
            {
                bitmapOld.Dispose();
            }
        }));
    }
}
  • IGrabResult를 Bitmap으로 바꾸는 구문은 함수 ConvertResultToBitmap()으로 빼고 진행해 보았다.
  • 나머지는 앞의 글들과 같다.

4.5 결과

 

'Basler' 카테고리의 다른 글

5. Reconnect Camera  (1) 2024.02.16
3. Continue shot Grab  (0) 2024.02.13
2. One shot Grab  (0) 2024.02.11
1. c# 작업 환경 만들기  (0) 2024.02.08

+ Recent posts