Halcon例程分析11:物體位姿檢測

打開halcon,按下ctrl+e打開halcon自帶例程。方法->模板匹配(基於描述符)->locate_cookie_box.hdev

* This example shows how to find a cookie box aligned in different
* directions with the descriptor based matching feature. First, a
* model and a reference pose are computed from the reference
* image, then the model is searched in a sequence of images
* showing the cookie box in different orientations. Using the
* resulting pose we can also check whether the box is placed
* upside down or not.
* 
* 
*重新創建特徵點模型變量,如果爲true則每次運行都對ROI進行特徵點提取
ReCreateDescrModel := false
* 
dev_update_off ()
dev_close_window ()
*讀取圖像
read_image (Image, 'packaging/cookie_box_01')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (4)
dev_set_color ('blue')
* 
*由攝像機內參生成攝像機參數,實際項目中需要根據自己的相機進行標定校準
gen_cam_par_area_scan_division (0.0155565, -109.42, 1.28008e-005, 1.28e-005, 322.78, 240.31, 640, 480, CamParam)
* 
*
*感興趣區域變量定義,四個點都是圖像座標(224,115),(224,540),(406,540),(406,115)左上角開始順時針數
RowsRoi := [224,224,406,406]
ColumnsRoi := [115,540,540,115]
*世界座標系中相對應的點座標,後面除1000是轉換單位,與以上座標一一對應(-189,-80),(189,-80),(189,80),(-189,80)左上角開始,順時針
*世界座標系的中心在盒子的正中心位置,向右是X軸,向下是Y軸z軸在盒子前平面上
WorldX := [-189,189,189,-189] / 1000.0
WorldY := [-80,-80,80,80] / 1000.0
* reference pose of the object to the camera is computed
*計算盒子位姿與圖像的關係,輸出參數pose即爲兩者間的關係,Quality是對位姿的一個評價
vector_to_pose (WorldX, WorldY, [], RowsRoi, ColumnsRoi, CamParam, 'iterative', 'error', Pose, Quality)
*根據上面映射出來的關係Pose,算出圖像上某點對應的世界座標,這麼做的意義是什麼? 沒什麼,就是單純驗證一下而已
image_points_to_world_plane (CamParam, Pose, RowsRoi, ColumnsRoi, 'm', XOuterBox, YOuterBox)
* generate ROI for model training
*通過兩個角點生成水平矩形
gen_rectangle1 (Rectangle, 224, 115, 406, 540)
*摳出矩形區域的圖像
reduce_domain (Image, Rectangle, ImageReduced)
* 
* If desired re-create the descriptor-based model. Note that this may take
* several minutes dependent on the hardware.
dev_display (Image)
if (ReCreateDescrModel)
    dev_display (Rectangle)
    disp_message (WindowHandle, 'Creating the descriptor-based model ... \n(may take a minute)', 'window', 10, 10, 'black', 'true')
    count_seconds (SecondsCreation1)
    *生成一個透視變換特徵點模型,要把當前物體的姿態Pose輸入進去作爲參考位姿
    create_calib_descriptor_model (ImageReduced, CamParam, Pose, 'harris_binomial', [], [], ['depth','number_ferns','patch_size','min_scale','max_scale'], [11,30,17,0.4,1.2], 42, ModelID)
    count_seconds (SecondsCreation2)
    TimeCreation := SecondsCreation2 - SecondsCreation1
    *把模型寫入文件方便下次調用,不然每次都要創建模型
    write_descriptor_model (ModelID, 'cookie_box_model.dsm')
else
    * If desired read the descriptor-based model from disk
    disp_message (WindowHandle, 'Reading the descriptor-based model file from disk ...\n ... will take a few seconds!', 'window', 10, 10, 'black', 'true')
    dev_set_check ('~give_error')
    dev_error_var (ErrorVar, 1)
    *把前面存儲的模型讀出使用
    read_descriptor_model ('cookie_box_model.dsm', ModelID)
    Error := ErrorVar
    dev_set_check ('give_error')
    if (Error != H_MSG_TRUE)
        *如果沒有成功讀出模型,即模型還未被創建則執行以下代碼創建模型
        * Create the descriptor-based model if it's not available on disk
        dev_display (Image)
        dev_display (Rectangle)
        disp_message (WindowHandle, 'Reading the descriptor-based model file from disk  ... \n... failed!', 'window', 10, 10, 'black', 'true')
        disp_message (WindowHandle, 'Creating the descriptor-based model (may take a minute)', 'window', 48, 10, 'black', 'true')
        * 
        count_seconds (SecondsCreation1)
        *創建模型
        create_calib_descriptor_model (ImageReduced, CamParam, Pose, 'harris_binomial', [], [], ['depth','number_ferns','patch_size','min_scale','max_scale'], [11,30,17,0.4,1.2], 42, ModelID)
        count_seconds (SecondsCreation2)
        TimeCreation := SecondsCreation2 - SecondsCreation1
        * Ignore writing errors as they are not critical for this example
        dev_set_check ('~give_error')
        write_descriptor_model (ModelID, 'cookie_box_model.dsm')
        dev_set_check ('give_error')
        ReCreateDescrModel := true
    endif
