1. 程式人生 > >利用形狀匹配進行定位,然後提取影象上特定的線段

利用形狀匹配進行定位,然後提取影象上特定的線段

***********************************************************************
												
*																		
* 檔名稱:	Matching Demo												
* 摘    要:	利用形狀匹配進行定位,然後提取影象上特定的線段
* 當前版本:	1.0
* 作    者:	平頭鷹
* 郵    箱: [email protected]
* 完成日期:	2018年10月12日
*------------------------------------------------------------------------




************************************************************************
*** 環境初始化 ***
dev_close_window ()
list_image_files ('Image', 'default', [], ImageFiles)
if (|ImageFiles|<1)
    return ()
endif
read_image (Image, ImageFiles[0])
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width/4, Height/4, 'black', WindowHandle)
dev_set_draw ('margin')
dev_display (Image)


************************************************************************
*** 建立形狀模板 ***
*******************
* 根據專案的實際需求,建立模板可能會選擇不同的方式:
* 1.如果影象是有紋理的,一般選用歸一化的灰度模板,create_ncc_model。
*   比如,有暗紋的窗簾布,上面又印刷了一些圖案,我們在定位這些圖案的時候,可以
*   考慮這種ncc。此外,99%的用到匹配的,基本上都用形狀匹配的方式;
* 2.使用形狀匹配,Halcon中常用的有兩類建立模板的方式。其一,是使用給定的Region,
*   利用create_(scaled_)shape_model運算元,自動提取輪廓建立模板;其二,某些情況,
*   如果直接利用給定的Region,自動提取的結果會有比較多的干擾,這是時候,我們往
*   往會利用手動繪製輪廓,然後利用create_scaled_shape_model_xld的方式建立模板。

************************************************
* 方法1,利用Region直接建立模板
************************************************
* draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
* gen_rectangle1 (Rect0, Row1, Column1, Row2, Column2)
gen_rectangle1 (Rect0, 811.5, 991.5, 1171.5, 1251.5)
* draw_rectangle1 (WindowHandle, Row11, Column11, Row21, Column21)
* gen_rectangle1 (Rect1, Row11, Column11, Row21, Column21)
gen_rectangle1 (Rect1, 895.5, 1119.5, 1079.5, 1339.5)
* 通常情況下,我們需要的實際輪廓並不是標準圖形,如果用了標準圖形建立ModelRegion
* 的話,會有一些非共同特徵的輪廓被提取出來,這樣會影響我們匹配的準確性,因此,可
* 在建立模板區域的時候,做一些區域處理。
difference (Rect0, Rect1, ModelRegion)
reduce_domain (Image, ModelRegion, ModelImage)
create_shape_model (ModelImage, 'auto', rad(-10), rad(20), 'auto', 'auto', 'use_polarity', 'auto', 'auto', ModelID)
get_shape_model_contours (ModelContours, ModelID, 1)
* 顯示模板輪廓。使用get_shape_model_contours運算元得到的輪廓,預設的輪廓的中心會
* 在(0, 0)位置,為了顯示直觀,我們把輪廓移動的它“本來的”位置
area_center(ModelRegion, Area, RowRefer, ColRefer)
vector_angle_to_rigid (0, 0, 0, RowRefer, ColRefer, 0, HomMat2D)
affine_trans_contour_xld (ModelContours, ShowContours, HomMat2D)
dev_display (Image)
dev_display (ShowContours)
* 儲存模板。在實際的專案開發中,模板不會在每次啟動程式都建立,因此,往往是建立之後
* 儲存下來,在下次程式啟動載入,直接使用。
write_shape_model (ModelID, 'RegionModel.shm')
*-----------------------------------------------


************************************************
* 方法2,利用繪製XLD或者直接讀入.dxf檔案建立模板
************************************************
** draw_xld (ContOut, WindowHandle, 'true', 'true', 'true', 'true')
** write_contour_xld_dxf (ContOut, 'MyDrawXld.dxf')
* read_contour_xld_dxf (ModelContours, 'MyDrawXld.dxf', [], [], DxfStatus)
** 注意:這裡用的是create_scaled_shape_model_xld,因為無論是手動畫的或者是讀入的CAD
** 檔案,可能和實際拍攝的都會有一個縮放差,因此用“scaled”
* create_scaled_shape_model_xld (ModelContours, 'auto', rad(-10), rad(20), 'auto', 0.9, 1.1, 'auto', 'auto', 'ignore_local_polarity', 5, ModelID)
* find_scaled_shape_model (Image, ModelID, rad(-10), rad(20), 0.9, 1.1, 0.5, 1, 0.5, 'least_squares', 0, 0.9, ReferRow, ReferCol, Angle1, Scale1, Score1)
* write_shape_model (ModelID, 'XldModel.shm')
* get_shape_model_contours (ModelContours, ModelID, 1)
*-----------------------------------------------


