Dalsa线阵CCD相机使用开发手册

  要使用Dalsa工业相机进行二次开发,看用户开发手册顺便做下笔记:(欢迎加QQ讨论:77248031, 或QQ群:585068192)

  由于“本公主”用的.NET开发,软件支持只翻译了手册中.NET部分,如有使用C++的小伙伴,可自行查阅手册。

  一,Application Architecture

   不管使用哪个API(Sapera LT++, Sapera LT.NET 或者是标准C),Sapera LT模块都可以部署在不同的Sapera LT服务器上。

  服务器可以运行在本地或者是Teledyne DALSA设备上。Sapera LT调用通过Sapera LT消息传递层以一种完全独立于底层硬件的方式路由到不同的服务器。 

二,Library Architecture

  典型的机器视觉应用程序需要配置采集资源、图像捕获和传输到内存缓冲区。图像缓冲区可以处理或展示,分析(图像),通过结果确定后续流程。

  可以监视事件并触发合适的响应。Sapera LT库架构是围绕这些基本机器视觉功能块组织起来的。

 三,Sapera LT .NET Basic Classes by Subject

  下图介绍了一些主要的Sapera LT.NET类的描述,并介绍了它们与其它类的关系:

3.1 Sapera LT ++ and Sapera LT .NET Class Descriptions

C++/.NET class Description
SapAcqDevice

控制Teledyne DALSA相机上的采集设备(例如,Genie M640)。 它被用作源传输节点,允许数据从一个采集资源传输到另一个传输节点,比如SapBuffer。 它被SapTransfer类使用。  

SapAcqToBuf,

SapAcqDeviceToBuf,

SapBufToBuf,

SapMultiAcqToBuf

这些具体化的传输类是从SapTransfer派生出来的,可以轻松地创建最常用的传输配置。 例如,设置一个从SapAcquisition对象(帧抓取器)到SapBuffer对象的传输配置通常需要很多行代码来调用SapTransfer类中的各种函数。 而使用具体化类SapAcqToBuf可以将其减少到仅一行代码。

SapAcquisition

通过acquisition section控制Teledyne DALSA board的采集设备(例如,X64 Xcelera-CL PX4)。它被用作源传输节点,允许数据从一个采集资源传输到另一个传输节点,比如SapBuffer。它被SapTransfer类使用。 

SapBuffer

对缓冲区的资源数组进行操作。一个SapTransfer实例可以将一个SapBuffer实例看成传输目的地,使得数据从原节点(例如SapAcquisition or SapAcqDevice)完成传输。一个SapBuffer实例可以通过SapView class来显示,也可以使用SapProcessing class来处理。

SapBufferRoi

SapBufferRoi 类的目的是在已存在的SapBuffer实例中创建一个感兴趣的矩形区域。ROI对于实例中的所有缓冲区资源具有相同的原点和维度

SapBufferWithTrash

SapBufferWithTrash类创建了一个额外的叫做缓冲垃圾的资源,在实时应用程序的数据传输过程中使用。trash buffer是一个应急缓冲,当数据传输比数据处理的速度快时使用。当处理速度不够快的时候,来不及处理新进来的数据,图像会被暂时传输到trash buffer直到重新稳定。

SapColorConversion

SapColorConversion类的目的是对从相机获取的图像以及其它格式的彩色图像进行Bayer转换。当使用带有采集卡的Teledyne DALSA板时,该类支持在采集硬件中的颜色转换(如果硬件支持)。否则该类也支持在主机上进行基于软件的转换。

SapData and SapDataXxx

SapData及其派生类充当Sapera LT数据类型的包装器,其中每个类封装特定类型的一个数据元素。 它们被用作各种Sapera LT ++和Sapera LT . net类中的属性值、方法参数或返回值。  

SapDisplay

SapDisplay类及其功能可以将资源显示在系统显示设备(计算机视频卡)或带有显卡的Teledyne DALSA板上。系统中每个显示适配器(VGA板)上至少有一个这样的资源。注意,SapView对象自动管理默认显示资源的内部SapDisplay 对象。但是,如果你需要默认资源以外的显示资源的话,你需要显式的管理对象。 