endif
* 
* 
if (ReCreateDescrModel)
    dev_display (Image)
    disp_message (WindowHandle, 'One model created in ' + TimeCreation$'.03f' + ' seconds.', 'window', 10, 10, 'black', 'true')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
endif
* 
* 
* Main loop:
* search model in image sequence
*總共10張測試圖像
for Index := 1 to 10 by 1
    OutputString := []
    read_image (Image, 'packaging/cookie_box_' + Index$'.02')
    dev_display (Image)
    * 
    * find model (using default parameters)
    count_seconds (Seconds1)
    *在圖像中查找模板,得到這幅圖像的位姿輸出Pose,Score是評價得分
    find_calib_descriptor_model (Image, ModelID, [], [], [], [], 0.25, 1, CamParam, 'num_points', Pose, Score)
    count_seconds (Seconds2)
    Time := Seconds2 - Seconds1
    * 
    * display results
    if (|Score| > 0)
        *獲取前面創建的模型的特徵點座標,Row ,Col是數組
        get_descriptor_model_points (ModelID, 'search', 0, Row, Col)
        dev_set_colored (12)
        dev_set_line_width (1)
        *通過上面特徵點的座標生成小十字叉做顯示用
        gen_cross_contour_xld (Cross1, Row, Col, 6, 0.785398)
        dev_display (Cross1)
        dev_set_color ('lime green')
        dev_set_line_width (3)
        *畫座標系,這個Pose位置是跟模型有關的,模型中存有座標系原點的信息
        disp_3d_coord_system (WindowHandle, CamParam, Pose, 0.1)
        * 
        *把位姿轉爲3維旋轉矩陣,包括旋轉和平移
        pose_to_hom_mat3d (Pose, HomMat3D)
        *通過位姿轉換矩陣計算出當前圖像對應的四個點所在的世界座標,即以剛纔創建模板時建立的座標系參考,現在這個被轉動了的盒子對應的4個點當前的座標位置
        *即剛纔繪製矩形的這四個點現在被HomMat3D這個矩陣轉到哪去了
        affine_trans_point_3d (HomMat3D, XOuterBox, YOuterBox, [0,0,0,0], XTrans, YTrans, ZTrans)
        *世界座標映射到圖像中,因爲我們的相機位置是不變的,那現在要框出被轉動了的物體,那肯定要知道當前物體在圖像中的位置
        project_3d_point (XTrans, YTrans, ZTrans, CamParam, RowTrans, ColTrans)

        * 
        * 
        gen_contour_polygon_xld (Contour, RowTrans, ColTrans)
        close_contours_xld (Contour, Contour)
        dev_display(Image)
        dev_display (Contour)
        dev_set_color('red')
        disp_3d_coord_system (WindowHandle, CamParam, Pose, 0.07)
        * 
        * determine direction of box
        *通過位姿判斷盒子的狀態,有沒有放倒之類的
        if ((Pose[5] > 45 and Pose[5] < 135) or (Pose[5] > 225 and Pose[5] < 315))
            OutputString := 'Box label found in ' + (Time * 1000)$'.4' + ' ms (on the side)'
        elseif (Pose[5] > 135 and Pose[5] < 225)
            OutputString := 'Box label found in ' + (Time * 1000)$'.4' + ' ms (upside down)'
        else
            OutputString := 'Box label found in ' + (Time * 1000)$'.4' + ' ms'
        endif
    endif
    if (|Score| == 0)
        OutputString := 'No label found'
    endif
    disp_message (WindowHandle, OutputString, 'window', 10, 10, 'black', 'true')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
endfor
dev_display (Image)
disp_message (WindowHandle, 'Program finished.\nPress \'Run\' to clear all descriptor models.', 'window', 10, 10, 'black', 'true')
stop ()
dev_update_on ()

物體位姿狀態原圖,箭頭指示個方向信息

檢測物體位姿狀態

發佈了60 篇原創文章 · 獲贊 8 · 訪問量 9692
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章