************************************************************************
*** 建立測量模板 ***
*******************

* 這部分可參考halcon標準例子"measure_stamping_part.hdev"
create_metrology_model (MetrologyHandle)
set_metrology_model_image_size (MetrologyHandle, Width, Height)
* draw_line (WindowHandle, Row_1, Col_1, Row_2, Col_2)
* Line := [Row_1, Col_1, Row_2, Col_2]
Line := [892.385, 1395.79, 1245.35, 1395.79]
add_metrology_object_generic (MetrologyHandle, 'line', Line, 25, 5, 1, 30, [], [], LineIndices)
get_metrology_object_model_contour (ModelContour, MetrologyHandle, 'all', 1.5)
get_metrology_object_measures (MeasureContour, MetrologyHandle, 'all', 'all', Row, Column)
* 把測量的位置和模板的位置關聯起來
set_metrology_model_param (MetrologyHandle, 'reference_system', [RowRefer, ColRefer, 0])  
set_metrology_object_param (MetrologyHandle, LineIndices, 'measure_transition', 'positive')
set_metrology_object_param (MetrologyHandle, LineIndices, 'measure_select', 'first')
set_metrology_object_param (MetrologyHandle, LineIndices, 'measure_length1', 55)
set_metrology_object_param (MetrologyHandle, LineIndices, 'measure_length2', 5)
set_metrology_object_param (MetrologyHandle, LineIndices, 'measure_threshold', 10)
set_metrology_object_param (MetrologyHandle, LineIndices, 'min_score', 0.3)


************************************************************************
*** 查詢形狀模板 ***
*******************
read_shape_model ('RegionModel.shm', ModelID)
*read_shape_model ('XldModel.shm', ModelID)
get_shape_model_contours (ModelContours, ModelID, 1)

** 畫搜尋ROI。實際應用中,查詢模板往往是要指定ROI的,這樣可以提高準確度,減少計算時間
* draw_rectangle1 (WindowHandle, Row12, Column12, Row22, Column22)
* gen_rectangle1 (SearchRegion, Row12, Column12, Row22, Column22)
gen_rectangle1 (SearchRegion, 811.5, 1003.5, 1159.5, 1279.5)
for i := 0 to |ImageFiles|-1 by 1
    read_image (Image, ImageFiles[i])
    reduce_domain (Image, SearchRegion, SearchImage)
    find_scaled_shape_model (SearchImage, ModelID, rad(-10), rad(20), 0.9, 1.1, 0.3, 1, 0.5, 'least_squares', 0, 0.9, RowFound, ColFound, AngleFound, ScaleFound, ScoreFound)
    * 如果找到模板
    if (1 = |RowFound|)
        hom_mat2d_identity (HomMat2D)
        hom_mat2d_scale (HomMat2D, ScaleFound, ScaleFound, 0, 0, HomMat2D)
        hom_mat2d_rotate (HomMat2D, AngleFound, 0, 0, HomMat2D)
        hom_mat2d_translate (HomMat2D, RowFound - 0, ColFound - 0, HomMat2D)
        affine_trans_contour_xld (ModelContours, ResultContours, HomMat2D)
        
        
        
        * 按照找到的模板位置,移動測量位置
        align_metrology_model (MetrologyHandle, RowFound, ColFound, AngleFound)
        * 應用測量
        apply_metrology_model (Image, MetrologyHandle)
        * 獲取結果
        get_metrology_object_measures (Contour, MetrologyHandle, 'all', 'all', Row, Column)        
*         gen_cross_contour_xld(Cross, Row, Column, 6, AngleFound)
        get_metrology_object_result (MetrologyHandle, 'all', 'all', 'used_edges', 'row', UsedRow)
        get_metrology_object_result (MetrologyHandle, 'all', 'all', 'used_edges', 'column', UsedColumn)
        gen_cross_contour_xld (UsedEdges, UsedRow, UsedColumn, 10, rad(45))
        get_metrology_object_result_contour (ResultContours, MetrologyHandle, 'all', 'all', 1.5)
        dev_set_color ('gray')
        dev_display (Contour)        
        dev_set_color ('blue')
        dev_display (UsedEdges)
        dev_set_color ('green')
        dev_display (ResultContours)
        *將xld轉換成region  ,region轉換成骨架
        gen_region_contour_xld (ResultContours, Region, 'filled')
        skeleton (Region, Skeleton)
        region_features (Skeleton, 'area', Value)
    else
        disp_message (WindowHandle, '沒有找到模板', 'window', Row, Column, 'black', 'true')
    endif
    stop ()
endfor