我們知道,Halcon中的坐標系的原點在左上角,而一般二維平面坐標系的原點在左下角。那么Halcon中坐標系和一般的二維坐標系有什么區別呢?我通過下面這個例子來分析。
1 gen_image_const (Image, 'byte', 512, 512) 2 dev_set_draw ('margin') 3
4 *點1 5 gen_circle (Circle1, 10, 10, 3) 6 disp_message (3600, '(10 ,10)', 'image', 2, 18, 'white', 'false') 7 *點2 8 gen_circle (Circle2, 100, 200, 3) 9 disp_message (3600, '(100 ,200)', 'image', 92, 208, 'white', 'false') 10 *點3 11 gen_circle (Circle3, 400, 100, 3) 12 disp_message (3600, '(400 ,100)', 'image', 392, 108, 'white', 'false') 13
14 union2 (Circle1,Circle2, RegionUnion) 15 union2 (RegionUnion,Circle2, RegionUnion) 16 union2 (RegionUnion,Circle3, RegionUnion) 17 gen_contour_region_xld (RegionUnion, Contours, 'border') 18 write_contour_xld_dxf (Contours,'C:/Users/happy xia/Desktop/XLD的鏡像變換/threePoint.dxf')
這三個點在Halcon中的位置如下圖:
上面的程序最終生成了一個名為threePoint.dxf的文件。我用文本查看器(notepad++、記事本等)打開查看它的數據:
紅框中“10”下面的數據代表點的x值,“20”下面的數據代表點的y值,即截圖里有兩個點(98.5, 396.5)、(99.5, 396.5),這兩個點都是XLD圓上的點,很明顯這兩個點所在圓的圓心坐標是(100, 400)。但是我們看最開始的那張圖,發現只有點(400, 100),並沒有點(100, 400)!
根據上面的事實現象,我們不難發現Halcon中的坐標系實際是這樣的:
根據導出的dxf文件中的坐標點反推,之前的那張圖的點的坐標實際上是這樣的:
這兩個坐標系的區別如下圖。不難看出,它們是上下鏡像的關系(只需要用CAD看圖軟件打開threePoint.dxf文件一看便知)。
上文詳細分析了Halcon坐標系的特點,由於有這樣的特點,Halcon中的XLD和導出的dxf文件輪廓就存在上下鏡像(上下顛倒)的關系,那么我們需要解決的一個問題就是:如何進行XLD的鏡像轉換?
鏡像,對應的單詞是“mirror”,我們在Halcon的幫助中搜索與之相關的算子,僅有mirror_image和mirror_region。
根據我前面的博客文章,我們知道,如果XLD是閉合的,那么可將XLD轉為Region,然后再轉回XLD,因此可將Region作為中介,來鏡像變換XLD。
方法一:以Region為中介,通過mirror_region算子間接對閉合XLD進行鏡像轉換。
原XLD如下圖所示。
1 gen_image_const (Image, 'byte', 7000, 5000) 2 read_contour_xld_dxf (Contours,'unionContour.dxf', [], [], DxfStatus) 3
4 *方法1:先轉換為Region,再鏡像Region,最后轉回到XLD 5 gen_region_contour_xld (Contours, Region, 'margin') 6 mirror_region (Region, RegionMirror, 'row', 6000) 7 gen_contour_region_xld (RegionMirror, ContoursMirror, 'border')
效果如下:
方法二:由於XLD都是由點組成的,因此可以點對點鏡像重繪
1 gen_image_const (Image, 'byte', 7000, 5000) 2 read_contour_xld_dxf (Contours,'unionContour.dxf', [], [], DxfStatus) 3
4 *方法2:點對點鏡像重繪 5 count_obj (Contours, Num) 6 Step := 5
7 axisValue := 6000
8
9 gen_empty_obj (Contour2) 10 for i := 1 to Num by 1
11 select_obj (Contours, Contour, i) 12 get_contour_xld (Contour, Row, Col) 13 Row1 := [] 14 Col1 := [] 15 for j := 0 to |Row|-1 by Step 16
17 Row1:=[Row1,axisValue - Row[j]] 18 Col1:=[Col1,Col[j]] 19
20 endfor 21
22 test_closed_xld (Contour, IsClosed) 23 if (IsClosed = 1) 24 Row1:=[Row1,axisValue - Row[0]] 25 Col1:=[Col1,Col[0]] 26
27 endif 28
29 gen_contour_polygon_xld (Contour1, Row1, Col1) 30 smooth_contours_xld (Contour1, SmoothedContours, 3) 31 concat_obj (Contour2, SmoothedContours, Contour2) 32 endfor
效果如下:
對於方法二程序有疑問的,可以參考我之前寫的文章:http://www.cnblogs.com/xh6300/p/7414256.html
上面兩種方法有一些小問題,不夠完美。方法一主要的局限是只適用於閉合的XLD,方法二對點進行處理的時候,為提高運算速度進行了間隔采樣,導致最終得到的XLD輪廓和初始XLD有細微差異。
其實Halcon還提供了一種最佳解決方案,即仿射變換:hom_mat2d_reflect —— 變換后的對象與初始對象相對於兩點確定的一條直線彼此對稱,其實就是鏡像。
方法三:使用hom_mat2d_reflect 直接進行鏡像的仿射變換
1 gen_image_const (Image, 'byte', 7000, 5000) 2 read_contour_xld_dxf (Contours,'unionContour.dxf', [], [], DxfStatus) 3
4 *方法3:使用仿射變換鏡像 5 hom_mat2d_identity (HomMat2DIdentity) 6 hom_mat2d_reflect (HomMat2DIdentity, 3000, 0, 3000, 100, HomMat2DReflect) 7 affine_trans_contour_xld (Contours, ContoursAffinTrans, HomMat2DReflect)
效果如下: