两个相机标定two_camera_calibration




two_camera_calibration.hdev


image.png

image.png

* This example program shows how high precision mosaicking
* can be performed with calibrated cameras.
* 
* Further information can be found in the
* Solution Guide III-C 3D Vision, Chapters 9 and 10.
* This example program is used in chapter 9 to
* illustrate calibrated mosaicking.
* 
dev_update_off ()
ImgPath := '3d_machine_vision/multiple_cameras/'
* 
* Open two windows for the left and the right image.
dev_close_window ()
read_image (Image1, ImgPath + 'camera1_ref')
get_image_size (Image1, Width, Height)
WindowScale := 0.66
dev_open_window (0, 0, Width * WindowScale, Height * WindowScale, 'black', WindowHandle1)
dev_open_window (0, Width * WindowScale + 6, Width * WindowScale, Height * WindowScale, 'black', WindowHandle2)
* 
* Set some parameters for both windows.
dev_set_window (WindowHandle1)
dev_set_color ('green')
dev_set_draw ('margin')
dev_set_line_width (2)
dev_set_part (0, 0, Height - 1, Width - 1)
set_display_font (WindowHandle1, 16, 'mono', 'true', 'false')
* 
dev_set_window (WindowHandle2)
dev_set_color ('green')
dev_set_draw ('margin')
dev_set_line_width (2)
dev_set_part (0, 0, Height - 1, Width - 1)
set_display_font (WindowHandle2, 16, 'mono', 'true', 'false')
* 
* We assume that the two cameras are already calibrated
* (we know the internal camera parameters).
gen_cam_par_area_scan_division (0.01619, -734.789, 7.402e-006, 7.4e-006, 324.911, 256.894, 640, 480, CamParam1)
gen_cam_par_area_scan_division (0.0162584, -763.35, 7.39842e-006, 7.4e-006, 324.176, 245.371, 640, 480, CamParam2)
* 
* Read the images and display them.
read_image (Image1, ImgPath + 'camera1_ref')
read_image (Image2, ImgPath + 'camera2_ref')
dev_set_window (WindowHandle1)
dev_display (Image1)
dev_set_window (WindowHandle2)
dev_display (Image2)
* 
* Prepare the camera calibration.
CaltabName := 'caltab_30mm.descr'
create_calib_data ('calibration_object', 2, 1, CalibDataID)
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
set_calib_data_cam_param (CalibDataID, 0, [], CamParam1)
set_calib_data_cam_param (CalibDataID, 1, [], CamParam2)
* 
* Find and display the calibration plate in the images.
dev_set_window (WindowHandle1)
find_calib_object (Image1, CalibDataID, 0, 0, 0, [], [])
get_calib_data_observ_points (CalibDataID, 0, 0, 0, RowCoord1, ColumnCoord1, Index1, Pose1)
get_calib_data_observ_contours (Caltab1, CalibDataID, 'caltab', 0, 0, 0)
dev_display (Caltab1)
* 
dev_set_window (WindowHandle2)
find_calib_object (Image2, CalibDataID, 1, 0, 0, [], [])
get_calib_data_observ_points (CalibDataID, 1, 0, 0, RowCoord2, ColumnCoord2, Index2, Pose2)
get_calib_data_observ_contours (Caltab2, CalibDataID, 'caltab', 1, 0, 0)
dev_display (Caltab2)
* 
disp_message (WindowHandle1, 'Calibration successful', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
clear_calib_data (CalibDataID)
* 
* Determine the offset between the calibration plate surface
* and the object surface
ThicknessCaliper := 2.9 / 1000.0
ThicknessPlate := 5.65 / 1000.0
DiffHeight := ThicknessPlate - ThicknessCaliper
DistancePlates := 0.06488
* 
* Define the pixel size of the mosaic image (in meters).
PixelSize := 0.0001
* 
* For the first (left) image, the determination
* of the necessary shift of the pose is straightforward.
* You can define the upper left corner of the rectified image
* in image coordinates
* based on a preselected border width.
BorderInPercent := 7
get_image_size (Image1, WidthImage1, HeightImage1)
UpperRow := HeightImage1 * BorderInPercent / 100.0
LeftColumn := WidthImage1 * BorderInPercent / 100.0
* 
* Then, this point must be transformed into world coordinates.
image_points_to_world_plane (CamParam1, Pose1, UpperRow, LeftColumn, 'm', LeftX, UpperY)
* 
* For the determination of the height of the rectified image
* we need to define a point that lies near the lower border
* of the first image.
LowerRow := HeightImage1 * (100 - BorderInPercent) / 100.0
* 
* Again, this point must be transformed
* into the world coordinate system.
image_points_to_world_plane (CamParam1, Pose1, LowerRow, LeftColumn, 'm', X1, LowerY)
* 
* The height can be determined as the vertical distance
* between the upper left point and the point near the
* lower image border, expressed in pixels of the rectified image.
HeightRect := int((LowerY - UpperY) / PixelSize)
* 
* Analogously, the width can be determined from a point t
* hat lies in the overlapping area of the two images,
* i.e., near the right border of the first image.
OverlapInPercent := 20
RightColumn := WidthImage1 * (100 - OverlapInPercent / 2.0) / 100.0
image_points_to_world_plane (CamParam1, Pose1, UpperRow, RightColumn, 'm', RightX, Y1)
WidthRect := int((RightX - LeftX) / PixelSize)
* 
* With the shifted pose and the size of the rectified image,
* the rectification map for the first image can be derived.
set_origin_pose (Pose1, LeftX, UpperY, DiffHeight, PoseNewOrigin1)
gen_image_to_world_plane_map (MapSingle1, CamParam1, PoseNewOrigin1, Width, Height, WidthRect, HeightRect, PixelSize, 'bilinear')
* 
* Generate a new homogeneous transformation matrix.
hom_mat3d_identity (HomMat3DIdentity)
* 
* The second image must be rectified such that it fits exactly
* to the right of the first rectified image. This means that the
* upper left corner of the second rectified image must be identical
* with the upper right corner of the first rectified image.
* Therefore, we need to know the coordinates of the upper right corner
* of the first rectified image in the coordinate system that is defined
* by the calibration plate in the second image.
* First, we express the upper right corner of the first rectified image
* in the world coordinate system that is defined by the calibration plate
* in the first image. It can be determined by a transformation from
* the origin into the upper left corner of the
* first rectified image (a translation) followed by a translation along
* the upper border of the first rectified image. Together with the shift
* that compensates the thickness of the calibration plate, this
* transformation is represented by the homogeneous transformation matrix:
hom_mat3d_translate_local (HomMat3DIdentity, LeftX + PixelSize * WidthRect, UpperY, DiffHeight, cp1Hur1)
hom_mat3d_translate_local (HomMat3DIdentity, DistancePlates, 0, 0, cp1Hcp2)
* 
* Then, we need the transformation between the two calibration plates of
* the calibration object. The homogeneous transformation matrix cp1Hcp2
* describes how the world coordinate system defined by the calibration plate
* in the first image is transformed into the world coordinate system
* defined by the calibration plate in the second image. This transformation
* must be known beforehand from a precise measurement of the calibration object.
* From these two transformations, it is easy to derive
* the transformation that transforms the world coordinate system
* of the second image such that its origin lies in the upper left corner
* of the second rectified image. For this, the two transformations
* have to be combined appropriately.
hom_mat3d_invert (cp1Hcp2, cp2Hcp1)
hom_mat3d_compose (cp2Hcp1, cp1Hur1, cp2Hul2)
* 
* With this, the pose of the calibration plate in the second image
* can be modified such that the origin of the world coordinate system
* lies in the upper left corner of the second rectified image.
pose_to_hom_mat3d (Pose2, cam2Hcp2)
hom_mat3d_compose (cam2Hcp2, cp2Hul2, cam2Hul2)
hom_mat3d_to_pose (cam2Hul2, PoseNewOrigin2)
* 
* With the resulting new pose and the size of the rectified image,
* which can be the same as for the first rectified image,
* the rectification map for the second image can be derived.
gen_image_to_world_plane_map (MapSingle2, CamParam2, PoseNewOrigin2, Width, Height, WidthRect, HeightRect, PixelSize, 'bilinear')
* 
* Open a new Graphics Window for the merged image.
dev_open_window (Height * WindowScale, 0, Width * 2 * WindowScale, Height * WindowScale, 'black', WindowHandleCombined)
set_display_font (WindowHandleCombined, 16, 'mono', 'true', 'false')
dev_set_color ('green')
dev_set_draw ('margin')
ScalePlot := 200
RowPlot := 400
Coord := [0:2000]
* 
*  Process all image pairs in a loop.
for I := 1 to 3 by 1
    * 
    * Display both images.
    dev_set_window (WindowHandle1)
    read_image (Image1, ImgPath + 'camera1_' + I$'02d')
    get_image_size (Image1, WidthImage1, HeightImage1)
    dev_set_part (0, 0, HeightImage1 - 1, WidthImage1 - 1)
    dev_display (Image1)
    dev_set_window (WindowHandle2)
    read_image (Image2, ImgPath + 'camera2_' + I$'02d')
    get_image_size (Image2, WidthImage2, HeightImage2)
    dev_set_part (0, 0, HeightImage2 - 1, WidthImage2 - 1)
    dev_display (Image2)
    * 
    * Start the time measurement.
    count_seconds (TimeStart1)
    * 
    * Rectify the image pair from the two-camera setup with map_image.
    map_image (Image1, MapSingle1, RectifiedImage1)
    map_image (Image2, MapSingle2, RectifiedImage2)
    concat_obj (RectifiedImage1, RectifiedImage2, Concat)
    * End the time measurement and calculate the difference.
    count_seconds (TimeEnd1)
    Time1 := TimeEnd1 - TimeStart1
    * 
    dev_set_window (WindowHandleCombined)
    * Start the time measurement again.
    count_seconds (TimeStart2)
    * 
    * Tile both images into one large image.
    tile_images (Concat, Combined, 2, 'vertical')
    * 
    * End the time measurement again and calculate the difference.
    count_seconds (TimeEnd2)
    Time2 := TimeEnd2 - TimeStart2
    * 
    * Display the combined image and the time measurement.
    get_image_size (Combined, WidthComb, HeightComb)
    dev_set_part (0, 0, HeightComb - 1, WidthComb - 1)
    dev_display (Combined)
    disp_message (WindowHandle1, 'Merge cameras: ' + (1000 * (Time1 + Time2))$'.3' + ' ms', 'window', 12, 12, 'black', 'true')
    * 
    * In addition, we plot the accuracy of the mosaicking with a procedure.
    plot_mosaicking_accuracy (Combined, WidthRect, HeightRect, WindowHandleCombined, Coord, ScalePlot, RowPlot)
    if (I < 3)
        disp_continue_message (WindowHandleCombined, 'black', 'true')
        stop ()
    endif
endfor


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864