4.4 ROI与图像遮罩
感兴趣区域(ROI)是从图像显示窗口中选择的一个图像区域,该区域内的数据是对图像进行分析处理时应重点关注的部分,也常被称为子图像(subimage)。为图像处理设定ROI,可以将注意力集中在要解决问题的主要方面,减少要处理的数据量,提高系统的处理速度和实时性。在机器视觉系统开发过程中,常见的ROI操作包括构建ROI、关联ROI到图像显示窗口、从图像显示窗口中提取ROI以及清除图像显示窗口中的ROI等。图像显示窗口中的图像不断变化时,与之关联的ROI可以保持不变。
ROI可通过各种标准几何形状或自由的封闭域来描述。从数据结构角度来看,ROI自身并不包括图像数据,它只是说明图像中哪个区域的数据需要被重点关注。NI Vision使用称为ROI Descriptor的数据结构来描述ROI,图4-31显示了该数据结构及其图解。由图可知,ROI可以由其矩形边界(global rectangle)和一个或多个不同的轮廓(contours)共同定义。矩形边界是指一个底边与图像底边平行,且恰好包含整个ROI的矩形,该矩形左上和右下顶点的坐标保存在ROI数据结构中的Global Rectangle数组中。ROI区域可以通过一个或多个几何轮廓来限定,这些不同几何轮廓所定义区域的交集构成了整个ROI。
图4-31 ROI数据结构及说明
用于限定ROI区域的轮廓也保存在一个称为Contours的数组中,数组的每个元素由特征ID、类型(type)和包含多个坐标值的数组Coordinates构成。特征ID用来说明该元素描述的轮廓是ROI的外边沿(external)还是内边沿(internal)。如果为外边沿,则其内部的所有区域被看作是ROI区域的一部分;而如果为内边沿,其外部所有部分均被当作是ROI区域的一部分。type值指定了元素所描述轮廓的几何形状,这些形状与表4-8中描述的ROI工具所创建的几何形状一致。Coordinates数组中每两个元素构成了轮廓中多个顶点的坐标。由此可见,Contours数组中的元素定义的轮廓本质上用于描述图像中某个区域,而单个或多个元素共同描述的轮廓所限定区域的交集就是最终希望得到的ROI。图4-31中只使用多边形(polygon)ROI工具定义的一个轮廓来描述ROI。
在LabVIEW中使用NI Vision定义ROI的方法大致可分为交互式、程序代码定义以及图像遮罩转换三大类,如表4-13所示。采用交互方式定义ROI时,需要用户使用各种ROI工具在图像中指定ROI区域,前述使用图像显示控件和外部图像显示窗口的工具条定义ROI的方法就是采用交互方式。除这两种情况外,ROI构造器(ROI constructor)也允许用户以交互的方式定义ROI。采用交互方式定义ROI可以减少程序代码的编写量,但在程序运行过程中需要用户参与。由于用户的操作习惯和操作环境千差万别,因此即使同一图像同一用户每次绘制的ROI也可能不同。如果要减少用户参与,精确定义ROI,则可通过程序代码来实现。相应地,开发人员也要花更多的精力研究如何在图像中精准确定ROI位置,并编写代码。最后,ROI也可以与图像遮罩相互转换,因此使用图像遮罩也可以定义ROI。
表4-13 ROI定义方法
ROI构造器可以看作是外部图像显示窗口与浮动ROI工具条组合的特殊形式。在主程序运行过程中,它将指定的外部图像显示窗口临时变更为模态窗口,或以Windows模态对话框的形式显示图像和ROI工具,用户只有选定ROI或取消ROI的选择,主程序才能继续运行。ROI构造器特别适合在运行过程中不显示图像(通常是为了提高程序运行效率,而放弃不必要的图像显示),但又需要通过交互方式定义ROI的机器视觉应用。
在程序中使用ROI构造器需要用到表4-14所列的VI。通过ROI构造器定义感兴趣区域的流程可概括为:显示图像和ROI构造器→用户定义ROI→确认后返回ROI描述。IMAQ ConstructROI可在指定窗口或独立对话框中以模态方式显示图像和指定的ROI工具,生成ROI构造器。用户随后就能在其中选择ROI工具并绘制ROI。经确认后,ROI构造器将返回描述所创建ROI的数据ROI Descriptor,这些数据可以进而被各种图像分析处理函数使用。IMAQ WindGetROI、IMAQ WindSetROI、IMAQ WindEraseROI、IMAQ WindROIColor用于获取、关联、清除图像显示窗口中的ROI或更改绘制ROI轮廓的颜色。
表4-14 ROI构造器控制VI
图4-32给出了一个使用ROI构建器以交互方式定义ROI的程序界面和程序代码。程序一开始先将图像wether.png读入内存等待进一步处理。紧接着由While循环和事件结构组成的事件处理器待命,随时准备处理各种用户界面事件。当用户单击Display Image按钮时,ShowImg Value Change事件分支中的IMAQ WindSetup和IMAQWind Draw就把内存中的图像绘制在一个独立的外部图像显示窗口中。若用户随后单击Construct ROI按钮,DefROI Value Change事件会被触发,其对应事件分支中的IMAQConstructROI将创建ROI构造器。由于传递给它的窗口编号为0,与之前IMAQWind Draw绘制的外部图像显示窗口编号(默认值窗口编号为0)一致,因此,IMAQConstructROI会将0号编号的图像显示窗口临时变为模态窗口形式的ROI构造器,并在其右侧显示ROI工具条。
图4-32 使用ROI构造器定义ROI
当用户在ROI构造器中定义好感兴趣区域并确认后,程序就返回所定义区域所对应的ROI Descriptor。此时,若用户再次单击Display Image按钮,就会发现之前定义的ROI显示在窗口中,说明它已经与该窗口关联。注意,在交互方式下,若构造器指定了窗口编号,则创建的ROI会自动与该窗口关联。若要使用程序代码将ROI Descriptor描述的ROI与图像显示窗口关联,可以使用IMAQ WindSetROI。如果要清除图像显示窗口中的ROI,可以单击Erase ROI按钮,它将触发EraseROI Value change事件,调用IMAQ WindEraseROI清除ROI。最后,单击Exit按钮退出程序时,IMAQ WindClose和IMAQ Dispose会清理现场,结束程序。
此外,在LabVIEW的Vision→Machine Vision→Select Region of Interest函数选板中,有4个用于选择点(IMAQ Select Point)、线(IMAQ Select Line)、矩形(IMAQ Select Rectangle)和环面(IMAQ Select Annulus)ROI的VI,这些VI运行时也会生成模态的ROI构造器窗口。不同之处在于窗口中显示的工具仅为一种,而且ROI构造器只返回几何形状的简易数据结构,而不是ROI Descriptor。
机器视觉系统开发过程中,常用到的几何形状有点、线段、矩形和环面。从简易数据结构角度来看,点可以用其在图像中的水平垂直坐标Point(x,y)表示,线段可以用起始点和终止点的坐标Line(StartX, StartY, EndX, EndY)表示,矩形可以用其左上和右下顶点的坐标来限定。若要得到旋转矩形,则可以将水平矩形沿着其中心逆时针旋转一定角度。也就是说水平矩形是旋转矩形旋转角为0时的特殊情况。据此,可以想到使用矩形未被旋转时的左上和右下顶点以及一个旋转角(rotation)作为所有矩形的简易数据结构,表示为Rectangle(left, top, right, bottom, rotation)。其中,旋转角指以矩形中心为旋转点逆时针旋转的角度。若其值不为0,则返回数据中的左上、右下点坐标并不是旋转后矩形中这些点的坐标,而是旋转角为0时矩形中对应点的坐标。环面简易数据结构可以由圆心坐标、内外半径及起止角来描述,表示为Annulus(CenterX,CenterY,InnerRadius,OuterRadius, StartAngle, EndAngle)。图4-33显示了矩形和环面的简易数据结构示意图。
图4-33 矩形和环面简易数据结构示意图
使用程序代码定义ROI归根结底是在程序运行过程中,通过各种方式确定ROI Descriptor数据结构的实例。常见的方法包括使用簇捆绑函数生成ROI描述数据(如将检测到的目标轮廓数据打包为ROI)、由其他NI Vision的图像分析处理函数自动生成,或者由几何形状的简易数据结构转换生成它的实例。其中后两种方法在机器视觉程序中尤为常见,而且有时还需要把ROI Descriptor再次转换回几何形状的简易数据结构。表4-15列出了几何形状简易数据结构与ROI Descriptor之间相互转换的VI,这些VI位于LabVIEW的Vision and Motion→Vision Utilities→Region of Interest→Region of Interest Conversion函数选板中。
表4-15 几何形状与ROI Descriptor相互转换VI
举例来说,假定用户使用图4-31程序定义了环面ROI,则程序返回的ROI Descriptor中不仅包括环面ROI的边界矩形Global Rectangle,还包括定义环面ROI轮廓的Contours数组。如果某些图像处理函数仅需要可以定义环面的简易数据结构,则返回的ROI Descriptor就不能直接作为参数供其使用,必须提取出其中所包括的必要的环面定义数据,并重新将其打包为简易结构才能使用。IMAQ Convert ROI to Annulus正是完成此项任务的最佳VI。相反若某些图像处理VI需要以环面ROI Descriptor作为输入,但其他VI返回的却是环面的简易数据结构,IMAQ Convert Annulus to ROI即可完成需要的转换。
除了以上介绍的ROI转换VI, NI Vision还提供了其他几个与ROI操作相关的重要VI,包括图像遮罩(Image Mask)与ROI相互转换的VI、ROI组合与拆分、ROI在不同坐标系之间的转换以及将已标记的图像(Label Image)区域转换为ROI的VI。这些VI位于LabVIEW的Vision and Motion→Vision Utilities→Region of Interest函数选板中,如图4-34所示。
图4-34 NI Vision的ROI函数选板
表4-16列出了与ROI操作相关的几个重要VI,并对其进行了分类,包括图像遮罩ROI之间的转换、ROI的分组与拆分、ROI在不同坐标系之间的转换以及标记图像与ROI的转换等。以下对这些VI的使用进行简要介绍。
表4-16 ROI操作VI
图像遮罩是尺寸小于或等于待处理图像尺寸且独立于待处理图像的8位图像。它的作用与ROI类似,都可用于划定图像中需要重点关注的区域,但图像遮罩对区域内像素的“管理”更为严苛。可以将图像遮罩置于待处理的图像上来确定待处理图像或其中某个区域的像素是否要被处理。当图像遮罩中的某个像素值不为0时,它所“覆盖”的待处理图像的像素必须参与运算;而若像素值为0,则其“覆盖”的像素点将保持不变。NI Vision使用位于LabVIEW的Vision and Motion→Vision Utilities→Image Processing→Operator函数子选板中的IMAQ Mask对图像进行遮罩运算,运算过程会将源图像复制至目标图像,复制时若输入图像遮罩中像素为0,则其所覆盖的像素值会在目标图像中被置0,否则保留原像素值。
图4-35以图像遮罩对图像像素取反运算的影响为例,说明了图像遮罩的作用。A为待处理图像,B为一幅遮罩图像,C为对A图像直接进行取反运算后的效果,D则为使用了图像遮罩B对A进行取反运算后的效果。在所有图像中,白色像素的值为255,黑色像素的值为0。图像像素取反运算可以用下面的公式描述:
Inverse (x,y)=(Level-1)-Pixel (x,y)
其中Inverse(x,y)为对图像像素取反运算后的结果,Level为灰度级数(8位图像灰度级数为256),Pixel(x,y)为待处理图像中像素的灰度。对比C和D不难看出,C是对A中所有像素都应用图像取反公式的结果,而D则是对A中局部区域应用取反公式的输出,该局部区域由B中非0像素部分限定(白色正方形部分)。
图4-35 图像遮罩示例
图像遮罩与待处理图像的位置关系可以使用其左上顶点(原点)在待处理图像中的坐标来描述。当遮罩被置于待处理图像的[i,j]点时,它将仅对待处理图像中[i,j]点之后的部分像素产生作用。当i,j=[0,0]时,其原点与待处理图像的原点重合。图4-36显示同一图像遮罩对图像中不同区域进行处理的例子。其中A为待处理图像,B为遮罩,C为遮罩原点与待处理图像原点重合时的处理结果,D为遮罩原点为[3,1]时的处理结果。由图可知,即使用同一遮罩对同一图像进行处理,当相对位置不同时,处理结果将截然不同。而且,遮罩仅对待处理图像的有效像素区域有效,如果它所覆盖的位置超出有效像素区域,则将忽略其作用(图中边界像素的值未受影响)。若要在程序中读取或设置内存图像中图像遮罩的原点位置,可以使用4.2节介绍过的IMAQ GetOffset和IMAQ SetOffset函数。
图4-36 图像遮罩位置对处理结果的影响
在实际机器视觉算法中,为了提高系统运算速度,增强系统的实时性,通常使用与待处理图像中ROI的边界矩形大小相同的图像遮罩。这种情况下,还可以先定义一个任意形状的ROI,再将其转换为遮罩图像,生成任意形状的遮罩图像。另外,有些情况下也要反过来把遮罩图像转换为ROI。例如,在进行灰度测量时,往往需要对图像进行二值化,把无效区域标记为0,然后将图像作为遮罩参数传递给相关VI进行计算;但是在进行色彩对比时,却需要将遮罩转换为ROI才能顺利进行计算。
图4-37给出了一个在程序中需要将ROI转换为图像遮罩的实际例子。程序先完成以下初始化工作:
(1)分别为待处理图像和图像遮罩分配内存缓冲,读入待处理的图像并将其显示在图像显示控件中。
(2)使用IMAQ Convert Rectangle to ROI将一个常量定义的矩形转换为ROI,并将其作为图像显示控件的初始ROI。
(3)运行一次While循环(i=0),使用Case结构中的IMAQ ROIToMask将初始ROI转换为图像遮罩,并传递给IMAQ Histograph来计算图像遮罩所覆盖部分的图像灰度分布。
While循环用于处理图像控件的各种事件。如果用户重新在图像显示控件中绘制ROI,Draw事件会被触发,相应的Case结构中的IMAQ ROIToMask会将用户绘制的ROI转换为图像遮罩,并传递给IMAQ Histograph来计算图像遮罩所覆盖部分的图像灰度。图4-37也显示了程序运行时的前面板。
仔细研究描述ROI的数据结构ROI Descriptor,可以发现它使用Contours数组来描述组成ROI所包括的轮廓形状。这意味着ROI既可包含单个轮廓形状(单个数组元素),也可由多个轮廓形状构成(多个元素)。由此不难想到,可以将多个ROI中的轮廓形状提取出来,重新组合在一个单独的ROI Descriptor中进行描述,以方便对它们进行统一操作。这个过程称为ROI的组合,可以使用IMAQ Group ROIs来完成。在实际过程中,为了方便操作,需要先把多个描述ROI的ROI Descriptor打包在一个数组中,再传递给该VI。经过组合操作后,所有ROI中的轮廓被整合到一个ROI Descriptor中。也可以使用IMAQ Ungroup ROIs对某个包含多个轮廓形状的ROI Descriptor进行ROI拆分。拆分操作是组合操作的逆过程,它可以将ROI拆分成多个独立的ROI Descriptor,并打包为数组后输出。拆分后的每个ROI Descriptor仅包含一个轮廓形状。IMAQ Ungroup ROIs与IMAQ Group ROIs位于LabView的同一函数选板中。
图4-37 ROI转换为图像遮罩的程序及前面板
IMAQ TransformROI可以根据参考坐标系(Base Reference Coordinate System)与另一个新的坐标系(New Reference Coordinate System)之间的平移和旋转关系,将图像中的ROI位置做相应的平移和旋转,以确保ROI在两个参考坐标系中的相对位置不变。通常情况下,在图像中设置的ROI都参照图像坐标系,如果不更改ROI的位置或形状,它就会圈定视场中的某一固定区域而不变化。但是,在实际机器视觉系统中,被识别目标的位置和放置角度却并不一定都固定,而是可能在一定范围内旋转或移动。如果ROI始终固定在视场中的某个位置,就很难保证要检测的目标特征每次都落在所设定的ROI范围内。
例如,某机器视觉系统在搭建之初以图4-38(a)作为标准图像,选定了一个以图像坐标系为参考坐标系的矩形ROI来圈出要检测的保险丝的位置。但是,若后续采集到图4-38(b)和(c)的被测目标时,由于原来所设定的ROI位置固定,系统就不能准确地圈出要检测的保险丝区域,从而可能导致检测失败。因此,需要设法使ROI也能根据检测目标位置或方向的变化在图像坐标系中做相应的调整。
图4-38 位置固定的ROI(彩图见插页)
怎样才能使ROI跟随检测目标位置和方向的变化进行自动调整呢?分析以上情况可发现,根据标准图像所指定的ROI是可以准确圈出特征区域的。问题发生在后续过程中采集到的检测目标位置和方位有变化时。如果能事先根据标准图像中被测目标的固定特征(如边缘、固定点等)设置参考坐标系,并在新采集的图像中根据同样的特征为检测过程重设新坐标系,就能根据两个坐标系之间的关系获知新采集的图像中目标相对于标准图像中目标的平移和旋转量。若对基于标准图像设置的ROI施加同样的平移和旋转变换,就能使其对于新的测量目标也能准确圈定特征区域。以上整个过程可总结为以下几步:
(1)基于标准图像中目标的固定特征,确定参考坐标系。
(2)在标准图像中设置用于检测的ROI。
(3)根据目标的固定特征,在新采集的图像中重新设置新坐标系。
(4)参照新坐标系和参考坐标系的平移旋转,对用于检测的ROI做同样的变换,以保证其仍能准确圈定特征区域。
例如,为了能检测图4-39所示器件的保险丝是否正常,可以先以图4-39(a)为标准图像,通过边沿检测确定坐标系(O,x,y)和用于检测保险丝的矩形ROI。在实际检测过程中,采集到图4-39(b)和图4-39(c)所示的检测目标时,就可以根据检测目标的边沿确定坐标系(O′,x′,y′)和(O″,x″,y″),然后再依据它们与原坐标系之间的转换关系,对用于检测保险丝的ROI进行旋转或平移,就能确保它相对于特征的位置不变。
图4-39 位置随坐标变化的ROI(彩图见插页)
IMAQ TransformROI正是参照两个坐标系的关系对ROI进行变换的工具。为了弄清楚IMAQ TransformROI的工作原理,有必要先研究平面坐标系的变换方法。平面中常见坐标系的变换包括坐标系的旋转、平移以及镜像翻转等。例如,图4-40中坐标系(O′,x′,y′)就可看作是坐标系(O,x,y)逆时针旋转θ度后再将原点平移到(x0,y0)点得到的。
先来看笛卡儿坐标系旋转时的情况。假定图4-40(a)中点R在原坐标系(O,x,y)和旋转后的新坐标系(O′,x′,y′)中的坐标分别为(x,y)和(x′,y′),则由图可以得到二者的转换关系如下:
图4-40 平面坐标系变换
若再将坐标原点平移到(x0,y0),则可以得到某一固定点在两个坐标系中坐标之间的转换关系表达式:
坐标系的镜像变换比较简单,若沿y轴镜像变换,则x值变为原值的负数;而若沿x轴做镜像变换,则y值变为原值的负数。在图像处理应用开发过程中,常以图像的左上顶点做原点,向下方向作为y轴方向。这种坐标系与常见笛卡儿的坐标系方向正好相反,因而将其称为间接(indirect)坐标系,笛卡儿坐标系称为直接(direct)坐标系统。间接坐标系恰好是对直接坐标系沿x轴镜像变换后的结果。
考虑图像中的ROI从一个坐标系变换到新坐标系中的情况。由于已知平面上某一固定点在两个不同坐标系中坐标的转换关系,若想将图像中一个ROI转换到新的坐标系中,只要使其在新坐标系统中的坐标与其原来在参考坐标系统中的坐标相同,并计算出转换后的ROI在原图像坐标系中的位置坐标即可。例如,若要将图4-41中坐标系(O,x,y)对应的ROI“Line”转换到坐标系(O,x′,y′)中,就可以使用IMAQ TransformROI。
图4-41中的程序先读取图像文件,并把一个简单的线段数据类型实例转换为相应的ROI Descriptor。该线段在图像坐标系中的起始点坐标为(100,300),终止点坐标为(200,300)。IMAQ TransformROI会根据输入的原图像坐标系与新坐标系之间的关系计算线段在新坐标系中的位置,确保它相对于新坐标系的位置与原来一致,并按照ROI Descriptor数据类型输出。IMAQ TransformROI中坐标系参数采用坐标原点、y轴方向(Direct/Indirect)以及坐标系相对图像坐标系像逆时针旋转的角度来描述。IMAQ Group ROIs将变换前后的ROI组合在一起,随后输入到图像显示控件的ROI属性,以便显示。
图像标记(Label Image)操作常用于颗粒(Particles)分析,它把二值图像中相互连通的一组像素(称为颗粒)全部更改为某一固定灰度值(用8位或16位表示)。可通过4连通或8连通原则来判断像素是否属于同一颗粒(参见第12章)。图像标记操作的输入图像为二值图像,但其输出却是含有为每个颗粒都设置了灰度标记值的灰度图像,其中灰度标记值的数量等于图像中颗粒的数量再加上用于背景的灰度标记值0。如果图像使用了调色板,则被标记的多个颗粒有可能使用同一灰度标记值。
图4-41 ROI转换示例
图4-42给出了对一幅图像中颗粒进行标记的实例程序。程序代码在将图像Alu.bmp读入内存后即进入图像标记循环。在循环中,若用户没有改变IMAQ Threshold使用的阈值,则循环就不做任何处理,否则就会对图像中的颗粒或区域进行标记。标记的过程是先用IMAQ Threshold将图像分割为二值图像,再经形态学处理函数IMAQ Morphology对颗粒或区域的边缘做平滑处理,随后才由IMAQ Label(位于LabVIEW的Vision and Motion→Image Processing→Processing函数选板中)将各区域内的像素修改为灰度标记值。除了对图像标记,程序还返回已标记的颗粒数,并使用IMAQ Quantify返回各标记区域的像素灰度统计信息,如图4-43所示。IMAQ Quantify的Image Mask参数必须为标记图像,关于该VI及IMAQ Threshold和IMAQ Morphology的使用将在第11章和第12章进行详细介绍。
图4-42 图像标记实例
图4-43 图像标记实例运行结果
完成了图像的标记,就可以设法将已标记图像中的某一感兴趣部分提取出来单独分析。IMAQ LabelToROI可以把图像中已标记区域转换为ROI。如果某个标记值对应多个区域,则其返回的ROI Descriptor将包含多个区域的轮廓。在使用它时还可以指定是否仅转换ROI外部轮廓和ROI包含的最大像素个数,以进一步约束转换结果。
如前所述,二值遮罩图像和标记图像均可转换为ROI,而且二值遮罩图像不仅能直接转换为ROI,还能先被标记后再转换为ROI,那么这些转换ROI的方法有什么不同呢?图4-44给出了测试几种转换ROI方法不同之处的程序。程序先为ROI的转换和图像显示分配了内存,然后使用IMAQ Threshold对图像进行了阈值化处理,将其转换为二值图像。其中灰度在范围[128,255]内的像素被置为255,其他像素灰度被置为0。阈值化后的二值图像可以被看作是遮罩图像,直接由IMAQ MasktoROI将其中的区域转换为ROI。由于图像中可能包含多个灰度区域,因此还需要使用IMAQ Ungroup ROIs从转换后的输出参数中提取由Particle index指定的ROI。为了直观地看到显示效果,程序复制了原图,并在清理其中的图无损层后,重新以图形和文字形式绘制了所提取出的ROI及其索引。类似地,程序还在图像阈值化后对其先进行标记,再分别使用IMAQ LabelToROI和IMAQ MaskToROI将标记图像转换为ROI并进行显示。
由图4-44所显示的运行结果可知,当Particle index为0时,直接使用IMAQ MasktoROI将二值遮罩图像转换为ROI的结果与先对二值图像进行标记再使用IMAQ MasktoROI将其转换为ROI的效果类似;而直接使用IMAQ LabelToROI将标记图像转换为ROI时,返回的第一个区域为图像背景。选取不同的Particle index(索引),可以发现使用其他两种ROI转换方法得到的ROI索引始终比IMAQ LabelToROI转换到的区域索引大1。
图4-44 几种转换ROI方法的对比
ROI对应的图像区域也可以单独提取出来进行显示,这需要借助IMAQ Extract 2。例如,图4-45中的程序代码就可以将图中矩形ROI对应的图像区域提取并单独显示出来。需要注意,IMAQ Extract 2使用矩形的左上、右下定点限定所选择的区域,在实际使用中,可以从ROI Descriptor中分解出ROI的边界矩形或者更为精准的轮廓矩形来提取图像中的某一部分。
图4-45 提取图像中ROI对应的区域(彩图见插页)