4.1 Winform 프로젝트 만들기
- Basler 솔루션 안에 BaslerMultiCameraGrab이라는 이름으로 Windows Forms 앱 (.NET Framework) 프로젝트를 만들고 C#작업환경 만들기를 참조하여 Basler.Pylon.dll을 참조 추가한다.
2024.02.08 - [Basler] - 1. c# 작업 환경 만들기
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 |