3.4 數據結構
在研究機器視覺算法之前,我們必須分析機器視覺應用中涉及的基本數據結構。因此,本節中我們先介紹一下表示圖像、區域、亞像素輪廓、句柄以及數組數據結構。
3.4.1 Image
Image指HALCON的圖像類型。在機器視覺中,圖像是基本的數據結構,它所包含的數據通常是由圖像采集設備傳送到計算機的內存中的。
圖像通道可以被簡單看作一個二維數組,這也是程序設計語言中表示圖像時所使用的數據結構。因此在像素(r,c)處的灰度值可以被解釋為矩陣g=fr,c中的一個元素。更正規的描述方式為:我們視某個寬度為w、高度為h的圖像通道f為一個函數,該函數表述從離散二維平面Z2的一個矩形子集r={0,…,h?1}×{0,…,w?1}到某一個實數的關系f:r→R,像素位置(r,c)處的灰度值g定義為g=f(r,c)。同理,一個多通道圖像可被視為一個函數f:r→Rn,這里的n表示通道的數目。
在上面的討論中,我們已經假定了灰度值是由實數表示的。在幾乎所有的情況下,圖像采集設備不但在空間上把圖像離散化,同時也會把灰度值離散化到某一固定的灰度級范圍內。多數情況下,灰度值被離散化為8位(一個字節),也就是,所有可能的灰度值所組成的集合是0~255。
簡單來說,圖像的通道是圖像的組成像素的描述方式,如果圖像內像素點的值能用一個灰度級數值描述,那么圖像有一個通道。比如灰色圖像,每個像素的灰度值為0~255;如果像素點的值能用三原色描述,那么圖像有三個通道。比如RGB是最常見的顏色表示方式,它的每個像素擁有R(Red,紅色)、G(Green,綠色)、B(Blue,藍色)3個通道,各自的取值范圍都是0~255。彩色圖像如果只存在紅色和綠色、沒有藍色,并不意味著沒有藍色通道。一幅完整的彩色圖像,紅色、綠色、藍色三個通道同時存在,圖像中不存在藍色只能說明藍色通道上各像素值為零。
(1)在HALCON中查看圖像變量
在HALCON中,把鼠標移動到HALCON變量窗口中的圖像變量上會顯示圖像變量的類型、通道及尺寸,如圖3.24所示。

圖3.24 HALCON的變量窗口
值得注意的是,在一般的圖像處理中,灰度圖像已經可以滿足要求。因此,為了節約計算量并加快速度,通常會將彩色圖像轉換成灰度圖像進行處理。在HALCON中,可以使用rgb1_to_gray算子或rgb3_to_gray算子將彩色圖像轉換成灰度圖像。
(2)在HALCON中訪問通道
①如要獲得某一指定通道的圖像,可以使用access_channel算子。
access_channel(MultiChannelImage : Image : Channel :)
MultiChannelImage:輸入的多通道圖像。
Image:輸出從多通道圖像中計算得到的指定通道圖像。
Channel:輸入的要訪問的通道索引,默認值:1,可取建議值:1、2、3、4、5、6等,但取值要小于通道數。
②如要獲取通道數量,則可以使用count_channels算子。
count_channels(MultiChannelImage:::Channels)
MultiChannelImage:輸入的多通道的圖像。
Channels:輸出計算得到的圖像通道數。
(3)通道合并與分離
①如將兩圖像的通道疊加得到新圖像,可以使用append_channel算子。
append_channel(MultiChannelImage, Image:ImageExtended::)
MultiChannelImage:輸入的多通道圖像。
Image:要疊加的圖像。
ImageExtended:疊加后得到的圖像。
②如要將三個單通道灰度圖像合并成一個三通道彩色圖像,可以使用compose3算子。
compose3(Imagel, Image2, Image3:MultiChannelImage::)
Imagel、Image2、Image3:對應三個單通道灰度圖像。
MultiChannelImage:轉換后得到的三通道彩色圖像。
③如要將多幅單通道圖像合并成一幅多通道彩色圖像,可以使用channels_to_image算子。
channels_to_image(Images:MultiChannellmage::)
Images:要進行合并的單通道圖像。
MultiChannelImage:合并得到的多通道彩色圖像。
④如要將三通道彩色圖像轉化為三個單通道灰度圖像,可以使用decompose3算子。
decompose3(MultiChannellmage:Imagel, Image2, Image3::)
MultiChannelImage:要進行轉換的三通道彩色圖像。
Image1:轉換得到第一個通道的灰度圖像,對應Red通道。
Image2:轉換得到第二個通道的灰度圖像,對應Green通道。
Image3:轉換得到第三個通道的灰度圖像,對應Blue通道。
讀取一幅紅色的三通道彩色圖像后利用decompose3算子分解成三個單通道圖像,其中得到的紅色通道是一幅白色圖像,得到的綠色和藍色通道是黑色圖像。所以我們能夠知道紅色在R通道中比較明顯,同理綠色和藍色分別在G和B通道中比較明顯。
⑤如要將多通道圖像轉換為多幅單通道圖像,可以使用image_to_channels算子。
image_to_channels(MultiChannelImage:Images::)
MultiChannelImage:要進行轉換的多通道彩色圖像。
Images:轉換后得到的單通道圖像。
⑥若要將彩色圖像從RGB空間轉換到其他顏色空間,可以使用trans_from_rgb算子。
trans_from_rgb(ImageRed, ImageGreen, ImageBlue:ImageResultl, ImageResult2, ImageResult3:ColorSpace:)
ImageRed、ImageGreen、ImageBlue:分別對應彩色圖像的R通道、G通道、B通道的灰度圖像。
ImageResult1、ImageResult2、ImageResult3:分別對應轉換后得到的三個單通道灰度圖像。
ColorSpace:輸出的顏色空間,包括‘hsv’、‘hls’、‘hsi’、‘ihs’、‘yiq’、‘yuv’等,RGB顏色空間轉換到其他顏色空間有對應的函數關系。
例3.2
圖像通道實例。
程序如下:
*讀取圖像 read_image (Image, 'D:/picture/ship.png') *計算圖像通道數 count_channels (Image, Num) *循環讀取每個通道的圖像 for I := 1 to Num by 1 *獲取多通道指定圖像 access_channel (Image, channel1, I) endfor *拆分通道 decompose3 (Image, RedImage, GreenImage, BlueImage) *合并通道 compose2 (RedImage, GreenImage, MultiChannelImage) *向圖像附加通道 append_channel (MultiChannelImage, BlueImage, ImageExtended)
程序執行結果如圖3.25所示。

圖3.25 圖像通道相關實例
3.4.2 Region
Region指圖像中的一塊區域。機器視覺的任務之一就是識別圖像中包含某些特性的區域,比如執行閾值分割處理。因此至少我們還需要一種能夠表示一幅圖像中一個任意的像素子集的數據結構。這里我們把區域定義為離散平面的一個任意子集:
R?Z2 (3.1)
這里選用R來表示區域是有意與前一節中用來表示矩形圖像的R保持一致。在很多情況下,將圖像處理限制在圖像上某一特定的感興趣區域(ROI)內是極其有用的。就此而論,我們可以視一幅圖像為一個從某感興趣區域到某一數據集的函數:
f:R→Rn (3.2)
這個感興趣區域有時也被稱為圖像的定義域,因為它是圖像函數f的定義域。將上述兩種圖像表示方法統一:對任意一幅圖像,可以用一個包含該圖像所有像素點的矩形感興趣區域來表示此圖像。所以,從現在開始,我們默認每幅圖像都有一個用R來表示的感興趣區域。
很多時候需要描述一幅圖像上的多個物體,它們可以由區域的集合來簡單地表示。從數學角度出發可以把區域描述成集合表示,如式(3.3)所示。
(3.3)
這個定義引入了二值圖像來描述區域。一個二值圖像用灰度值0表示不在區域內的點,用1(或其他非0的數)表示被包含在區域內的點。簡單言之,區域就是某種具有結構體性質的二值圖。
(1)在HALCON中查看區域特征
區域的特征我們可以通過點擊工具欄中的“特征檢測”,如圖3.26(a)所示。在彈出的對話框中選擇region,可以看到region的不同特征屬性及相對應的數值,如圖3.26(b)所示。

