最近使用basler相机,摸索了一段时间,找过一些其他的代码,有的不管用,有的只能拍照,无法处理相片流。其中有一个博客代码简洁明了,可以做入门学习,但是只能拍照不能录像:
https://blog.csdn.net/gy0124/article/details/103469354
以下将介绍可以实现拍照、录像功能的代码。
建议先看上面的博客,对代码有大致框架了解后再看下面的代码。
功能和控件 | 控件名称 |
---|---|
拍照 button | toolStripButtonOneShot |
录像 button | toolStripButtonContinuousShot |
停止 button | toolStripButtonStop |
相机列表 listview | UpdateDeviceList |
定时器 timer | updateDeviceListTimer |
窗体form | MainForm |
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using PylonLiveView;
using Basler.Pylon; //引入basler的动态链接库
namespace PylonLiveView
{
// 主界面
public partial class MainForm : Form
{
private Camera camera = null;//实例化一个camera
private PixelDataConverter converter = new PixelDataConverter();//后面处理图像数据
private Stopwatch stopWatch = new Stopwatch();//用于准确测量运行时间
// 构造函数
public MainForm()
{
InitializeComponent();
/* 设置参数名称。如果不需要可以删掉
testImageControl.DefaultName = "Test Image Selector";
pixelFormatControl.DefaultName = "Pixel Format";
widthSliderControl.DefaultName = "Width";
heightSliderControl.DefaultName = "Height";
gainSliderControl.DefaultName = "Gain";
exposureTimeSliderControl.DefaultName = "Exposure Time";*/
//更新相机列表:定时器定时刷新列表,将找到的相机名称显示在列表上
UpdateDeviceList();
//按钮使能状态:两个按钮(拍照和录像)
EnableButtons(false, false);
}
// 拍照的按钮(点击事件)
private void toolStripButtonOneShot_Click(object sender, EventArgs e)
{
OneShot(); // Start the grabbing of one image.
}
//录像的按钮(点击事件)
private void toolStripButtonContinuousShot_Click(object sender, EventArgs e)
{
ContinuousShot(); // Start the grabbing of images until grabbing is stopped.
}
// 停止按钮(点击事件)
private void toolStripButtonStop_Click(object sender, EventArgs e)
{
Stop(); // 停止抓取图像
}
//事件(连接断开)
private void OnConnectionLost(Object sender, EventArgs e)
{
if (InvokeRequired)
{
// 如果未触发,新建立一个事件
BeginInvoke(new EventHandler<EventArgs>(OnConnectionLost), sender, e);
return;
}
//断开相机
DestroyCamera();
//更新相机列表
UpdateDeviceList();
}
// 事件(打开相机)
private void OnCameraOpened(Object sender, EventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new EventHandler<EventArgs>(OnCameraOpened), sender, e);
return;
}
// 使能按钮(如果打开了,拍照和录像按钮显示可用)
EnableButtons(true, false);
}
// 事件(关闭相机)
private void OnCameraClosed(Object sender, EventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new EventHandler<EventArgs>(OnCameraClosed), sender, e);
return;
}
// 不使能按钮(如果断开了,拍照和录像按钮显示不可用)
EnableButtons(false, false);
}
// 事件(抓取相片)
private void OnGrabStarted(Object sender, EventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new EventHandler<EventArgs>(OnGrabStarted), sender, e);
return;
}
//停止时测量,并将事件设置为0
stopWatch.Reset();
//停止更新列表
updateDeviceListTimer.Stop();
//不使能按钮(如果断开了,拍照和录像按钮显示不可用)
EnableButtons(false, true);
}
// 事件(抓取相片后的图像处理)
private void OnImageGrabbed(Object sender, ImageGrabbedEventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new EventHandler<ImageGrabbedEventArgs>(OnImageGrabbed), sender, e.Clone());
return;
}
try
{
// 获取相片
IGrabResult grabResult = e.GrabResult;
//如获取相片为true
if (grabResult.IsValid)
{
if (!stopWatch.IsRunning || stopWatch.ElapsedMilliseconds > 33)
{
stopWatch.Restart();
//把抓取到的图片放在bitmap
Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
// 一下是图像格式转换(如果需要换成HImage或者其他格式,修改此处代码)
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
converter.OutputPixelFormat = PixelType.BGRA8packed;
IntPtr ptrBmp = bmpData.Scan0;
converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
bitmap.UnlockBits(bmpData);
// 临时bitmap用于释放上一个bitmap
Bitmap bitmapOld = pictureBox.Image as Bitmap;
//把抓取图像放在picturebox显示
pictureBox.Image = bitmap;
//如果想要保存图片,savepath是保存路径,比如public string savePath = "D:/download/0.jpg";
//bitmap.Save(savePath, System.Drawing.Imaging.ImageFormat.Jpeg);
if (bitmapOld != null)
{
// 释放bitmap
bitmapOld.Dispose();
}
}
}
}
catch (Exception exception)
{
ShowException(exception);
}
finally
{
// 释放
e.DisposeGrabResultIfClone();
}
}
// 事件(停止抓取)
private void OnGrabStopped(Object sender, GrabStopEventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new EventHandler<GrabStopEventArgs>(OnGrabStopped), sender, e);
return;
}
stopWatch.Reset();
//开始更新列表
updateDeviceListTimer.Start();
//跟上面相同,不赘述
EnableButtons(true, false);
if(e.Reason != GrabStopReason.UserRequest)
{
MessageBox.Show("A grab error occured:\n" + e.ErrorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// 相机使能方法
private void EnableButtons(bool canGrab, bool canStop)
{
toolStripButtonContinuousShot.Enabled = canGrab;
toolStripButtonOneShot.Enabled = canGrab;
toolStripButtonStop.Enabled = canStop;
}
// 关闭相机
private void Stop()
{
try
{
camera.StreamGrabber.Stop();
}
catch (Exception exception)
{
ShowException(exception);
}
}
// 断开相机
private void DestroyCamera()
{
/* 清空相机参数
try
{
if (camera != null)
{
testImageControl.Parameter = null;
pixelFormatControl.Parameter = null;
widthSliderControl.Parameter = null;
heightSliderControl.Parameter = null;
gainSliderControl.Parameter = null;
exposureTimeSliderControl.Parameter = null;
}
}
catch (Exception exception)
{
ShowException(exception);
}*/
// 断开相机
try
{
if (camera != null)
{
camera.Close();
camera.Dispose();
camera = null;
}
}
catch (Exception exception)
{
ShowException(exception);
}
// 释放转换
if (converter != null)
{
converter.Dispose();
converter = null;
}
}
// 拍照方法
private void OneShot()
{
try
{
camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.SingleFrame);
camera.StreamGrabber.Start(1, GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);
}
catch (Exception exception)
{
ShowException(exception);
}
}
// 录像方法
private void ContinuousShot()
{
try
{
camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
camera.StreamGrabber.Start(GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);
}
catch (Exception exception)
{
ShowException(exception);
}
}
// 更新列表方法
private void UpdateDeviceList()
{
try
{
// 查询相机
List<ICameraInfo> allCameras = CameraFinder.Enumerate();
ListView.ListViewItemCollection items = deviceListView.Items;
// 遍历找到的相机
foreach (ICameraInfo cameraInfo in allCameras)
{
// 设置找到新相机的bool参数
bool newitem = true;
foreach (ListViewItem item in items)
{
ICameraInfo tag = item.Tag as ICameraInfo;
// 如果列表的item名称跟相机名称一致,说明不是新的相机
if ( tag[CameraInfoKey.FullName] == cameraInfo[CameraInfoKey.FullName])
{
tag = cameraInfo;
newitem = false;
break;
}
}
// 如果有新的相机,把相机加到listview
if (newitem)
{
ListViewItem item = new ListViewItem(cameraInfo[CameraInfoKey.FriendlyName]);
string toolTipText = "";
foreach( KeyValuePair<string, string> kvp in cameraInfo)
{
toolTipText += kvp.Key + ": " + kvp.Value + "\n";
}
item.ToolTipText = toolTipText;
item.Tag = cameraInfo;
deviceListView.Items.Add(item);
}
}
//移除断开的相机
foreach (ListViewItem item in items)
{
bool exists = false;
// 如果listview的item没有一个跟找到的相机匹配,则移除
foreach (ICameraInfo cameraInfo in allCameras)
{
if (((ICameraInfo)item.Tag)[CameraInfoKey.FullName] == cameraInfo[CameraInfoKey.FullName])
{
exists = true;
break;
}
}
if (!exists)
{
deviceListView.Items.Remove(item);
}
}
}
catch (Exception exception)
{
ShowException(exception);
}
}
private void ShowException(Exception exception)
{
MessageBox.Show("Exception caught:\n" + exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// 关闭窗体时,断开相机
private void MainForm_FormClosing(object sender, FormClosingEventArgs ev)
{
// Close the camera object.
DestroyCamera();
}
//当选择新相机时,断开已有相机,连接新相机
private void deviceListView_SelectedIndexChanged(object sender, EventArgs ev)
{
if (camera != null)
{
DestroyCamera();
}
if (deviceListView.SelectedItems.Count > 0)
{
ListViewItem item = deviceListView.SelectedItems[0];
ICameraInfo selectedCamera = item.Tag as ICameraInfo;
try
{
camera = new Camera (selectedCamera);
camera.CameraOpened += Configuration.AcquireContinuous;
camera.Open();
// 相机事件与订阅者设置(详情看委托与事件,这里streamGrabber里有三个事件,分别关联三个方法,这三个方法在前面的代码。这是区别与其他博客代码的地方,也是实现相机不断抓取相片流的地方。)
camera.ConnectionLost += OnConnectionLost;
camera.CameraOpened += OnCameraOpened;
camera.CameraClosed += OnCameraClosed;
camera.StreamGrabber.GrabStarted += OnGrabStarted;
camera.StreamGrabber.ImageGrabbed += OnImageGrabbed;
camera.StreamGrabber.GrabStopped += OnGrabStopped;
/*Set the parameter for the controls.
testImageControl.Parameter = camera.Parameters[PLCamera.TestImageSelector];
pixelFormatControl.Parameter = camera.Parameters[PLCamera.PixelFormat];
widthSliderControl.Parameter = camera.Parameters[PLCamera.Width];
heightSliderControl.Parameter = camera.Parameters[PLCamera.Height];
if (camera.Parameters.Contains(PLCamera.GainAbs))
{
gainSliderControl.Parameter = camera.Parameters[PLCamera.GainAbs];
}
else
{
gainSliderControl.Parameter = camera.Parameters[PLCamera.Gain];
}
if (camera.Parameters.Contains(PLCamera.ExposureTimeAbs))
{
exposureTimeSliderControl.Parameter = camera.Parameters[PLCamera.ExposureTimeAbs];
}
else
{
exposureTimeSliderControl.Parameter = camera.Parameters[PLCamera.ExposureTime];
}*/
}
catch (Exception exception)
{
ShowException(exception);
}
}
}
// 定时器跟新列表
private void updateDeviceListTimer_Tick(object sender, EventArgs e)
{
UpdateDeviceList();
}
}
}
(1)先加入上面的控件,修改控件名称一致
(2)按钮的点击事件、定时器定时、列表选取事件、窗体关闭等都要自己点击设置,不能照着代码全部复制,不然这些事件没有注册到Designer.cs中。也就是以下几个:
private void toolStripButtonOneShot_Click(object sender, EventArgs e){……}
private void toolStripButtonContinuousShot_Click(object sender, EventArgs e){……}
private void toolStripButtonStop_Click(object sender, EventArgs e){……}
private void deviceListView_SelectedIndexChanged(object sender, EventArgs ev){……}
private void updateDeviceListTimer_Tick(object sender, EventArgs e){……}
private void MainForm_FormClosing(object sender, FormClosingEventArgs ev){……}
(3)代码完整下载(包括其他功能,可启动运行):
https://download.csdn.net/download/chotin/12098938