首先吐槽一句,官方的demos写的真的不好,坑爹啊。对于小白来说,开发官方demos为我所用太难了。为什么呢?因为它Dalsa的DALSA.SaperaLT.SapClassBasic.dll中,不仅有采图的代码库,还有用于显示的UI库(它不是用Winform的PictureBox显示图片,而是用它自家的UI显示图片),demos把采图程序和UI库杂糅在一起,而且隐藏了少部分细节。

后来我在网上狂搜资料,搜到了两个大佬的两篇好文章:

dalsa 8k线阵网口相机c#开发

https://blog.csdn.net/baidu_30028771/article/details/64628784

DALSA相机SDK不完全教程

http://www.cnblogs.com/lgyup/p/4313332.html

文章一的代码是一个完整的例子,是可以直接采到图的。文章二的代码缺少关键的GetCameraInfo()方法,是不能直接运行的,但是这篇文章的讲解更全面、深入,可以说两篇都是必备的啦。

我为什么要写这两篇文章呢?因为我想集合这两家之长,再加入一点自己的经验、代码,并且提供完整的源代码方便大家开发。很忏愧 ,只做了一点微小的贡献。

我的开发硬件、软件信息:

操作系统:windows 10、windows 7   64bit都有

线扫相机:Dalsa  Linea Mono 4k  26 kHz GigE (LA-GM-04K08A)

IDE :Visual studio 2013

第一篇文章我直接运行代码报错了,是到了跟Dalsa相关的dll的语句时报错的。Win 10系统很扯淡,报错的提示一点都看不懂,我换Win 7的系统后,也报错,但是明确把错误原因找出来了。其实是Dalsa的dll中有低版本.Net Framework的代码,导致不兼容。解决的办法,网上一大推,核心就一句:在app.config的合适位置,加这句话useLegacyV2RuntimeActivationPolicy=”true”。

如果没有app.config文件,你就需要创建这个文件。

我的app.config文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

现在你需要把我上文提到的两篇博客仔细看一下了。

……

看完了吗?看完了的话,接着往下看我的文章。

首先学习一下相机配置文件(.ccf)如何生成:

① 打开相机软件Sapera CamExpert,确保相机已经正常工作,然后自己改变到合适的参数;

② 点击软件左上角的File——Save As...,选择文件夹路径,修改文件名。

我的解决方案资源结构如下:

因为我是用Halcon显示图片,因此我添加了两个dll引用。除了app.config之外,我所有自己编写的代码全部在Form1.cs中。其实相当于我把全部源代码一字不漏全告诉你了。

我的Form1界面如下:

(点击Init初始化,会弹出该线阵相机的型号)

然后点击“snap”的话,它会连续采集15张图,并保存,如下:

Form1.cs的全部内容如下:

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DALSA.SaperaLT.SapClassBasic;
using HalconDotNet;

namespace WinDalsa
{
public partial class Form1 : Form
{
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 > )
{
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); //
m_AcqDevice.GetFeatureValue("Height", out height); //
m_AcqDevice.GetFeatureValue("SensorWidth", out sensorWidth); //
m_AcqDevice.GetFeatureValue("SensorHeight", out sensorHeight); // } #region 单步采集、连续采集、冻结采集
private void btn_snap_Click(object sender, EventArgs e)
{ //Snap()只采集一张,如果是Snap(15)则连续采集15张
m_Xfer.Snap();//m_Xfer.Snap(m_Buffers.Count)
} private void btn_grab_Click(object sender, EventArgs e)
{
m_Xfer.Grab();
} private void btn_freeze_Click(object sender, EventArgs e)
{
m_Xfer.Freeze(); //还有m_Xfer.Abort()的用法; } #endregion //得到所有连接的相机信息,并将它们加入到ArrayList里面去
public bool GetCameraInfo(out string sCameraName, out int nIndex)
{
sCameraName = "";
nIndex = ; int serverCount = SapManager.GetServerCount();
int GenieIndex = ;
System.Collections.ArrayList listServerNames = new System.Collections.ArrayList(); bool bFind = false;
string serverName = "";
for (int serverIndex = ; serverIndex < serverCount; serverIndex++)
{
if (SapManager.GetResourceCount(serverIndex, SapManager.ResourceType.AcqDevice) != )
{
serverName = SapManager.GetServerName(serverIndex);
listServerNames.Add(serverName);
GenieIndex++;
bFind = true;
}
} int count = ;
string deviceName = "";
foreach (string sName in listServerNames)
{
deviceName = SapManager.GetResourceName(sName, SapManager.ResourceType.AcqDevice, );
count++;
} sCameraName = serverName;
nIndex = GenieIndex; return bFind;
} private bool CreateNewObjects()
{ 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, ); // 创建采集设备,new SapAcqDevice()的括号中第二个参数既可以写配置文件路径,也可以写false,猜测false是用相机当前的设置
//m_AcqDevice = new SapAcqDevice(m_ServerLocation, false);
m_AcqDevice = new SapAcqDevice(m_ServerLocation, @"C:\Users\xh6300\Desktop\dalsa_win7_develop\gray\T_Linea_M4096-7um_Default_Default_2800.ccf"); if (m_AcqDevice.Create() == false)
{
DestroyObjects();
DisposeObjects();
return false;
}
// 创建缓存对象
if (SapBuffer.IsBufferTypeSupported(m_ServerLocation, SapBuffer.MemoryType.ScatterGather))
{
m_Buffers = new SapBufferWithTrash(, m_AcqDevice, SapBuffer.MemoryType.ScatterGather);
}
else
{
m_Buffers = new SapBufferWithTrash(, 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[].EventType = SapXferPair.XferEventType.EndOfFrame;
m_Xfer.Pairs[].Cycle = SapXferPair.CycleMode.NextWithTrash;
if (m_Xfer.Pairs[].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; }
} private static int picCountNum = ; //统计采集了多少张图,有利于理解m_Xfer.Snap(15)中15的意思 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; //
SapFormat format = m_Buffers.Format; //Uint8
double rate = m_Buffers.FrameRate; //30.0,连续采集时,这个值会动态变化
int height = m_Buffers.Height; //
int weight = m_Buffers.Width; //
int pixd = m_Buffers.PixelDepth; //8 //显示实时帧率
UpdateFrameRate();
lbl_FrameRate.BeginInvoke(new Action(() => { lbl_FrameRate.Text = m_Buffers.FrameRate.ToString();})); //利用halcon从内存中采集图片并保存
HObject ImageTemp = null;
HOperatorSet.GenImage1(out ImageTemp, "byte", , , addr);//取内存数据,生成图像,halcon实现 hWindowControl1.HalconWindow.SetPart(, , , );
HOperatorSet.DispObj(ImageTemp, hWindowControl1.HalconWindow);
picCountNum++;
HOperatorSet.WriteImage(ImageTemp, "bmp", , "C:\\Users\\xh6300\\Desktop\\tt\\" + picCountNum); } 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 -;
if (!m_AcqDevice.GetFeatureInfo(featureName, feature))
return -;
double maxValue = ;
if (!feature.GetValueMax(out maxValue))
return -;
return maxValue;
} //这个一般用得少,最小值一般是很小的数(比如Gain最小0.125,width最小128),我们一般不会设置这样的数
private double GetMinValue(string featureName)
{
SapFeature feature = new SapFeature(m_ServerLocation);
if (!feature.Create())
return -;
if (!m_AcqDevice.GetFeatureInfo(featureName, feature))
return -;
int minValue = ;
if (!feature.GetValueMin(out minValue))
return -;
return minValue;
}
}
}

当你完全理解了这篇文章(以及我提到的两篇),Dalsa网口线阵相机的开发基本就没啥问题了,当然这时候你返回去看官方demos会有新的收获,比如我上面的UpdateFrameRate()就是从官方demos中剥离出来的,该函数可以得到采图时的实际帧率。

有什么问题可以留言询问。

