侵刪
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, height)k為畸變系數
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, height)k1,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)