圖3.26 特征檢測
region的特征主要有以下三個部分:
①基礎特征:Region的面積、中心、寬高、左上角與右下角坐標、長半軸、短半軸、橢圓方向、粗糙度、連通數、最大半徑、方向等。
②形狀特征:外接圓半徑、內接圓半徑、圓度、緊密度、矩形度、凸性、偏心率、外接矩形的方向等。
③幾何矩特征:二階矩、三階矩、主慣性軸等。
(2)將Image圖像轉換成Region區域
在HALCON中,通常需要將Image圖像轉換成Region區域方便圖像處理,轉換方法一般為以下兩種。
①可以利用閾值分割threshold算子進行轉化。
threshold(Image:Region:MinGray, MaxGray:)
Image:要進行閥值分割的圖像。
Region:經過閥值分割得到的區域。
MinGray:閥值分割的最小灰度值。
MaxGray:閥值分割的最大灰度值。
區域的灰度值g滿足:
MinGray≤g≤MaxGray (3.4)
對彩色圖像使用threshold算子最終只針對第一通道進行閾值分割,即使圖像中有幾個不相連的區域,threshold也只會返回一個區域,即將幾個不相連區域合并然后返回合并的區域。
②使用灰度直方圖進行轉化,步驟如下:
在工具欄中點擊“打開灰度直方圖”,如圖3.27所示。接著打開使能輸出按鈕,最后拖動圖3.27中的紅色豎線(閾值為44的豎線)與綠色豎線(閾值為152的豎線),點擊插入代碼即可。這里綠色豎線、紅色豎線與橫坐標交點的值對應閾值分割的最小值與最大值。

圖3.27 灰度直方圖
例3.3
閾值分割算子獲得區域實例。
程序如下:
*關閉窗口 dev_close_window () *獲得圖像 read_image (Aegypt1, 'egypt1') *獲得圖像尺寸 get_image_size (Aegypt1, Width, Height) *打開窗口 dev_open_window (0, 0, Width, Height, 'black', WindowHandle) *顯示圖像 dev_display (Aegypt1) *閾值分割圖像獲得區域 threshold (Aegypt1, Regions, 23, 160)
程序執行結果如圖3.28所示。

圖3.28 閾值分割獲得區域實例圖
3.4.3 XLD
XLD(eXtended Line Descriptions)稱為亞像素精度輪廓,指圖像中某一塊區域的輪廓。圖像中Image和區域Region這些數據結構是像素精度的,像素越高,分辨率越大,圖像就越清晰。點與點之間的最小距離就是一個像素的寬度,在實際工業應用中,可能需要比圖像像素分辨率更高的精度,這時就需要提取亞像素精度數據,亞像素精度數據可以通過亞像素閾值分割或者亞像素邊緣提取來獲得。在HALCON中XLD代表亞像素邊緣輪廓和多邊形,XLD輪廓如圖3.29所示。

圖3.29 XLD輪廓
通過圖3.29的XLD輪廓可以看出:
①XLD輪廓可以描述直線邊緣輪廓或多邊形,即一組有序的控制點集合,排序是用來說明哪些控制點是彼此相連的關系。這樣就可以理解XLD輪廓由關鍵點構成,但并不像像素坐標那樣一個點緊挨一個點。
②典型的輪廓提取是基于像素網格的,所以輪廓上的控制點之間的距離平均為一個像素。
③輪廓只是用浮點數表示XLD各點的行、列坐標。提取XLD并不是沿著像素與像素交界的地方,而是經過插值之后的位置。
(1)在HALCON中查看XLD的特征
查看XLD特征的步驟與查看Region特征的步驟相似。點擊工具欄中的“特征檢測”,選擇XLD,在圖形窗口選擇要查看的XLD特征,可看到XLD的特征屬性及其相對應的數值,如圖3.30所示。

圖3.30 XLD特征檢測
XLD特征分為四部分:
①基礎特征:XLD面積、中心、寬高、左上角及右下角坐標。
②形狀特征:圓度、緊密度、長度、矩形度、凸性、偏心率、外接矩形的方向及兩邊的長度等。
③云點特征:云點面積、中心、等效橢圓半軸及角度、云點方向等。
④幾何矩特征:二階矩等。
(2)Image轉換成XLD
將單通道Image轉換成XLD可以使用threshold_sub_pix、edges_sub_pix等算子。例如:
threshold_sub_pix(Image:Border:Threshold:)
Image:要提取XLD的單通道圖像。
Border:提取得到的XLD輪廓。
Threshold:提取XLD輪廓的閾值。
例3.4
圖像轉XLD實例。
程序如下:
*關閉窗口 dev_close_window () *獲取圖像 read_image (Image, 'fabrik') *打開適應圖像大小的窗口 dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) *提取圖像得到亞像素邊緣 edges_sub_pix (Image, Edges, 'canny', 2, 12, 22) *顯示邊緣 dev_display (Edges)
程序執行結果如圖3.29所示。
3.4.4 Handle
Handle句柄是一個標識符,是拿來標識對象或者項目的。它就像我們的車牌號一樣,每一輛注冊過的車都會有一個確定的號碼,不同的車號碼各不相同,但是也可能會在不同的時期出現兩輛號碼相同的車,只不過它們不會同時處于使用之中罷了。從數據類型上來看,它只是一個32位(或64位)的無符號整數。應用程序幾乎總是通過調用一個Windows函數來獲得一個句柄,之后其他的Windows函數就可以使用該句柄,以引用相應的對象。在Windows編程中會用到大量的句柄,比如HINSTANCE(實例句柄)、HBIT-MAP(位圖句柄)、HDC(設備描述表句柄)、HICON(圖標句柄)等。
Windows之所以要設立句柄,根本上源于內存管理機制的問題,即虛擬地址。簡而言之,數據的地址需要變動,變動以后就需要有人來記錄、管理變動,因此系統用句柄來記載數據地址的變更。在程序設計中,句柄是一種特殊的智能指針,當一個應用程序要引用其他系統(如數據庫、操作系統)所管理的內存塊或對象時,就要使用句柄。句柄與普通指針的區別在于,指針包含的是引用對象的內存地址,而句柄則是由系統所管理的引用標識,該標識可以被系統重新定位到一個內存地址上。這種間接訪問對象的模式增強了系統對引用對象的控制。
3.4.5 Tuple
Tuple可以理解為C/C++語言中的數組,數組是編程語言中常見的一種數據結構,可用于存儲多個數據,每個數組元素存放一個數據,通常可通過數組元素的索引來訪問數組元素,包括為數組元素賦值和取出數組元素的值。C/C++語言中數組的操作大都可以在Tuple中找到對應的操作。
(1)數組的數據類型
①變量類型:int、double、string等。
②變量長度:如果長度為1則可以作為正常變量使用。第一個索引值為0,最大的索引為變量長度減1。
(2)Tuple數組定義和賦值
①定義空數組。
Tuple:=[ ]
②指定數據定義數組。
Tuple:=[1, 2, 3, 4, 5, 6] Tuple2:=[1, 8, 9,'hello'] Tuple3:=[0x01, 010, 9,'hello'] //Tuple2與Tuple3值一樣 tuple:=gen_tuple_const(100, 47) //創建一個具有100個元素的,每個元素都為47的數據
③Tuple數組更改指定位置的元素值(數組下標從0開始)。
Tuple[2]=10 Tuple[3]='unsigned'//Tuple數組元素為Tuple:=[1, 2, 10,'unsigned', 5, 6]
④求數組的個數。
Number:=|Tuple| //Number=6
⑤合并數組。
Union: =[Tuple,Tuple2] //Union=[1, 2, 3, 4, 5, 6, 1, 8, 9,'hello']
⑥生成1~100內的數。
數據間隔為1 Numl: =[1, 100] 數據間隔為2 Numl: =[1,2,100]
⑦提取Tuple數組指定下標的元素。
T:=Num1[2] //T=5
⑧已知數組生成子數組。
T: =Num2[2, 4] //T=[5, 7, 9]
小結
本章簡要介紹了HALCON的功能特點及其交互式的編程環境HDevelop的開發環境,并概述了利用HALCON進行實時采集和離線采集的圖像采集過程。此外,介紹了圖像處理過程中的五種常用數據結構,分別是圖形Image、Region、XLD、Handle和Tuple,HALCON數據結構是HALCON學習的基礎,本章節對后續HALCON編程的學習具有重要意義。