SapFeature

SapFeature类及功能可以从SapAcqDevice类检索特征信息。SapAcqDevice类支持的每个特性都提供了一组属性,如名称、类型、访问模式等,这些属性可以通过特性模块获得。  

SapFlatField

SapFlatField类的目的是对从相机获取的图像或从磁盘加载的图像进行平场校正。 它可以从获取硬件(如果支持的话)或从软件实现中支持该功能。  

SapGio SapGio类的目的是控制一个通用输入和输出块——一组可以同时读写的I/ o。  
SapLocation SapLocation类标识一个Sapera服务器/资源对  
SapLut SapLut类实现了查找表管理。 它通常与SapAcquisition和SapView类一起使用,分别操作采集和显示查找表。  
SapManager SapManager类包括描述系统中出现的Sapera资源的方法。 它还包括错误管理功能。  
SapMetadata

SapMetadata类提供了管理GigE- vision相机元数据的函数(用于Genie-TS和Linea GigE)。 启用时,支持的元数据(例如,时间戳或设备ID)包含在SapBuffer对象中。  

SapPerformance

SapPerformance类实现基本的基准测试功能。 它被SapProcessing类用来计算处理一个缓冲区所需的时间。 您也可以根据自己的基准测试需要使用它。  

SapProcessing SapProcessing类允许您通过派生类实现自己的处理。  
SapTransfer

SapTransfer类实现了管理通用传输过程的功能——将数据从一个源节点传输到一个目标节点。 以下类被认为是传输节点:SapAcquisition、SapAcqDevice和SapBuffer。  

SapView

SapView类包含通过SapDisplay对象在窗口中显示SapBuffer对象的资源的功能。 “自动清空”机制允许SapView和SapTransfer对象之间同步,以便在不丢失任何数据的情况下实时显示缓冲区。  

SapXferFrameRateInfo

SapXferFrameRateInfo类为相关的SapTransfer对象提供帧速率统计信息。它在构造SapTransfer对象时自动创建。  

SapXferNode

SapXferNode类是基类,用于表示由SapTransfer类管理的传输任务中涉及的源或目标传输节点。节点的实际类可以是SapAcqDevice、SapAcquisition或SapBuffer。  

SapXferPair SapXferPair类描述了SapTransfer类的一对源节点和目标节点。  
SapXferParams SapXferParams类存储由SapTransfer类管理的传输任务所需的参数。  

 

.NET Only Class Description
SapAcqDeviceNotifyEventArgs SapAcqDeviceNotifyEventArgs类存储了SapAcqDevice类的AcqDeviceNotify事件的参数  
SapAcqNotifyEventArgs SapAcqNotifyEventArgs类存储了SapAcquisition类的AcqNotify事件的参数  
SapDisplayDoneEventArgs SapDisplayDoneEventArgs类存储了SapView类的DisplayDone事件的参数。  
SapErrorEventArgs SapErrorEventArgs类存储SapManager类的错误事件的参数  
SapException SapException类是SapLibraryException和SapNativePointerException类通用的基类。  
SapGioNotifyEventArgs SapGioNotifyEventArgs类存储了SapGio类的GioNotify事件的参数。  
SapLibraryException 当Sapera LT库中报告异常的错误条件时,会抛出SapLibraryException类。  
SapManVersionInfo SapManVersionInfo类包含与当前安装的Sapera LT副本对应的版本信息。  
SapNativePointerException 当发生内部指针错误条件时,会抛出SapNativePointerException类。  
SapProcessingDoneEventArgs SapProcessingDoneEventArgs类存储了SapProcessing类的ProcessingDone事件的参数。  
SapResetEventArgs SapResetEventArgs类存储SapManager类的Reset事件的参数。  
SapServerFileNotifyEventArgs SapServerFileNotifyEventArgs包含SapManager类的ServerFileNotify事件的应用程序处理程序方法的参数。  
SapServerNotifyEventArgs SapServerNotifyEventArgs类存储SapManager类的ServerNotify事件的参数。  
SapSignalNotifyEventArgs SapSignalNotifyEventArgs类存储了SapAcquisition类的SignalNotify事件的参数。  
SapXferCounterStampInfo SapXferCounterStampInfo类存储关于特定传输对的counter-stamp功能的信息。  
SapXferNotifyEventArgs SapXferNotifyEventArgs类存储了SapTransfer类的XferNotify事件的参数。  

