机器视觉中不同类型光源的不同打光方式的效果探究

有经验的机器视觉工程师都会认可这样一句话:机器视觉项目的成败在于能否得到一张打光优秀的图片。如果采集到的图片本身“质量”很差,那么接来下的图像处理工作就会困难重重。

由于项目的需求以及光源厂商的努力,目前机器视觉光源的类型可以说十分丰富,例如条光、背光、平行背光、同轴光、点光、隧道光、碗光、环形光、球形光、条形聚光等。根据光的波长和颜色,又可以分为X光、蓝光、红光、白光、红外光等。

网上关于光源选型方面的资料多如牛毛,我不想再重复,我想说点其他的。

在光源大家族中,有一种光最为灵活多变,它就是环形光。环形光有低角度环形光、高角度环形光等不同类型,例如0°环形光、30°环形光、45°环形光、60°环形光、90°环形光等。

不同的资料对于这个环光的“角度”定义不同,有的指“光源照射方向与水平面的夹角”,有的指“光源照射方向与镜头光轴(一般是竖直方向)的夹角”。本文采用后一种定义方式来描述。

为什么说环形光的花样多呢?因为它的口径可以不同、它的“角度”可以不同、它的光的颜色可以不同、它的安装高度也可以不同(其他光源安装高度不同差异一般不会有这么大)。

下面我以拍摄镜头模组为例,采用不同“角度”的环形光,沿着镜头光轴方向在不同高度分别采集图像,大家可以观察图像的特点与变化。

(这是一个手机镜头模组,高约6mm,中间有一块透明的有划伤的玻璃镜片)

注意:以下每一系列组图中,光源的高度都是从高到低不断往下移的

① 90°环形光(即光源照射方向与竖直方向成90°的环形光)

② 30°环形光

如果你读到了这里,不妨停下来想想,为什么用不同角度、不同高度的环形光照明,图像会有这样的差异呢?

其核心就一点:始终抓住有哪些光被反射之后,沿着竖直方向被相机捕捉到了。物体在相机中成了像,是因为物体表面有光反射进了相机,这些光被相机捕捉到从而成了像。

如果想提高光源选型的能力,深刻理解上面这两句话是十分必要的。

在只有光源而暂时没有相机的时候,如何猜测相机采集到的图像是什么样的呢?我有一个小技巧:把头伸到被测物正上方,从上往下竖直观察被测物的打光情况。为什么要以这个姿势观察呢?因为相机也是以这个姿势“观察”被测物的。

从上面的两组图片可以看出,如果想检测模组的镜片划伤,在合适的高度用90°环形光打光,能得到一张高质量的易于处理的图片。但这是最佳的方案吗?未必。

我们用背光试试:

划伤一览无余,很好地从背景里被分割出来了。当然,对于这种检测并不是说背光就一定优于90°环光,因为很多时候,由于现场条件的限制,是没有办法放置背光的。

我顺手拍了一张同轴光打光的,顺便也贴上来:

同轴光源一般比较贵,它之所以贵我猜测一方面是因为它发出的是平行光,另一方面是因为它内部的那个45°的“半透半反”装置需要较高的装配精度。

观察上面的同轴光打光的图片,可以发现,用同轴光拍的图片一般看起来比较“平庸”。同轴光能够凸显物体表面的不平整,克服表面反光造成的干扰

这些是由同轴光的特性决定的:同轴光最终照到被测物上的是竖直向下的光,光经物体反射后,只有竖直往上的反射光才能通过同轴光的“半透半反”装置竖直进入相机(因此反光不见了,因为反光折射到其他方向去了,没有射入相机)。

另外,很多人在应用中应该发现了,在相机镜头参数、安装高度等其他条件一致时,把同轴光源调到最亮去打光,得到的图片一般亮度也很低,这是为什么呢?这是因为同轴光从发出光到光最终被相机捕捉到,它经历了两次“半透半反”的过程,光源的亮度有极大的损失。

文末我再把之前的两句话重复一下:

始终抓住有哪些光被反射之后,沿着光轴方向被相机捕捉到了。物体在相机中成了像,是因为物体表面有光反射进了相机,这些光被相机捕捉到从而成了像。

时间: 2024-10-12 13:46:20

机器视觉中不同类型光源的不同打光方式的效果探究的相关文章

