halcon3D gen_image_to_world_plane_map的图像高精度拼接技术
基于上一篇文章,对gen_image_to_world_plane_map有了深刻的理解
https://blog.csdn.net/Tianwen_running/article/details/143661157?fromshare=blogdetail&sharetype=blogdetail&sharerId=143661157&sharerefer=PC&sharesource=Tianwen_running&sharefrom=from_link
讲一讲基于这个算子的图像拼接技术
一,聊聊原理
1,首先我们在一张平板上准备两张标定图片,确定两个标定图片中心点之间之间的距离是d,就像下面这个样子
2,首先两个相机都是校准过的,对相机的内参是已知的。以左视图为基准,拍两张照片,如下图
3,求出两图的pose1和pose2对图像进行从图像坐标系向世界坐标系的map关系。对于map后的imagemaped图像来说,只要像素大小一致,这两张图像的联系是,他们的0,0点,在世界坐标系下的关系是已知的,那就是在x方向的距离是D.为什么是x,这是标定板照片在制作时定好的,在pose中,反应的中心00点在标定图像的正中心位置。
4,先对image1进行全图片的向世界坐标系的转换,那么问题来了pose2的世界坐标系的map00点应该在什么地方呢
关系式 pose2沿自己的x轴方向移动-d,到达pose1的位置,然后沿向y方向移动pose1设置map00点的距离和x方向移动pose1距离右边框的距离,到达它的世界坐标map00点,有点绕绕的,在代码里看看,结果是这样的
5,在这里参考的是halcon的实例two_camera_calibration.hdev,当然halcon处理的更好,实例真的非常值得学习!
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:=0.0029
DiffHeight := ThicknessPlate - ThicknessCaliper
DistancePlates := 0.06488
*
*马赛克像素的大小0.0001m.
PixelSize := 0.0001
******将pose的00点,移动到像素00点对应的世界坐标系下
image_points_to_world_plane (CamParam1,Pose1, 0, 0, 'm', X, Y)
set_origin_pose (Pose1,X, Y, 0, PoseNewOrigin)
get_image_size (Image1, Width2, Height2)
image_points_to_world_plane (CamParam2, Pose1, Height2, Width2, 'm', X2, Y2)
widthx:=round((X2-X)/0.0001)
widthy:=round((Y2-Y)/0.0001)
gen_image_to_world_plane_map (Map, CamParam1, PoseNewOrigin,Width2, Height2,widthx, widthy, PixelSize , 'bilinear')
map_image (Image1, Map, ImageMapped2)hom_mat3d_identity (HomMat3DIdentity1)
***两个标定板中心距离是DistancePlates := 0.06488
hom_mat3d_translate_local (HomMat3DIdentity1, -DistancePlates, 0, 0, HomMat3DTranslate)
***向世界坐标系转换中,第二章照片的00点位置,应该在左照片的右下角处
***移到pose1的00点后,再向x方向移动 X2,Y2的距离
hom_mat3d_translate_local (HomMat3DTranslate, X2,Y, 0, HomMat3DTranslate1)****对pose的中心点进行移动
pose_to_hom_mat3d (Pose2, HomMat3D)
hom_mat3d_compose (HomMat3D, HomMat3DTranslate1, HomMat3DCompose)
***再转回pose
hom_mat3d_to_pose (HomMat3DCompose, Pose2Origin)get_image_size (Image2, Width3, Height3)
gen_image_to_world_plane_map (Map1, CamParam2, Pose2Origin, Width3, Height3, widthx, widthy, PixelSize, 'bilinear')
map_image (Image2, Map1, ImageMapped3)concat_obj (ImageMapped2, ImageMapped3, ObjectsConcat1)
tile_images (ObjectsConcat1, TiledImage1, 2, 'horizontal')***目测看看两个中心的距离 289,396和289,1045
***a:=0.069
a:=(1045-396)*0.0001