四,Trigger-to-Image-Reliability Framework

   机器视觉系统用于检测,在不同类型的制造和过程工业识别和指导应用。 

  该视觉系统包括面和线扫描,彩色和单色相机和帧捕捉器,以提供能够自动操作的系统,对物体执行100%的检查任务。 

  视觉系统必须在各种操作条件下产生可靠的结果,以帮助提高产品和工艺的质量。 

  Teledyne DALSA的相机和帧捕捉器结合了Trigger-to-Image-Reliability(T2IR) Framework,以确保从物体被放置在相机前到决定接受或拒绝被检查物体的数据可靠性。 

  T2IR框架基于硬件和软件设计原则,以确保可靠性,并作为硬件特性和功能、独立的基于GUI的工具和编程API交付。 T2IR框架允许应用程序跟踪、跟踪、调试、恢复和防止任何数据丢失。

4.1 Teledyne DALSA采集设备功能架构

  让我们简要地看一下Teledyne DALSA硬件设备的采集设备架构的主要构建模块:

  • Acquisition Control Uint (ACQ):这个概念功能块负责控制图像采集功能和特征。它负责确保在正确的时间采集到正确的图像。ACQ负责管理软件控制下的摄像机控制信号。 此外,ACQ还提供了图像采集序列的运行状态。
  • Data Transfer Engine(DTE):DTE负责将数据从板载内存移进移出到主机内存,该功能块采用智能DMA体系结构,并根据硬件的性能指标进行扩展。 DTE还负责根据T2IR框架生成管理图像流所需的所有通知。
  • Image Processing Unit(IPU):IPU实现实时嵌入式图像处理。 IPU的能力根据采购硬件的价格性能标准而有所不同。 从简单的帧捕捉器和相机中的颜色空间转换到图像分析,再到视觉处理器上的外部设备控制,嵌入式处理的复杂性各不相同。

  考虑到Teledyne DALSA图像采集设备的功能架构,让我们进一步了解T2IR框架,了解它是什么,它的主要构建模块,以及它如何帮助降低成本。

4.2 什么是Trigger-to-Image Reliability (T2IR)?

  机器视觉应用程序的图像采集过程始于向相机发送一个信号,称为外部触发器,以开始生成图像。 因此,无论视觉系统的性质如何,触发信号都代表了图像采集序列的关键起点,使图像处理和分析能够为进一步的检查过程提供决策。

  

  视觉系统的可靠性体现在其处理可预测和不可预测触发信号的能力上。 为了实现这种可靠性,视觉系统中的图像采集和控制两个部分必须协调工作。 

  对系统事件的控制响应与生成具有相同质量的产品所需的信息质量直接相关。 这有助于通过增加系统的正常运行时间和产量来降低成本。

 

  T2IR是硬件和软件功能的结合,可以共同提高视觉系统的可靠性。 T2IR功能提供完整的系统级监控、控制和诊断能力。 它可以让你进入你的视觉系统来监控和调试图像流。 

  您可以跟踪数据流,从图像采集到传输到主机内存。 您甚至可以将图像临时存储在板载内存中,以克服意想不到的传输瓶颈。 这意味着没有丢失的数据,没有错误的数据,而且还有明确的源头来识别和跟踪所有错误。

  Sapera T2IR以一种不干扰应用程序的方式完成这些任务。

