一,首先先配置生成项目,根据官方文档步骤来:

这个没啥好说的,一步步照做就是了,就最后一步,开始我没重视,最后代码写完测试的时候还真的遇到问题了,一直出这样的错:

查了官方文档才看到最后一条~,然后在项目属性中把这个勾掉了,代码完美运行拉……

二,功能步骤

其实整个步骤很简单:

1,首先初始化连接相机:点击Init按钮会有MessageBox打印相机名

2,然后读取配置文件(配置文件是通过官方自带的CamExpert来生成的)读取参数,也可以在程序中配置,本程序有个setting按钮,按一下就可以配置拉,把想配置的参数写在对应的代码块里(当然小编很懒,没做显示的功能,所以按按钮的时候你可能觉得按了个寂寞,但已经配置好了)。还有个读取参数的按钮(当然小编也没做显示的功能,所以也按了个寂寞),但有助于debug的时候查看数据,也可以自己打印出来看看。

3,Snap是快照,可以设置快照的张数,因为写本程序时只有相机没有镜头,所以是黑乎乎一片…但用光源照的时候会呈现白色,所以还是有点反应知道不是卡住的哈哈。    4,Grab就是连续抓取图像了,Freeze是停止。

5,最后的保存结果(没有镜头只能可怜巴巴的用感光性来测试了T_T)    PS:程序最重要的是一个回调函数:m_Xfer_XferNotify,每读取一帧图片的时候会调用这个函数,当然回调函数是自己加的,通过这个命令:

m_Xfer.XferNotify += new SapXferNotifyHandler(m_Xfer_XferNotify);

这条命令和m_Xfer_XferNotify函数是精髓!精髓!精髓!

没啥说的,上代码。可运行代码一字不差的放上来咯,注释也尽可能详细了:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.Drawing.Imaging;

using DALSA.SaperaLT.SapClassBasic;

namespace dalsaSave