Java中枚举类型Enum的一种使用方式

枚举类定义如下: package com.qunar.enumtest; public enum Status { SCUUESS("1", "成功"), FAILED("2", "失败"); private String value; private String desc; public String getValue() { return value; } public void setValue(String valu

函数中的类型是怎么工作的

函数中的类型是怎么工作的 理解类型标记 我们已经理解函数了,看看函数中的类型是怎么工作的,还有域和范围.这只是一个概述,这个"understandingF# types"系列会为你详细介绍. 首先,我们应该多理解类型符号一点.我们之后箭头符号用于域和范围,所以它总是像函数签名: val functionName : domain -> range 看这些示例函数 : let intToString x = sprintf "x is %i" x // form

第66课 C++中的类型识别

1. 类型识别 (1)在面向对象中可能出现下面的情况 ①基类指针指向子类对象 ②基类引用成为子类对象的别名 ▲静态类型——变量(对象)自身的类型(定义变量类型时类型或参数类型) ▲动态类型——指针(引用)所指向的对象的实际类型 (2)基类指针转子类指针: ①示例:Derived* d = static_cast<Derived*>(pBase); //危险的转换方式 ②问题:不安全,是否能强制类型转换取决动态类型. 2. 利用多态获取动态类型 (1)解决方案 ①在基类中定义虚函数,并返回具体的

NET中的类型和装箱/拆箱原理

谈到装箱拆箱,DebugLZQ相信给位园子里的博友一定可以娓娓道来,大概的意思就是值类型和引用类型的相互转换呗---值类型到引用类型叫装箱,反之则叫拆箱.这当然没有问题,可是你只知道这么多,那么DebugLZQ建议你花点时间看看楼主这篇文章,继续前几篇博文的风格--浅谈杂侃. 1. .NET中的类型 为了说明装箱和拆箱,那首先必须先说类型.在.NET中,我们知道System.Object类型是所有内建类型的基类.注意这里说的是内建类型,程序员可以编写不继承子自System.Object的类型,这

Scala 深入浅出实战经典 第53讲:Scala中结构类型实战详解

王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 腾讯微云:http://url.cn/TnGbdC 360云盘:http://yunpan.cn/cQ4c2UALDjSKy 访问密码 45e2土豆:http://www.tudou.com/programs/view/pR_4sY0cJLs/优酷:http://v.youku.com/v_show/id_

JS中的类型检测

JS中用于类型检测的函数有typeof.instanceof .Object.prototype.toString.constrcutor.duck type typeof用于检测基本类型和函数 有些特殊情况 null.数组.Date数据类型用typeof判断返回的是object instanceof用来判断对象类型,基于原型链,可以用来判断数组和Date数据类型

泛型中的类型约束和类型推断

前一篇文章介绍了泛型的基本概念.在本文中,我们看一下泛型中两个很重要的特性:类型约束和类型推断. 类型约束 相信你还记得前面一篇文章中的泛型方法,在这个泛型方法中,我们就使用了类型约束. 类型约束(type constraint)进一步控制了可指定的类型实参,当我们创建自己的泛型类型或者泛型方法的时候,类型约束是很有用的. 回到前一篇例子中的泛型方法,这个泛型方法就要求可指定的类型实参必须实现了IComparable接口. 为什么会有这个约束呢?原因很简单,因为我们在泛型方法的实现中直接调用T类

C#中值类型和引用类型

本文将介绍C#类型系统中的值类型和引用类型,以及两者之间的一些区别.同时,还会介绍一下装箱和拆箱操作. 值类型和引用类型 首先,我们看看在C#中哪些类型是值类型,哪些类型是引用类型. 值类型: 基础数据类型(string类型除外):包括整型.浮点型.十进制型.布尔型. 整型(sbyte.byte.char.short.ushort.int.uint.long.ulong ) 浮点型(float 和 double ) 十进制型(decimal ) 布尔型(bool ) 结构类型(struct) 枚

iOS中block类型大全

iOS中block类型大全 typedef的block 作为属性的block 作为变量的block 作为方法变量入参的block 作为方法参数的block 无名block 内联函数的block 递归调用的block 作为方法返回值的block 作为函数名的block(太过奇葩,完全不知道怎么用-_-!) iOS中block类型大全,码迷,mamicode.com