DALSA网口线扫相机SDK开发详解例程(C#版)的更多相关文章

  1. Dalsa线扫相机SDK开发-小试牛刀(1)

    拿到了dalsa相机,可以用Sapera软件配置相机,进行图像采集.但是自己开发的话就得撸起袖子写代码了,查了两篇不错的博文,作为指导. Sapera帮助文档 - <好好先生>专栏 - 博 ...

  2. 【转发】NPAPI开发详解,Windows版

    NPAPI开发详解,Windows版 9 jiaofeng601, +479 9人支持,来自Meteor.猪爪.hanyuxinting更多 .是非黑白 .Yuan Xulei.hyolin.Andy ...

  3. Dalsa线扫相机SDK下载和安装

    1.首先去官方网站下载SDK Support Downloads - Teledyne DALSA http://www.teledynedalsa.com/imaging/support/downl ...

  4. 《Linux设备驱动开发详解(第3版)》(即《Linux设备驱动开发详解:基于最新的Linux 4.0内核》)--宋宝华

    http://blog.csdn.net/21cnbao/article/details/45322629

  5. VisionPro连接Dalsa线扫相机

    1 环境配置 硬件:编码器(提供编码信号的PLC) 线扫相机 镜头 相机线缆 图像采集卡(Dalsa_Xcelera-CL_PX4 Dual) 软件:VisionPro 8.2 VisionPro软件 ...

  6. 基于H5的微信支付开发详解

    这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可 ...

  7. ****基于H5的微信支付开发详解[转]

    这次总结一下用户在微信内打开网页时,可以调用微信支付完成下单功能的模块开发,也就是在微信内的H5页面通过jsApi接口实现支付功能.当然了,微信官网上的微信支付开发文档也讲解的很详细,并且有实现代码可 ...

  8. iOS原生地图开发详解

    在上一篇博客中:http://my.oschina.net/u/2340880/blog/414760.对iOS中的定位服务进行了详细的介绍与参数说明,在开发中,地位服务往往与地图框架结合使用,这篇博 ...

  9. iOS应用开发详解

    <iOS应用开发详解> 基本信息 作者: 郭宏志    出版社:电子工业出版社 ISBN:9787121207075 上架时间:2013-6-28 出版日期:2013 年7月 开本:16开 ...

随机推荐

  1. tomcat日志文件目录修改

    tomcat每次启动时,自动在logs目录下生产以下日志文件,造成日志文件众多: 将logs的日志文件放置到新建的文件夹位置,避免主硬盘空间的占用.主要更改catalina.out的文件位置和每日的日 ...

  2. CF1061F:Lost Root(交互&概率)

    The graph is called tree if it is connected and has no cycles. Suppose the tree is rooted at some ve ...

  3. sql中的一些通用函数

    1. SQL中使用case,when,then SELECT CASE TYPE THEN '正常' THEN '密码错误' ELSE '不正常' END '状态' FROM tbl_user 或者 ...

  4. 0302 IT行业就业与软件工程

    阅读以下文章 http://www.thea.cn/news/terminal/9/9389.html http://www.shzhidao.cn/system/2015/09/22/0102610 ...

  5. ringojs 使用rp 包管理web 应用依赖

    rp 是一个类似npm 的包管理工具,我们可以使用package.json 定义依赖 然后执行rp install 即可,类似ringo-admin 的功能 其中packages 类似node 的no ...

  6. deno学习二 基本代码

    deno 介绍是安全的ts 运行时 简单的代码 使用js(app.js) console.log("demoapp") 输出 dalongdemo 使用ts(app.ts) con ...

  7. 在IIS服务上发布网站

    一.打开控制面板中的“管理工具” 二.打开IIS管理器 三.右键网站,选择“新建网站”

  8. 从 Excel 表格粘贴到 浏览器表格中

    从 Excel 表格粘贴到 浏览器表格中 由于 Excel 用途广泛,所以在导入时用到很多. 但是更多人的喜欢使用复制粘贴. 在网上找了一圈有找到一个开源项目,可以将 Excel 粘贴到 HTML 中 ...

  9. python 内置方法的时间复杂度

    好文,非常值得参考 http://www.orangecube.net/python-time-complexity

  10. 认识Linux操作系统

    Linux系统是一个类似UNIX的操作系统 认识Linux的来世与今生 1.Linux系统的历史 Linux系统是一个类似UNIX的操作系统,Linux系统是UNIX在微机上的完整实现,它的标志是一个 ...