{

public partial class Form1 : Form

{

// 全局变量

private static int picCountNum = 0; // 统计采集了多少张图,有利于理解m_Xfer.Sanp(15)中15的意思

private string configFilePath = @"D:\T_Linea_M4096-7um_Default_Default.ccf"; // 配置文件的路径

private string imgPath = @"D:\imgs\"; //采集图片保存地址

private SapLocation m_ServerLocation; // 设备的连接地址

private SapAcqDevice m_AcqDevice; //采集设备

private SapBuffer m_Buffers; // 缓存对象

private SapAcqDeviceToBuf m_Xfer; // 传输对象

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

}

private void Form1_FormClosed(object sender, FormClosedEventArgs e)

{

DestroyObjects();

DisposeObjects();

}

// 初始化并连接相机

private void btn_init_Click(object sender, EventArgs e)

{

CreateNewObjects();

}

private void btn_setting_Click(object sender, EventArgs e)

{

// 设置曝光值,为了设置的值不超限,需要获取曝光值的允许范围(主要是最大值)

double valuetemp = GetMaxValue("ExposureTime");

if (valuetemp > 0)

{

m_AcqDevice.SetFeatureValue("ExposureTime", valuetemp);

}

m_AcqDevice.SetFeatureValue("Gain", "9.9");

}

private void btn_getValue_Click(object sender, EventArgs e)

{

string deviceModelName;

string deviceUserId;

string pixelFormat;

string triggerMode;

double acquisitionLineRate; // 行频和曝光时间不能设置为int类型

double exposureTime;

double gain;

int width;

int height;

int sensorWidth;

int sensorHeight;

m_AcqDevice.GetFeatureValue("DeviceModelName", out deviceModelName); //Linea M4096-7um

m_AcqDevice.GetFeatureValue("DeviceUserID", out deviceUserId); //空

m_AcqDevice.GetFeatureValue("PixelFormat", out pixelFormat); //Mono8

m_AcqDevice.GetFeatureValue("TriggerMode", out triggerMode); //Off

m_AcqDevice.GetFeatureValue("AcquisitionLineRate", out acquisitionLineRate); //10000.0

m_AcqDevice.GetFeatureValue("ExposureTime", out exposureTime); //70.0

m_AcqDevice.GetFeatureValue("Gain", out gain); //9.0

m_AcqDevice.GetFeatureValue("Width", out width); //4096

m_AcqDevice.GetFeatureValue("Height", out height); //2800

m_AcqDevice.GetFeatureValue("SensorWidth", out sensorWidth); //4096

m_AcqDevice.GetFeatureValue("SensorHeight", out sensorHeight); //1

}

#region

private void btn_snap_Click(object sender, EventArgs e)

{

// Snap() 只采集一张, 如果是Snap(15)则连续采集15张

m_Xfer.Snap(15); //m_Xfer.Snap(m_Buffers.Count)

}

private void btn_grab_Click(object sender, EventArgs e)

{

m_Xfer.Grab();

}

//关闭的时候,执行Freez()停止采集,线程等待5秒,

//目的是停止采集后,将还存在内存地址通道中的裸数据都取出来,

//如果freeze之后直接释放,就拿不到还在地址上的数据了,缓存对象释放之后,将本次采集所有对象摧毁。

private void btn_freeze_Click(object sender, EventArgs e)

{

m_Xfer.Freeze();

}

#endregion

//得到所有连接的相机信息,并将他们加入到ArrayList里面去

public bool GetCameraInfo(out string sCameraName, out int nIndex)

{

Console.WriteLine("开始获取相机信息");

sCameraName = "";

nIndex = 0;

// 查询相机数量

int serverCount = SapManager.GetServerCount();

int GenieIndex = 0;

// 实例化一个list,作为容器

System.Collections.ArrayList listServerNames = new System.Collections.ArrayList();

bool bFind = false;

string serverName = "";

for (int serverIndex = 0; serverIndex < serverCount; serverIndex++)

{

if (SapManager.GetResourceCount(serverIndex, SapManager.ResourceType.AcqDevice) != 0)

{

serverName = SapManager.GetServerName(serverIndex);

listServerNames.Add(serverName);

GenieIndex++;

bFind = true;

}

}

int count = 1;

string deviceName = "";

foreach (string sName in listServerNames)

{

deviceName = SapManager.GetResourceName(sName, SapManager.ResourceType.AcqDevice, 0);

count++;

}

sCameraName = serverName;

nIndex = GenieIndex;

return bFind;

}

// 初始化并连接相机

public bool CreateNewObjects()

{

Console.WriteLine("相机初始化");

string Name;

int Index;

// 获取相机详细信息

bool RTemp = GetCameraInfo(out Name, out Index);

if (RTemp)

{

MessageBox.Show(Name);

}

else

{

MessageBox.Show("Get camera info false!");

return false;

}

m_ServerLocation = new SapLocation(Name, 0);

//创建采集设备,new SapAcqDevice()的括号中第二个参数既可以写配置文件路径,也可以写false,false是用相机当前的设置

// 获取相机信息,加载相机配置文件(用相机专家调整好参数后导出ccf文件),加载参数

if (configFilePath.Length > 0)

m_AcqDevice = new SapAcqDevice(m_ServerLocation, configFilePath);

else

m_AcqDevice = new SapAcqDevice(m_ServerLocation, false);

Console.WriteLine(m_AcqDevice.Create());

if (m_AcqDevice.Create() == false)

{

DestroyObjects();

DisposeObjects();

return false;

}

// 创建缓存对象

if (SapBuffer.IsBufferTypeSupported(m_ServerLocation, SapBuffer.MemoryType.ScatterGather))

{

m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGather);

}

else

{

m_Buffers = new SapBufferWithTrash(2, m_AcqDevice, SapBuffer.MemoryType.ScatterGatherPhysical);

}

if (m_Buffers.Create() == false)

{

DestroyObjects();

DisposeObjects();

return false;

}

//设置行频,注意:行频在相机工作时不能设置(曝光、增益可以),最好在初始化阶段设置

m_AcqDevice.SetFeatureValue("AcquisitionLineRate", 20000.0);

//创建传输对象

m_Xfer = new SapAcqDeviceToBuf(m_AcqDevice, m_Buffers);

// 这一句是核心,这是回调函数,就靠它采图了

m_Xfer.XferNotify += new SapXferNotifyHandler(m_Xfer_XferNotify);

m_Xfer.XferNotifyContext = this;

m_Xfer.Pairs[0].EventType = SapXferPair.XferEventType.EndOfFrame;

m_Xfer.Pairs[0].Cycle = SapXferPair.CycleMode.NextWithTrash;

if (m_Xfer.Pairs[0].Cycle != SapXferPair.CycleMode.NextWithTrash)

{

DestroyObjects();

DisposeObjects();

return false;

}

if (m_Xfer.Create() == false)

{

DestroyObjects();

DisposeObjects();

return false;

}

return true;

}

