halcon中相似變換、仿射變換、投影變換的區別以及應用方式和例程

在機器視覺系統中,鏡頭是重要成像部件之一,而基於小孔成像原理的工業鏡頭往往會產生透視畸變現象,如何校正畸變是進行圖像分析的前提 ,這其中就會用到投影變換,也是幾何變換的一種。除此之外,圖像處理中常用到的平移、旋轉、縮放等,也屬於幾何變換。本文將通過實例詳細介紹HALCON中的幾何變換。

 

基礎知識

 

齊次座標(Homogenous Coordinate)

 

齊次座標就是將一個原本是n維的向量用一個n+1維向量來表示。例如二維點p(x,y)àp(x,y, w)就成了齊次座標,同理三維點p(x,y,z)àp(x,y,z, w)也成了齊次座標。顯然,齊次座標的表達並不是唯一的,隨w值的不同而不同。在計算機圖學中,w 作爲通用比例因子,它可取任意正值,但一般在幾何變換中,總是取w=1。齊次座標表示是計算機圖形學的重要手段之一,它既能夠用來明確區分向量和點,同時也更易於進行幾何變換。

 

以點p(x,y)爲例,如果想把它平移至p(x+a,y+b),是不可能用矩陣計算完成的,現在換成齊次座標(x,y,1),通過矩陣相乘(左側公式) ,很方便得到平移後的座標(x+a,y+b)。通常把變換矩陣寫到左側,爲了保持一致把變換矩陣改成右下角形式,這就是齊次變換矩陣。

 

齊次變換矩陣

 

在同一變換矩陣中既表示姿態(旋轉、縮放等)又表示位置(平移),這種形式的矩陣稱爲齊次變換矩陣。如下:

齊次座標的使用,使得幾何變換更容易計算,尤其對於仿射變換(二維/三維)更加方便,由於圖形硬件、視覺算法已經普遍支持齊次座標與矩陣乘法,因此更加促進了齊次座標使用,使得它成爲圖形學中的一個標準,下面提到的幾何變換(仿射變換)都以齊次座標和齊次變換矩陣爲基礎。

 

幾何變換

 

幾何變換包括:

相似變換(Similarity Transformation)

仿射變換(Affine Transformation)

投影變換(Projective Transformation)

 

注:線性變換不包含平移,所以沒有歸入幾何變換,總之HALCON中常用幾何變換是仿射和投影變換,而相似變換是仿射變換的一種簡單情況!相似變換、仿射變換、投影變換既可以發生在二維空間內也可發生在三維空間內。

 

相似變換

 

相似變換的定義:由一個平面/立體圖形變換到另一個平面/立體圖形,在改變的過程中保持形狀不變(大小方向和位置可變),任何相似變換都可以分解爲等比例縮放、平移、旋轉的組合,例如,對於縮放,用齊次變換矩陣可以如下表示(二維和三維),其中a≠0。

仿射變換

 

仿射變換的定義:由一個平面/立體圖形變換到另一個平面/立體圖形,在改變的過程中保持直線和平行線不變(平行線映射爲平行線),任何仿射變換都可以分解爲縮放、平移、旋轉和切變(Shearing)的組合,對於仿射變換,齊次變換矩陣如下表示(二維和三維):

 對於仿射變換,有兩個比較特殊的變換:非等比例縮放和切變(如下圖),除了這兩個特殊的變換之外,相似變換可以看做是仿射變換的特殊形式,注:線性變換包括旋轉、縮放、切變,但不包含平移,因此仿射變換也定義爲一個線性變換再加上一個平移變換。

 投影變換的定義:變換過程中,直線映射爲直線(但不一定保證平行度),任何二維投影變換都可以用3x3可逆矩陣表示,而任何三維投影變換都可以用4x4可逆矩陣表示。如下:

 

從定義來看,仿射變換可以看做是投影變換的特殊形式。另外,把投影變換矩陣的最後一行變爲[0,0,1]或者[0,0,0,1],即可變爲仿射變換矩陣,也可以證明仿射變換是投影變換的特殊形式。因此,對於平移、縮放、切變等,仿射變換和投影變換都可以實現。

 

如下例子,把左圖進行旋轉操作變成右圖,可以用仿射變換和投影變換兩種方式實現。

仿射變換實現方法

 

投影變換實現方法之一

(直接用給定點生成投影變換矩陣)

  • 投影變換實現方法之二

    (用三維仿射變換矩陣生成投影變換矩陣)

  • 注:對於旋轉來說,也可以看做是相機沿Z軸旋轉90度後的成像效果,因此也可以用三維仿射變換,先轉換相機座標系,再生成投影變換矩陣!

旋轉示例中的仿射變換矩陣(也是齊次變換矩陣)

 

旋轉示例中的投影變換矩陣(3X3),也是可逆矩陣

 

 

 

同理,縮放、切變等,仿射變換和投影變換也都可以實現,但如下變換,只能用二維投影變換矩陣實現,因爲變換過程中沒有保證線的平行性。

總結

 

HALCON中所用的變換知識只涉及到了二維、三維仿射變換和二維投影變換,二維仿射變換多用於平面圖像的平移、旋轉、縮放等;三維仿射變換多用於三維座標系的平移、旋轉等(或者用3D位姿表示),而二維投影變換多用於校正透視畸變,也就是三維空間的景象如何投影到相機靶面上的效果,如果相機和被測平面不垂直就會有畸變。

 

在成像過程中,普通工業鏡頭(小孔成像原理)都會帶來透視畸變,也就是常見的近大遠小現象,除非相機和被測平面保持絕對垂直,否則透視畸變是不可避免的。因此,通過三維空間的仿射變換(變換座標系,使相機不垂直於被攝平面),可以產生透視畸變效果,也就是相當於進行了投影變換,HALCON也提供了算子hom_mat3d_project,能直接把三維仿射變換矩陣轉換成二維投影變換矩陣(4x4的矩陣轉換成3x3矩陣)。下面我們通過一個例子來說明一下。

 

 首先生成單位矩陣,進行一系列的旋轉變換,產生三維仿射變換矩陣,也就是使得相機和被攝平面不垂於!

 把三維仿射變換矩陣再轉化成二維投影變換矩陣

進行投影變換,也就是我們看到的右側的效果

另外一種方法是,直接使用給定點生成投影變換矩陣,可以得到同樣的效果

上面的這個例子是很好的說明了透視畸變現象如何產生的,左側圖是相機垂直於被攝平面,沒有透視變形現象。然後進行了一系列的三維仿射變換,產生的效果就是相機不再垂直於被攝面,所以右圖產生了透視畸變現象,那麼從左圖到右圖恰恰是進行了一次二維投影變換。因爲投影變換矩陣是可逆的,所以也可以把右圖校正爲左圖,這恰恰是HALCON中投影變換的用處所在!

 

以下例子也是HALCON中典型的畸變校正示例,使用的正是投影變換。

 

附錄

 

解釋一下HALCON中的:

hom_mat2d_*和hom_mat3d_*算子

 

hom_mat2d_identity產生2x3矩陣,用於描述二維變換,實際上是3x3齊次變換矩陣(仿射變換);

hom_mat3d_identity產生3x4矩陣,用於描述三維變換,實際上是4x4齊次變換矩陣(仿射變換);

hom_mat2d_*既支持2x3矩陣(仿射變換)也支持3x3矩陣(投影變換);

hom_mat3d_*支持3x4矩陣(仿射變換),也就是4x4齊次變換矩陣

 

關於如何在HALCON中生成的:

仿射變換矩陣和投影變換矩陣

 

仿射變換矩陣

用hom_mat2d_identity或hom_mat3d_identity產生單位矩陣,然後經過平移、旋轉、縮放等操作後得到仿射變換矩陣。

 

投影變換矩陣

hom_mat3d_project能直接把三維仿射變換矩陣轉換成投影變換矩陣,如果知道空間座標系是如何變換的,可以用這種方法;

hom_vector_to_proj_hom_mat2d用給定點生成投影變換矩陣,輸入點的座標爲三維齊次座標,可以支持無窮遠點和有限遠點的變換;

vector_to_proj_hom_mat2d用給定點生成投影變換矩陣,輸入點爲二維非齊次座標,支持有限遠的點的變換;

 

注:對於涉及有限遠點的變換,以上兩個算子都可以!

 

最後給出halcon的投影變換實例:2d_data_codes_rectify_symbol.hdev

例子中用到的圖像:

接着是正文具體代碼:

*參考例子:
*投射變換和二維碼識別:2d_data_codes_rectify_symbol.hdev
*輪廓轉線及調整直線:measure_metal_extended.hdev(例子中還有調整弧線,本例沒有用到)

dev_set_draw ('margin')//設置填充模式
read_image (Image, 'code2d')//獲取圖片
threshold (Image, Region, 10, 90)//通過閾值分割,獲取二維碼的區域
shape_trans (Region, RegionTrans, 'convex')//把區域的邊緣連接起來
gen_contour_region_xld (RegionTrans, Contours, 'border')//區域轉輪廓
segment_contours_xld (Contours, ContoursSplit, 'lines', 5, 10, 1)//把輪廓斷開成線
XCoordCorners := []//保存四邊形的頂點X座標
YCoordCorners := []//保存四邊形的頂點Y座標
*對輪廓進行排序,不排序會影響投射變換操作
sort_contours_xld (ContoursSplit, SortedRegions, 'lower_left', 'true', 'row')
count_obj (SortedRegions, Number)//獲取區域數量
for Index := 1 to Number by 1
    select_obj (SortedRegions, ObjectSelected, Index)//遍歷區域
    *把彎線變直
    fit_line_contour_xld (ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
    gen_contour_polygon_xld (Contour, [RowBegin,RowEnd], [ColBegin,ColEnd])//畫線看效果
    tuple_concat (XCoordCorners, RowBegin, XCoordCorners)//保存X軸數據
    tuple_concat (YCoordCorners, ColBegin, YCoordCorners)//保存y軸數據
endfor
*標記出記錄的點
gen_cross_contour_xld (Crosses, XCoordCorners, YCoordCorners, 6, 0.785398)
*獲取投射變換參數HomMat2D
hom_vector_to_proj_hom_mat2d (XCoordCorners, YCoordCorners, [1,1,1,1], [70,270,270,70], [100,100,300,300], [1,1,1,1], 'normalized_dlt', HomMat2D)
*對圖像進行投射變換
projective_trans_image (Image, Image_rectified, HomMat2D, 'bilinear', 'false', 'false')
*以下爲對二維碼的識別
create_data_code_2d_model ('Data Matrix ECC 200', [], [], DataCodeHandle)
find_data_code_2d (Image_rectified, SymbolXLDs, DataCodeHandle, [], [], ResultHandles, DecodedDataStrings)
clear_data_code_2d_model (DataCodeHandle)
area_center_xld (SymbolXLDs, Area, Row, Column, PointOrder)
*顯示二維碼解析到的數據
disp_message (3600, DecodedDataStrings, 'window', Row+160, Column-100, 'black', 'true')

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章