4.3 跟踪图像(Tracking and Tracing Images)

  虽然我们已经从检测目标的角度进行了讨论,当目标处于正确位置时触发闪光灯和摄像头采集,并从传感器读取正确的图像数据,但这只是设计可靠的机器视觉系统的开始。 

  另一个主要问题是协调图像数据的收集,并将这些图像与通过材料处理系统移动的实物相关联。  

 

  T2IR使用一个重要的设计概念来帮助工程师创建可靠和可重复的系统:图像标记或时间戳。 为了说明这一点,让我们使用一个材料处理单元的示例,其处理速度可达每分钟3,600个零件(ppm)。 

  为了使工厂的生产线以最高速度工作,每个图像都必须加标签,以便下游决定对正确的物体进行保留、丢弃或重新检查。

 

  更高级的应用程序可能需要来自多个视图的检查。 继续我们之前的例子,让我们假设对象必须在每一面检查,每一面都有不同的照明,相同的帧率。 

  现在,限制从每分钟检查3600个部件发展到每分钟处理14400个图像。 在这种情况下,成像系统必须将四个不同的采集点关联起来,然后才能做出接受、拒绝或重新检查目标的最终决定。  

   图像标签(时间戳)由机载硬件时钟、PC时钟或使用外部信号(如触发器、编码器滴答声或图像采集和/或图像传输到主机时的另一个脉冲输入)生成。 例如,Xtium-CL MX4提供了以下硬件时间戳:

  

  设备和主机(在开始接收帧时发出)的采集帧开始时间戳与图像一起保存在Sapera缓冲区中。 主机应用程序可以使用Sapera函数检索这些时间戳进行分析.

  由于在图像捕获和分析之间存在时间滞后,可以使用图像时间戳来确保系统对正确的对象进行操作。 时间戳还可以用来精确地测量采集或处理速率。 它还可以通过比较连续帧之间的时间间隔来确定是否发生了数据丢失。

五,Overcoming Too Much Data

5.1 跟踪Trashed Frames

  让我们以前面的例子为基础:系统每分钟处理3600个零件,包括同时从4个方面获取图像,从而导致机器视觉系统每分钟获取、处理和分析14400幅图像。 适当的系统设计要求在系统中内置一定数量的过剩容量,以处理高峰负载。 触发器-图像可靠性框架通过圆形缓冲区的概念提供峰值负载能力。 它还将此与用户通知相结合,以便持续跟踪。 在处理峰值负载时,重要的是要监视图像队列,以确保系统的各个部分保持同步,如果发生任何变化,则识别出来并及时通知用户应用程序。

  T2IR框架的可扩展性使Teledyne DALSA能够在其硬件产品中添加复杂的参数切换功能,这些功能非常适合用于循环缓冲区。 例如,Teledyne DALSA Genie相机允许用户在一帧一帧的基础上改变触发延迟、频闪输出、曝光延迟和持续时间、增益、LUTs和FFC(平场系数)。 类似地,Xtium-CL MX4帧捕获器允许用户在一帧一帧的基础上切换平场和lut。 当激活时,这些高级切换功能完全在采集设备中运行,而无需使用主机CPU资源。 此外,切换参数时生成的图像可以保存为图像序列。

  T2IR为处理数据过多的情况提供了广泛的选择。它为用户提供了安全丢弃图像的必要信息,同时保留了图像处理后结果的准确性。当每个图像都计数时,丢弃图像不可避免的会导致吞吐量下降。因此,即使在丢弃图像时,也必须注意将对吞吐量的影响降到最低。如果确定系统随后无法处理图像,T2IR框架运行应用程序在收集流程的早起丢弃图像。T2IR框架使用”垃圾“缓冲区的概念来有效的丢弃传入的图像。当系统无法处理传入的数据时,获取的图像被传输到”垃圾缓冲区“。

  发生这种情况时,将通过数据溢出事件通知用户应用程序。 例如,当将图像传输到主机缓冲区时,Xtium系列帧捕获器会监测下游瓶颈,并立即在获取源处丢弃图像,而不是一直在主机内存中传输然后丢弃它。 这允许采集部分立即返回到就绪状态,以捕获下一个图像.

 5.2 确保数据质量

  一般来说,机器视觉摄像机负责以一种可预测的方式优雅地处理过度触发的情况。 当相机的触发器的速率超过其最大帧率或线率能力时,发生相机的过触发情况。 如果相机不能正常响应并停止发送图像,T2IR功能提供了从这种情况中恢复的方法,并向用户应用程序生成通知。 这是所有Teledyne DALSA帧抓取器的标准功能。 捕获和处理丢线或帧是决定采集系统可靠性的重要因素,直接影响结果的准确性。 例如,对于线扫描相机,缺失的线会改变图像中物体的宽高比,导致处理算法产生不正确的结果。 同样,对于区域扫描相机来说,这可能意味着丢失了物体。

 六,Processing Buffers

  为了在获取图像的同时处理其它图像,需要多个图像缓冲区。当这些缓冲区通过一个传输资源与采集设备相连,图像以环形方式存储在这些缓冲区内,先存到第一个缓冲区,然后第二个,等等,直到到达最后一个,接下来第一个缓冲区会被覆盖继续循环。当第一个缓冲区被处理时,图像被保存到下一个缓冲区。

  例如,4个图像缓冲区:

  然而,图像缓冲区只有在平均图片处理时长小于平均采集时长的情况下可以处理所有的图片。当处理时长追不上采集帧率时,就需要用到另外一种缓存来解决来不及处理的图片,此缓存不是环形列表的一部分。在Sapera LT,这个缓存称为Trash buffer。

  

  分配缓存的API支持:

  •  用一个SapBuffer或SapBufferWithTrash类的实例,都可以给定一个缓存大小

  将缓存链接在一起的API支持:

  •  用一个SapTransfer类的实例,或它的一个派生类,例如:SapAcqToBuf或SapAcqDeviceToBuf

6.1 缓存状态

  缓存可以有两种状态:

  • Empty: 意味着可以像缓冲区存储图像
  • Full:意味着有未处理的数据仍然存储在缓存区中

  缓存状态在empty和full之间变换如下:

  • 所有buffer初始状态都是empty
  • 当图像被采集到缓冲区时,传输硬件将它们的状态设置为full
  • 当传输硬件需要一个新的图像缓冲区时,它可以考虑或忽略当前的缓冲区状态,这取决于传输循环模式
  • 当缓冲区可以再次用于收集图像时,由应用程序代码负责将其状态设置为空

注意:这些与Trash buffers无关。

  API对管理buffer状态的支持:

  .NET: 虽然你可以使用SapBuffer和SapBufferWithTrash类的State属性,但是依赖SapTransfer、SapProcessing和SapView类中的自动空机制通常是更好的。

6.2 Auto-Empty 机制

引用一种应用程序可配置机制,根据该机制,缓冲区状态自动设置为空。

  有4种可能的场景:

  • 在transfer回调函数(如果有的话)执行完返回之后,Buffer状态立刻被transfer(SapTransfer)置为empty。这是默认执行的。
  • 当缓冲区内的图像被处理后,Buffer状态立刻被processing(SapProcessing)置为empty状态,这一过程是在processing回调函数(如果有的话)被调之前完成的。
  • 当缓冲区内的图像被展示后,在view回调函数(如果有的话)被调之前,缓冲区状态会被view(SapView)置为empty
  • Buffer状态也可以在程序中被直接置为empty

管理auto-empty机制的API支持:

  .NET: 在SapTransfer, SapProcessing和SapView类中使用AutoEmpty属性。

6.3 Transfer Cycling Modes

 当决定下一张图片存储在哪个缓存区时,使用transfer所使用的标准。

  OFF模式时:

  • 永远传输到当前缓冲区
  • 忽略buffer的状态
  • 忽略是否有trash buffer

  Asynchronous模式时:

  • 永远传输到下一个缓冲区
  • 忽略buffer的状态
  • 忽略是否有trash buffer

  Synchronous模式时:

  • (Case 1)如果下一个缓冲区是empty状态,则传输到下一个缓冲区
  • (Case 2)如果下一个缓冲区是full状态,则传输到当前缓冲区
  • 忽略是否有trash buffer

  Next Empty模式时:

  • (Case 1)如果下一个缓冲区是empty状态,则传输到下一个缓冲区
  • (Case 2)如果下一个缓冲区是full状态,则传输到队列的再下一个缓冲区
  • (Case 3)如果所有缓冲区都是full状态,则传输到当前缓冲区
  • 忽略trash buffer的存在

  Synchromous With Trash 模式时:

  • (Case 1)如果下一个缓冲区是empty状态,则传输到下一个缓冲区
  • (Case 2)如果下一个缓冲区是full状态,则传输到trash buffer
  • (Case 3)只要下一个缓冲区是full状态,则持续传输到trash buffer
  • 缓冲区状态与trash buffer无关

  Synchronous Next Empty With Trash模式时:

  • (Case 1)如果下一个缓冲区是empty,则传输到下一个缓冲区
  • (Case 2)如果下一个缓冲区是full,传输到队列中的下一个empty缓冲区
  • (Case 3)如果所有缓冲区都是full,则传输到trash buffer
  • (Case 4)只要所有缓冲区都是full,则持续传输到trash buffer
  • buffer状态与trash buffer无关

  管理transfer cycling 模式的API支持:

  .NET: 使用SapXferPair类种的Cycle属性

6.4 处理和显示图像的执行流程

   例一:程序只需要读取采集图像的时间戳

     .NET API:

    • 调用SapTransfer类的XferNotify事件的handler function
    • 函数读取SapBuffer类的CounterStamp属性来检索时间戳,并返回
    • 缓冲区状态由SapTransfer类自动设置为空

   例二:程序只需要处理采集的图像

     .NET API(初始化):

    • 创建一个从SapProcessing派生的新类,该类覆盖的Run函数将处理实际的处理过程
    • 将SapTransfer类的AutoEmpty属性设置为False,避免buffers在此类中被设置为empty
    • 将SapProcessing类的AutoEmpty属性设为True,在此类中缓冲区可被置为empty

     .NET API(在每个图像被采集后):

    • 调用SapTransfer类中XferNotify事件的application handler function
    • 函数调用SapProcessing类的Execute函数,并返回
    • 最终调用应用程序中被overriden的Run函数
    • 这个函数执行图像的实际处理,并返回
    • 缓冲区状态被SapProcessing类自动设置为empty
    • 调用SapProcessing类的ProcessingDone事件的application handler function(如果有的话)

  例三:程序需要在显示(处理之后的)图像之前处理图像

     .NET API(初始化):

    • 创建一个从SapProcessing类派生出的新类,重载Run函数以进行实际的图像处理
    • 将SapTransfer类的AutoEmpty属性置为False,以避免在SapTransfer类中被置为empty
    • 将SapProcessing类的AutoEmpty属性置为False,以避免在SapProcessing类中被置为empty
    • 将SapView类的AutoEmpty属性置为True,在SapView类中将buffer状态置为empty

     .NET API (每张图像被采集后):

    • 调用SapTransfer类中XferNotify的application handler function
    • 这个function调用SapProcessing类的Execution function,并return
    • 最终在程序中调用重载的Run function
    • Run function执行实际的图像处理,并返回
    • 调用SapProcessing类中ProcessingDone事件的application handler function
    • 这个函数调用SapView类中的Show函数来显示处理后的图像,并返回
    • buffer状态被SapView类自动设置为empty状态
    • 调用SapView类中DisplayDone事件的application handler function(如果有的话)

 七,平场校正

  许多Teledyne DALSA帧捕捉器和摄像机支持硬件平场校正。以下部分概述了如何使用Sapera LT SapFlatField类进行平场校正。

  平场校正每个像素使用2个系数(偏移量和增益)来补偿固定模式噪声(FPN)和光响应不均匀性(PRNU)。

  • 暗场校正(FPN)是在没有入射光(也称为暗电流)的情况下像素响应的变化。 它是由传感器中存在的背景电压产生的噪声信号。 平场偏移(offset)系数被用来校正这种噪声。 为了使用SapFlatField::ComputeOffset进行FPN校正,需要对一些暗图像进行平均(即,使用镜头盖阻止所有光线进入传感器)。 平均图像中允许的零像素百分比可以使用SapFlatField::SetBlackPixelPercentage设置(太多的零像素表示相机的黑色级别太高,信息被剪切; 调整相机设置相应)。
  • 明场校正(PRNU)是是像素对等量光的响应变化。平常增益系数(flat field gain coefficients)用于矫正这种响应的不均匀性,使得当暴露在享同得入射光时输出相同的像素响应值。为了使用SapFlatField::ComputeGain进行PRNU校正,需要对一些白色图像进行平均,这样相机就接近但不饱和。计算每个像素的增益系数,使其达到低于饱和的指定目标值。

  对于FPN和PRNU校正来说,使用越多数量的图像来平均越能减少随机噪声带来的影响

   ComputeOffset函数必须在ComputeGain函数之前调用。要对图像应用软件平场校正,请使用SapFlatField::Execute函数。 对于硬件平场校正,将平场校正文件加载到设备并在硬件上激活,有关更多信息,请参阅设备文档(device documentation)。

  平场校正后应用的系统偏移量和增益通常用于最大化典型图像场景的图像动态范围。