private void DestroyObjects()

{

if (m_Xfer != null && m_Xfer.Initialized)

m_Xfer.Destroy();

if (m_Buffers != null && m_Buffers.Initialized)

m_Buffers.Destroy();

if (m_AcqDevice != null && m_AcqDevice.Initialized)

m_AcqDevice.Destroy();

}

private void DisposeObjects()

{

if (m_Xfer != null)

{

m_Xfer.Dispose();

m_Xfer = null;

}

if (m_Buffers != null)

{

m_Buffers.Dispose();

m_Buffers = null;

}

if (m_AcqDevice != null)

{

m_AcqDevice.Dispose();

m_AcqDevice = null;

}

}

void m_Xfer_XferNotify(object sender, SapXferNotifyEventArgs argsNotify)

{

// 首先判断此帧是否为废弃帧,若是则立即返回,等待下一帧(但这句话有时候m_Xfer.Snap(n)时会导致丢帧,可以注释掉试试)

if (argsNotify.Trash) return;

// 获取m_Buffers的地址(指针),只要知道了图片内存的地址,其实就能有各种办法搞出图片了(例如转成Bitmap)

IntPtr addr;

m_Buffers.GetAddress(out addr);

// 观察buffer中的图片的一些属性值,语句后注释里面的值是可能的值

int count = m_Buffers.Count; //2

SapFormat format = m_Buffers.Format; //Uint8

double rate = m_Buffers.FrameRate; //30.0,连续采集时,这个值会动态变化

int height = m_Buffers.Height; //2800

int weight = m_Buffers.Width; //4096

int pixd = m_Buffers.PixelDepth; //8

//显示实时帧率

UpdateFrameRate();

lbl_FrameRate.BeginInvoke(new Action(() => { lbl_FrameRate.Text = m_Buffers.FrameRate.ToString(); }));

picCountNum++;

// 保存到本地。这个save方法就是从SDK中提取出来的,给上参数,就可以实现图片的保存,不用借助其他任何的技术方法

m_Buffers.Save(imgPath + picCountNum + ".bmp", "-format bmp" );

// 从内存读取图片,并转换成bitmap格式,创建调色板,打印到PictureBox

PixelFormat pf = PixelFormat.Format8bppIndexed;

Bitmap bmp = new Bitmap(weight, height, m_Buffers.Pitch, pf, addr);

ColorPalette m_grayPalette;

using (Bitmap tempbmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))

{

m_grayPalette = tempbmp.Palette;

}

for (int i = 0; i <= 255; i++)

{

m_grayPalette.Entries[i] = Color.FromArgb(i, i, i);

}

bmp.Palette = m_grayPalette;

Image img = Image.FromHbitmap(bmp.GetHbitmap());

picBox.Image = img;

}

     

private void UpdateFrameRate()

{

if (m_Xfer.UpdateFrameRateStatistics())

{

float framerate = 0.0f;

SapXferFrameRateInfo stats = m_Xfer.FrameRateStatistics;

if (stats.IsBufferFrameRateAvailable)

framerate = stats.BufferFrameRate;

else if (stats.IsLiveFrameRateAvailable && !stats.IsLiveFrameRateStalled)

framerate = stats.LiveFrameRate;

m_Buffers.FrameRate = framerate;

}

}

// 获得相机参数的最大值(行频和曝光时间是近似倒数的关系,获得参数最大值可以防止设置参数超限)

private double GetMaxValue(string featureName)

{

SapFeature feature = new SapFeature(m_ServerLocation);

if (!feature.Create()) return -1;

if (!m_AcqDevice.GetFeatureInfo(featureName, feature)) return -1;

double maxValue = 0;

if (!feature.GetValueMax(out maxValue)) return -1;

return maxValue;

}

// 这个一般用的少,最小值一般是很小的数(比如Gain最小0.125, width最小128),我们一般不会设置这样的数

private double GetMinValue(string featureName)

{

SapFeature feature = new SapFeature(m_ServerLocation);

if (!feature.Create()) return -1;

if (!m_AcqDevice.GetFeatureInfo(featureName, feature)) return -1;

int minValue = 0;

if (!feature.GetValueMin(out minValue)) return -1;

return minValue;

}

}

}

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: