1. 程式人生 > >halcon相機標定及影象矯正(程式碼)

halcon相機標定及影象矯正(程式碼)

1 halcon相機標定和影象矯正

對於相機採集的圖片,會由於相機本身和透鏡的影響產生形變,通常需要對相機進行標定,獲取相機的內參或內外參,然後矯正其畸變。相機畸變主要分為徑向畸變和切向畸變,其中徑向畸變是由透鏡造成的,切向畸變是由成像儀與相機透鏡的不平行造成的。

針孔模型是理想透鏡的成像模型,但是實際中相機的透鏡不可能是理想的模型,透鏡形狀的非理想特徵造成像點會沿徑向發生畸變。一個像點沿徑向內縮叫負畸變或桶形畸變沿徑向外延叫正畸變或枕形畸變。這種崎變相對於光軸嚴格對稱的也是畸變的主要分量

1徑向畸變                           圖

2切向畸變

相機標定模型公式,

 

                  Or                                                           

          (1-1)

其中,(X,Y,Z)為世界座標系中的實際點座標,(u,v)為影象座標系統的畫素座標,A為相機內參,f畫素單元的焦距,c影象畫素中心點。

                                                   (1-2)

 

3相機成像模型

1.1 halcon相機標定

1.1.1標定助手及相機引數設定

開啟halcon標定助手,載入標定板檔案,選擇相機型別,設定相機引數,然後載入相機採集的標定影象,如下圖所示,影象中全部標定點能夠檢測出,即採集的相機已經設定好,然後生成程式碼。

 

4 halcon標定助

標定板生成:

標定板檔案的生成分為.descr.cpd的檔案,不同格式檔案需使用不同函式進行生成。如,

*生成的是27*31,標定點直徑0.0075mm.cpd標定板(精度高標定板)

create_caltab (27, 31, 0.0075, [13, 6, 6, 20, 20], [15, 6, 24, 6, 24], 'light_on_dark', 'D:/calplate.cpd', 'caltab.ps')

*生成的是7*7,標定點之間距離0.1m,直徑0.5.descr標定板

gen_caltab( 7, 7, 0.1, 0.5, 'D:/caltab.descr', 'caltab.ps')

載入標定影象:

 

5載入標定影象

如圖5所示,載入標定影象後,狀態為確定時,表示標定影象可用於進行標定,然後通過標定助手直接生成標定程式碼即可。

    如圖6所示,載入標定影象後,狀態為檢測出品質問題,此原因大多是照片質量問題,例如光照、對焦、曝光等,需按照halcon標定注意事項的內容拍攝照片。一般照片檢測出品質問題也可以進行相機標定。

載入標定板影象會出現標誌點提取失敗”,出現此原因的需要根據標定介面下的狀態列查詢halcon錯誤資訊,例inconsistent....(image mirrored? ),則需要查詢相應原因(實際標定板(透明)與標定板檔案圖片的可能有映象區別,將實際標定板翻轉即可,多試)。此不可進行相機標定。

                            

6 相機標定問題

相機初始引數設定:

例如,

*f, k, cell width, cell height, cx, cy, width, heightk為畸變係數

StartParameters := [0.029,0,4.3e-006,4.3e-006,2592,1728,5184,3456]

*f, k1, k2, k3, p1, p2, cell width, cell height, cx, cy, width, heightk1,k2,k3徑向畸變, p1,p2為切向畸變

StartParameters := [0.029,0,0,0,0,0,4.3e-006,4.3e-006,2592,1728,5184,3456]

其中,相機初始引數根據相機模型的不同而不同,若相機模型為area(division),則相機引數為7個,若area(多項式),則相機引數12個。

1.1.2 標定程式

利用標定助手生成程式碼,然後執行結果,分析其正確性,若需要將其生成為C/C++程式,可通過halcon介面的‘檔案’項‘匯出’成.cpp檔案。

 

圖7 halcon生成C程式

Halcon標定程式

*Calibration 01: Code generated by Calibration 01

*讀入某個資料夾下的所有標定影象

list_files ('D:/halconvc/img', ['files','follow_links'], ImageFiles)

tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm

|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)

*初始標定引數設定及定義標定板檔案

TmpCtrl_ReferenceIndex := 0

TmpCtrl_PlateDescription := 'D:/calib/calplate.cpd'

StartParameters := [0.029,0,0,0,0,0,4.3e-006,4.3e-006,2592,1728,5184,3456]

TmpCtrl_FindCalObjParNames := 'sigma'

TmpCtrl_FindCalObjParValues := 1

 

* Calibration 01: Create calibration model for managing calibration data

create_calib_data ('calibration_object', 1, 1, CalibHandle)

set_calib_data_cam_param(CalibHandle,0,'area_scan_polynomial', StartParameters)

set_calib_data_calib_object (CalibHandle, 0, TmpCtrl_PlateDescription)

* Calibration 01: Collect mark positions and estimated poses for all plates

gen_empty_obj (Images)

for Index := 0 to |ImageFiles|-1 by 1

    read_image (Image, ImageFiles[Index])

    concat_obj(Images,Image,Images)

*提取影象Images中標定板上的圓形標誌來確定標定板的有效區域

    find_calib_object (Image, CalibHandle, 0, 0, Index, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues)

endfor

* Calibration 01: Perform the actual calibration

calibrate_cameras (CalibHandle, TmpCtrl_Errors)

get_calib_data (CalibHandle, 'camera', 0, 'params', CameraParam)

 

   *將內外參儲存到磁碟

write_cam_par(CameraParam,'D:/halconvc/campar.dat')

get_calib_data (CalibHandle, 'calib_obj_pose', [0, TmpCtrl_ReferenceIndex], 'pose', CameraPose)

set_origin_pose (CameraPose, 0, 0, 0.01, CameraPose)

write_pose(CameraPose,'D:/halconvc/campos.dat')

stop()

 

*另外讀取內外參檔案的函式

read_cam_par ('D:/halconvc/campar.dat', CameraParam)

read_pose ('D:/halconvc/campos.dat', CameraPose)

1.2影象矯正

Halcon中影象矯正,接上述程式,以下介紹兩種方法。

使用內外參,即相機內參和位資

*  goal: rectify images

*  first determine parameters such that the entire image content is visible

*  -> transform image boundary into world plane, determine smallest

*     rectangle around it

*當裝置固定後,位資是唯一的

select_obj(images,image,1)

get_image_pointer1(Image, Pointer, Type, Width, Height)

gen_rectangle1 (ImageRect, 0, 0, Height-1, Width-1)

gen_contour_region_xld (ImageRect, ImageBorder, 'border')

contour_to_world_plane_xld(ImageBorder, ImageBorderWCS, CameraParam,

CameraPose, 1)

smallest_rectangle1_xld (ImageBorderWCS, MinY, MinX, MaxY, MaxX)

set_origin_pose(CameraPose, MinX, MinY, 0.01, PoseForEntireImage)

image_points_to_world_plane(CameraParam,PoseForEntireImage,[Height/2, Height/2, Height/2+1], [Width/2, Width/2+1, Width/2], 1, WorldPixelX, WorldPixelY)

distance_pp(WorldPixelY[0], WorldPixelX[0], WorldPixelY[1], WorldPixelX[1],

            WorldLength1)

distance_pp(WorldPixelY[0], WorldPixelX[0], WorldPixelY[2], WorldPixelX[2],

            WorldLength2)

ScaleForSimilarPixelSize := (WorldLength1+WorldLength2)/2

*  -> determine output image size such that entire input image fits into it

ExtentX := MaxX-MinX

ExtentY := MaxY-MinY

WidthRectifiedImage := ExtentX/ScaleForSimilarPixelSize

HeightRectifiedImage := ExtentY/ScaleForSimilarPixelSize

*  create mapping with the determined parachuangjia

*建立一個投射圖,其描述影象平面與座標軸系統中平面Z為零之間的對映

gen_image_to_world_plane_map(Map, CameraParam, PoseForEntireImage, Width, Height, WidthRectifiedImage, HeightRectifiedImage, \

                             ScaleForSimilarPixelSize, 'bilinear')

clear_calib_data (CalibHandle)

 

* Map the images

for I :=  1 to |ImageFiles| by 1

  select_obj (Images, Img, I)

  map_image (Img, Map, ImageMapped)

  write_image (ImageMapped, 'jpg', 0, 'D:/halconvc/picture/'+I)

Endfor

②僅使用內參

read_image (Image,'D:/halconvc/img/IMG_00.JPG')

read_cam_par('D:/halconvc/campar.dat',CameraParam)

CarParamVirtualFixed:=CameraParam

*對於area(diversion)相機模型(7個引數)

change_radial_distortion_cam_par('adaptive',CameraParam,0,CarParamVirtualFixed)

*對於area(多項式)相機模型(12個引數)

change_radial_distortion_cam_par('adaptive',CameraParam,[0,0,0,0,0],CarParamVirtualFixed)


*上述相機模型選一種後進行下面的map_image

*建立一個投射圖,其描述影象與其相應正在改變的徑向畸變,而對於12個引數的畸變包括徑向和切向畸變

gen_radial_distortion_map(Map,CameraParam,CarParamVirtualFixed,'bilinear')

map_image(Image,Map,ImageMapped)