7.1 平场文件格式

  平场校正生成一个8或16-bit的TIF文件,包含偏移(offset)和增益(gain)因子。缓存与采集图像等宽但高度2倍于采集图像的高度(第一半包含偏移(offset)因子,第二半是增益(gain)因子)。

  8位或16位的格式由传递给SapFlatField::ComputeOffset / ComputeGain函数的缓冲区的格式决定。 16位文件用于10、12、14或16位输出格式。一般来说,应该使用传感器的最高输出格式来校正平场系数。通过设置偏移因子(SapFlatField::SetOffsetFactor), 16位平坦场系数文件可以用于较低的输出格式。

  Sapera LT使用的TIFF文件结构

  • TIFF header —— 根据TIFF 6.0规范
  • 图像数据宽度与采集图像宽度相等
  • 图像数据高度是采集图像高度的2倍
  • 图像的上半部是偏移(offset)数据
  • 图像下半部是增益(gain)数据
  • 图像像素格式与采集图像的像素格式相同

7.2 平场校正公式

  对于每个像素,平场校正通过以下公式计算:

$correctedValue = (originalValue - offset) * (gain / gainDivisor + gain base)$

  Gain Divisor增益除数

   对于8位增益系数,增益除数通常等于128,这样在0和255之间的增益值就变成了0和2之间的值。 然后,当调用Create方法时,它被设置为采集设备增益除数(gain divisor)的值(SapFlatField::SetGainDivisor方法只在没有硬件支持的情况下使用)。 gainDivisor和gain base用于将浮点增益值(gain value)转换为可保存在. TIFF图像中的整数值。

  Gain Base

  对于增益基,如果采集设备(例如,Genie TS)支持,则在调用Create方法后从设备中检索它。 对于所有其他采集设备,以及基于软件的平场校正,该属性的初始值为0,如果需要,应用程序代码可以调用SetGainBase。

7.3 偏移因子(offset coefficients)

  FPN校正的偏移因子(offset coefficients)基于对每个像素点进行计算,使用在Xn, Yn点的平均像素减去DN值。DN值对应的是表示小于1%像素点分布的下限(利用~3σ标准差计算平均黑色图像的直方图平均值)。

  $Offset coefficient(Xn, Yn)= average pixel value(Xn, Yn) - DN value of ~3σ$

  这种方法保留了动态范围,减少了在零处被裁剪的像素数(这将导致图像数据的丢失,即使随后应用偏移量和增益来调整黑色阈值)。 

  SapFlatField::SetOffsetMinMax可以用来限制可能的增益值。 如果像素达到这个限制,当SapFlatField::EnableClippedGainOffsetDefects = TRUE(默认)时,它们将被标记为有问题的。

 

7.4 增益因子(Gain Coefficients)

  应用偏移系数后计算增益系数。 计算增益系数使所有像素达到指定的目标值(或白色图像中的最大像素值)。 SapFlatField::SetGainMinMax可以用来限制可能的增益值。 如果像素达到这个限制,当SapFlatField::EnableClippedGainOffsetDefects = TRUE(默认)时,它们将被标记为有问题的

7.5 像素替换 (Pixel Replacement)

  or the black and white images, pixel values higher/lower than

(average pixel value +/- deviationMax)

  are considered as defective pixels. By default, the maximum deviation is 0.25 x maximum pixel value (for example for 8-bit images the maximum deviation is 63). The maximum deviations for the black and white images are set using the SapFlatField::SetDeviationMaxBlack / SetDeviationMaxWhite functions. Pixel replacement is enabled/disabled using SapFlatField::EnablePixelReplacement. Pixels are replaced using the pixel to its immediate left, other than the first pixel of a line, which uses the pixel to the right.

7.6 校正相机的平场系数:

  • 配置相机到所需的帧率和曝光时间,调整光照的水平以正常运行。 如果使用,任何水平或垂直的像素合并(binning)也应使用。
  • 镜头应在所需的放大倍率和孔径并轻微不聚焦,以避免在参考图像中引入粒度或细节(当校正完成,重新聚焦镜头)。
  • 由于白色参考点位于物体平面上,其表面的任何标记或污染物(即灰尘、划痕、污迹)都将体现在相机的校正文件中。 为了避免这一点,使用干净的白色塑料或陶瓷材料,而不是试图依靠纸张参考。 (理想情况下,白色物体将在校正过程中移动,因为相机的平均处理会减少白色参考中的任何微小变化的影响。)
  • 调整系统增益直到峰值强度达到所需DN水平,然后使用SapFlatField::ComputeOffset函数校正固定模式噪声(FPN)。 使用镜头盖,以确保没有光线到达传感器。
  • 完成后,取下镜头盖,使用SapFlatField::ComputeOffset使用所需的目标值(DN)进行光响应非均匀性(PRNU)校正。 你希望所有的像素都匹配。 这个目标值应该高于你第一次设置相机时看到的峰值。
  • The system gain remains as first set

7.7 代码示例:C++代码展示如何使用Sapera LT进行平场手动校正

 1 // Rely on the SapFlatField class to automatically create the offset and gain buffers with the
 2 // correct dimensions and format, but perform the calibration manually
 3 // pAcquisition is an existing SapAcquisition object
 4 // pBuffer is an existing SapBuffer object containing an acquired image.
 5 SapFlatField* pFlatField = new SapFlatField(pAcquisition); 
 6 BOOL success = pFlatField->Create();
 7 SapBuffer* pBufferOffset = pFlatField->GetBufferOffset(); 
 8 SapBuffer* pBufferGain = pFlatField->GetBufferGain(); 
 9 // Can also use the following: 
10 // int bufWidth = pBufferOffset->GetWidth(); 
11 // int bufWidth = pBufferGain->GetWidth();
12 int bufWidth = pBuffer->GetWidth();
13 // Can also use the following:
14 // int bufHeight = pBufferOffset->GetHeight();
15 // int bufHeight = pBufferGain->GetHeight();
16 int bufHeight = pBuffer->GetHeight();
17 // Can also use the following:
18 // int bufFormat = pBufferOffset->GetFormat();
19 // int bufFormat = pBufferGain->GetFormat();
20 int bufFormat = pBuffer->GetFormat();
21 // This is for 8-bit buffers.
22 BYTE* pBufData;
23 success = pBuffer->GetAddress(&pBufData);
24 BYTE* pOffsetData;
25 success = pBufferOffset->GetAddress(&pOffsetData);
26 BYTE* pGainData;
27 success = pBufferGain->GetAddress(&pGainData);
28 int gainDivisor = pFlatField->GetGainDivisor();
29 // Code to perform manual calibration using pBufData, pOffsetData,
30 // pGainData, and gainDivisor goes here
31 //
32 success = pFlatField->Destroy();
33 delete pFlatField;

 

 

  

    

 

 

 

 

 

 
 
posted @ 2021-12-30 11:28  玻璃公主  阅读(2108)  评论(0编辑  收藏  举报