1.制作标定板和描述文件
(用PS软件打印)
cpp
* 0.00375 mark 点间距 , 不是 点的直径//倒数第二个就是描述文件
gen_caltab(7,7,0.00375,0.5,'caltab_30mm.descr','30-30.ps')
* 1 比 1 打印 。Photoshop 格式
2.把标定板调正
调正的目的是为了确定一个正中心的参考姿态(放在循环读取标定图像之后,获取外参的基准)
方法一:
cpp
*实时调整 相机视野内的标定板中心点的位置和角度 。 角度 保持在0度 ±4度。 位置在中心点 600,800 ±3.
*************************************************************1.初始化******************************************************************************
* 关闭窗口
dev_close_window ()
* 更新程序计数器,更新变量,更新图形窗口
dev_update_off ()
* 设置区域填充模式
dev_set_draw ('margin')
* 读取图像
read_image (Image, './图像/1.bmp')
* 获取图像类型,宽度,高度,缓存数据
get_image_pointer1 (Image, Pointer, Type, Width, Height)
* 打开窗口
dev_open_window (0, 0, Width/5, Height/5, 'black', WindowHandle1)
* 设置字体信息
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
* 显示图像
dev_display (Image)
get_image_size(Image, Width, Height)
* 右下角显示运行字样字符串
disp_continue_message (WindowHandle1, 'black', 'true')
*
*************************************************************2.校正相机****************************************************************************
* 标定文件名
CaltabName := 'caltab_30mm.descr'
* [Focus,Kappa,Sx,Sy,Cx,Cy,Width,Height]
*Focus 镜头的焦距
*Kappa 畸变值
*Sx,Sy 像元尺寸 4.8 0.0000048 =4.8 *e-6 m
*Cx 640, Cy 512
*Width,Height 1280,1024
*3072 2048
StartCamPar := [0.008,0,2.4e-006,2.4e-006,3072/2,1024,3072,2048]
*创建标定数据模型
*CalibDataID 准备一个标定句柄!
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*1.设置相机类型并初始化标定数据模型里的摄像机内部参数
*面扫描 多项式 area_scan_division
set_calib_data_cam_param (CalibDataID, 0, \
'area_scan_division', StartCamPar)
*2.为校正句柄 指定校正文件 'caltab_30mm.descr'
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
*读取图像
read_image (Image1, './图像/1.bmp')
*图像增强
scale_image(Image1, Image, 1.0, 0)
*显示图像
dev_display (Image)
*获取校正板内边框以内的区域
find_caltab (Image, Caltab, CaltabName, 3, 110, 5)
*设置输出对象显示颜色
dev_set_color ('green')
*显示校正板内边框以内的区域
dev_display (Caltab)
*提取出图像中MARK点的位置并计算出摄像机外部参数
find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar,\
128, 10, 18, 0.9, 15, 100, \
RCoord, CCoord, StartPose)
*设置输出对象显示颜色
dev_set_color ('red')
*设置半径为2.5
tuple_gen_const(|RCoord|,2.5, Radius)
*显示MARK所有点的位置
disp_circle (WindowHandle1, RCoord, CCoord, Radius)
dev_set_color ('blue')
*显示MARK中心点的位置
disp_circle (WindowHandle1, RCoord[24], CCoord[24], 6)
*设置第一行的起始点和终点
StartRow:=RCoord[0]
StartColumn:=CCoord[0]
EndRow:=RCoord[6]
EndColumn:=CCoord[6]
dev_set_color('yellow')
*设置第一行的所有点
Row:=[]
Column:=[]
Row:=RCoord[0:6]
Column:=CCoord[0:6]
stop()
*显示第一行的所有点
gen_cross_contour_xld(Cross, Row, Column, 6, 0.785398)
dev_set_line_width(3)
dev_set_color('red')
*由点生成直线
gen_contour_polygon_xld (Contour, Row, Column)
*拟合直线
fit_line_contour_xld (Contour, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
*生成直线
gen_contour_polygon_xld (Contour, [RowBegin,RowEnd], [ColBegin,ColEnd])
*显示直线起点
disp_circle (WindowHandle1, RCoord[0], CCoord[0], 6)
*显示终点
disp_circle (WindowHandle1, RCoord[6], CCoord[6], 6)
*计算直线角度
angle_lx(RowBegin,ColBegin,RowEnd,ColEnd,Phi)
Angle:=deg(Phi)
disp_message (WindowHandle1, 'RCoord= '+RCoord[24], ' WindowHandle', RCoord[24], CCoord[24], 'yellow', 'false')
disp_message (WindowHandle1,'CCoord= '+CCoord[24], ' WindowHandle', RCoord[24]+40, CCoord[24], 'yellow', 'false')
disp_message (WindowHandle1, 'angle= '+Angle, 'WindowHandle', RCoord[0], CCoord[0], 'red', 'false')
dev_update_time ('on')
disp_continue_message (WindowHandle1, 'black', 'true')
*移动到中心点(仿射变换)
get_image_size(Image, Width1, Height1)
vector_angle_to_rigid(RCoord[24], CCoord[24], rad(Angle), Height1/2, Width1/2, 0, HomMat2D)
affine_trans_image(Image, ImageAffinTrans, HomMat2D, 'constant', 'false')
*保存调正的图像
write_image(ImageAffinTrans, 'bmp', 0, 'TZ11')
stop ()
方法二:
cpp
*实时调整 相机视野内的标定板中心点的位置和角度 。 角度 保持在0度 ±4度。 位置在中心点 600,800 ±3.
*************************************************************1.初始化******************************************************************************
* 关闭窗口
dev_close_window ()
* 更新程序计数器,更新变量,更新图形窗口
dev_update_off ()
* 设置区域填充模式
dev_set_draw ('margin')
* 读取图像
read_image (Image, 'pic02.png')
* 获取图像类型,宽度,高度,缓存数据
get_image_pointer1 (Image, Pointer, Type, Width, Height)
* 打开窗口
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle1)
* 设置字体信息
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
* 显示图像
dev_display (Image)
* 右下角显示运行字样字符串
disp_continue_message (WindowHandle1, 'black', 'true')
*
*************************************************************2.校正相机****************************************************************************
* 标定文件名
CaltabName := 'caltab_56mm.descr'
* [Focus,Kappa,Sx,Sy,Cx,Cy,Whith,Height]
StartCamPar := [0.0184898,-548.002,8.33409e-006,8.3e-006,275.291,255.374,1600,1200]
*创建标定数据模型
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*设置相机类型并初始化标定数据模型里的摄像机内部参数
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
*为校正模型指定校正文件
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
*读取图像
read_image (Image, 'pic02.png')
*显示图像
dev_display (Image)
*获取校正板内边框以内的区域
find_caltab (Image, Caltab, CaltabName, 3, 112, 5)
*设置输出对象显示颜色
dev_set_color ('green')
*显示校正板内边框以内的区域
dev_display (Caltab)
*提取出图像中MARK点的位置并计算出摄像机外部参数
find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar, 128, 10, 18, 0.9, 15, 100, RCoord, CCoord, StartPose)
*设置输出对象显示颜色
dev_set_color ('red')
*显示MARK点的位置
disp_circle (WindowHandle1, RCoord, CCoord, gen_tuple_const(|RCoord|,2.5))
dev_set_color ('blue')
*显示MARK点的位置
disp_circle (WindowHandle1, RCoord[24], CCoord[24], 6)
StartRow:=RCoord[0]
StartColumn:=CCoord[0]
EndRow:=RCoord[6]
EndColumn:=CCoord[6]
dev_set_color('yellow')
Row:=[]
Column:=[]
for i:=0 to 6 by 1
Row:=[Row,RCoord[i]]
Column:=[ Column,CCoord[i]]
endfor
stop()
gen_cross_contour_xld(Cross, Row, Column, 6, 0.785398)
gen_contour_polygon_xld (Contour, Row, Column)
fit_line_contour_xld (Contour, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
gen_contour_polygon_xld (Contour, [RowBegin,RowEnd], [ColBegin,ColEnd])
disp_circle (WindowHandle1, RCoord[0], CCoord[0], 6)
disp_circle (WindowHandle1, RCoord[6], CCoord[6], 6)
angle_lx(RowBegin,ColBegin,RowEnd,ColEnd,Phi)
Angle:=Phi*180/3.1415926
disp_message (WindowHandle1, 'RCoord= '+RCoord[24], ' WindowHandle', RCoord[24], CCoord[24], 'yellow', 'false')
disp_message (WindowHandle1,'CCoord= '+CCoord[24], ' WindowHandle', RCoord[24]+40, CCoord[24], 'yellow', 'false')
disp_message (WindowHandle1, 'angle= '+Angle, 'WindowHandle', RCoord[0], CCoord[0], 'red', 'false')
dev_update_time ('on')
disp_continue_message (WindowHandle1, 'black', 'true')
*移动到中心点
get_image_size(Image, Width1, Height1)
vector_angle_to_rigid(RCoord[24], CCoord[24], rad(Angle), Height1/2, Width1/2, 0, HomMat2D)
affine_trans_image(Image, ImageAffinTrans, HomMat2D, 'constant', 'false')
write_image(ImageAffinTrans, 'png', 0, 'pic06.png')
stop ()
3.内外参标定
cpp
* 关闭窗口
dev_close_window ()
* 更新程序计数器,更新变量,更新图形窗口
dev_update_off ()
* 设置区域填充模式
dev_set_draw ('margin')
* 读取图像
read_image (Image, 'MPic/pic01.png')
* 获取图像类型,宽度,高度,缓存数据
get_image_pointer1 (Image, Pointer, Type, Width, Height)
* 打开窗口
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle1)
* 设置字体信息
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
* 显示图像
dev_display (Image)
* 右下角显示运行字样字符串
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
* 标定文件名
CaltabName := 'caltab_56mm.descr'
* [Focus,Kappa,Sx,Sy,Cx,Cy,Width,Height]
StartCamPar := [0.008, 0, 5.2e-006, 5.2e-006, 800, 600, 1600, 1200]
*创建标定数据模型
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*设置相机类型并初始化标定数据模型里的摄像机内部参数
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
*为校正模型指定校正文件
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
NumImages := 8
for i := 0 to NumImages by 1
*读取图像
read_image (Image, 'MPic/pic'+(i+1)$'02d')
*显示图像
dev_display (Image)
gen_rectangle1(Rectangle, 1, 1, 1200,1600)
reduce_domain(Image, Rectangle, ImageReduced1)
min_max_gray ( ImageReduced1, Image, 5, Min, Max, Range)
scale_image (Image, ImageScaled, 255 / Range, -Min * 255 / Range)
*获取校正板内边框以内的区域
find_caltab (ImageScaled, Caltab, CaltabName, 3, 112, 5)
*设置输出对象显示颜色
dev_set_color ('green')
*显示校正板内边框以内的区域
dev_display (Caltab)
*提取出图像中MARK点的位置并计算出摄像机外部参数
find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar, \
128, 10, 18, 0.9, 15, 100, RCoord, CCoord, StartPose)
*设置输出对象显示颜色
dev_set_color ('red')
*显示MARK点的位置
disp_circle (WindowHandle1, RCoord, CCoord, gen_tuple_const(|RCoord|,2.5))
dev_set_part (0, 0, Height-1, Width-1)
*收集观察数据
set_calib_data_observ_points (CalibDataID, 0, 0, i, RCoord, CCoord, 'all', StartPose)
endfor
dev_update_time ('on')
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
*开始校正摄像机
calibrate_cameras (CalibDataID, Error)
*获取优化以后的摄像机内部参数
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
******保存相机内参,且该函数只能保存内参***
write_cam_par(CamParam,'cam.dat')
****************************
*获取优化以后的校正对象姿势,相对于当前参考相机。(这个位姿就是上面调正后的标定板位姿)
get_calib_data (CalibDataID, 'calib_obj_pose', [0,0], 'pose', PoseCalib)
write_pose(PoseCalib, 'poseOrigin.dat')
4.单像素对应的距离
cpp
*矫正后再测量
*选取两个像素点 2个点求距离
Image_X1:=100
Image_Y1:=100
Distance_XY:=500
Image_X2:=Image_X1+Distance_XY
Image_Y2:=Image_Y1+Distance_XY
gen_cross_contour_xld(Cross1, Image_X1, Image_Y1, 46, 0.785398)
gen_cross_contour_xld(Cross2, Image_X2, Image_Y2, 76, 0.785398)
*考虑标定板厚度的影响 PoseNewOrigin在这里
*[0.0209422, -0.0257558, 0.56891, 7.69086, 10.9034, 359.249, 0]
* 0 旋转轴种类
* pose1:=[0,0,0.003,0,0,0,0]
* pose_compose(PoseCalib,pose1,PoseCompose1)
* 0.003 标定板的厚度 3mm 0.003m
*第一个参数是标定的外参
set_origin_pose(PoseCalib,0,0,-0.003,PoseNewOrigin)
*将像素坐标转化为世界坐标(单位m)第一个参数是标定的内参
image_points_to_world_plane(CamParam, PoseNewOrigin, Image_Y1, Image_X1, 'm', World_X1, World_Y1)
image_points_to_world_plane(CamParam ,PoseNewOrigin, Image_Y2, Image_X2, 'm', World_X2, World_Y2)
*******************************************************************************************
*计算世界坐标距离
distance_pp(World_Y1, World_X1, World_Y2, World_X2, DistanceWorld)
*计算像素坐标
distance_pp(Image_X1,Image_Y1,Image_X2,Image_Y2,DistanceImage)
*每个像素对应的世界坐标距离
DistanceOnePixel:=DistanceWorld/DistanceImage
5.求偏移值,把图像移到正中间
cpp
WindowHandle1Out := WindowHandle1
disp_3d_coord_system (WindowHandle1Out, CamParam, PoseNewOrigin, 0.05)
*调整世界坐标到中心偏移量
OffSetX:=(Width/2)*DistanceOnePixel
OffSetY:=(Height/2)*DistanceOnePixel
set_origin_pose (PoseNewOrigin, -OffSetX, -OffSetY, 0, PoseNewOriginFinal)
6.消除畸变和视角畸变
cpp
*内参 CamParam,
* 外参 PoseNewOriginFinal,
*图像的宽度和高度, 像素Width, Height, Width, Height,
*单像素对应距离DistanceOnePixel
gen_image_to_world_plane_map(Map1, CamParam, PoseNewOriginFinal, Width, Height, \
Width, Height,DistanceOnePixel, 'bilinear')
write_object(Map1, 'Map1.obj')
read_object(Map1, 'Map1.obj')
*5.验证 和 测试 !
for Index := 1 to 1 by 1
read_image(Image1, 'MPic/pic'+Index$'02d'+'.png')
* 在这里对原始图像 Image1, 进行畸变矫正,ImageMapped1。
map_image(Image1,Map1, ImageMapped1)
*验证精度是否足够
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle3)
dev_display(ImageMapped1)
column:=611
dev_set_color('blue')
dev_set_line_width(3)
gen_contour_polygon_xld (Polygon, [451,451], [column,column+0.056/DistanceOnePixel])
dev_set_color('red')
dev_set_line_width(1)
gen_cross_contour_xld(Cross1, 451, column, 46, 0.785398)
gen_cross_contour_xld(Cross2, 451, column+0.056/DistanceOnePixel, 46, 0.785398)
disp_message (WindowHandle3, '56cm', 'window', 205, 195, 'red', 'false')
dev_display (Polygon)
dev_display (Cross1)
dev_display (Cross2)
disp_continue_message (WindowHandle3, 'black', 'true')
stop()
endfor
附录
cpp
* This program measures the length of scratches in world
* coordinates in a perspectively distorted image
*************************************************************1.初始化******************************************************************************
* 关闭窗口
dev_close_window ()
* 更新程序计数器,更新变量,更新图形窗口
dev_update_off ()
* 设置区域填充模式
dev_set_draw ('margin')
* 读取图像
read_image (Image, 'picture/image1.png')
* 获取图像类型,宽度,高度,缓存数据
get_image_pointer1 (Image, Pointer, Type, Width, Height)
* 打开窗口
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle1)
* 设置字体信息
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
* 显示图像
dev_display (Image)
* 右下角显示运行字样字符串
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
*
*************************************************************2.校正相机****************************************************************************
* read_cam_par ('cam.dat', CamParam)
* 标定文件名
CaltabName := 'caltab_56mm.descr'
* [Focus,Kappa,Sx,Sy,Cx,Cy,Whith,Height]
StartCamPar := [0.008, 0, 5.2e-006, 5.2e-006, 640, 512, 1280, 1024]
*创建标定数据模型
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*设置相机类型并初始化标定数据模型里的摄像机内部参数
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
*为校正模型指定校正文件
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
NumImages := 8
for i := 1 to NumImages by 1
*读取图像
read_image (Image, 'picture/image'+i$'01d')
*显示图像
dev_display (Image)
gen_rectangle1(Rectangle, 1, 1, 1024,1280)
reduce_domain(Image, Rectangle, ImageReduced1)
min_max_gray ( ImageReduced1, Image, 5, Min, Max, Range)
scale_image (Image, ImageScaled, 255 / Range, -Min * 255 / Range)
*获取校正板内边框以内的区域
find_caltab (ImageScaled, Caltab, CaltabName, 3, 112, 5)
*设置输出对象显示颜色
dev_set_color ('green')
*显示校正板内边框以内的区域
dev_display (Caltab)
*提取出图像中MARK点的位置并计算出摄像机外部参数
find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar, 128, 10, 18, 0.9, 15, 100, RCoord, CCoord, StartPose)
*设置输出对象显示颜色
dev_set_color ('red')
*显示MARK点的位置
disp_circle (WindowHandle1, RCoord, CCoord, gen_tuple_const(|RCoord|,2.5))
dev_set_part (0, 0, Height-1, Width-1)
*收集观察数据
set_calib_data_observ_points (CalibDataID, 0, 0, i, RCoord, CCoord, 'all', StartPose)
endfor
dev_update_time ('on')
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
*开始校正摄像机
calibrate_cameras (CalibDataID, Error)
*获取优化以后的摄像机内部参数
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
*获取优化以后的校正对象姿势,相对于当前参考相机。第一张图作为参考位姿
get_calib_data (CalibDataID, 'calib_obj_pose', [0,1], 'pose', PoseCalib)
******保存相机内参,且该函数只能保存内参***
write_cam_par(CamParam,'cam.dat')
write_pose(PoseCalib, 'poseOrigin.dat')
stop()
*都是两个点求距离***********************************************************************************************************************
*矫正后再测量
*选取两个像素点 2个点求距离
Image_X1:=100
Image_Y1:=100
Distance_XY:=500
Image_X2:=Image_X1+Distance_XY
Image_Y2:=Image_Y1+Distance_XY
*考虑标定板厚度的影响 PoseNewOrigin在这里
set_origin_pose(PoseCalib,0,0,0.003,PoseNewOrigin)
*将像素坐标转化为世界坐标(单位m)
image_points_to_world_plane(CamParam, PoseNewOrigin, Image_Y1, Image_X1, 'm', World_X1, World_Y1)
image_points_to_world_plane(CamParam ,PoseNewOrigin, Image_Y2, Image_X2, 'm', World_X2, World_Y2)
*******************************************************************************************
*计算世界坐标距离
distance_pp(World_Y1, World_X1, World_Y2, World_X2, DistanceWorld)
*计算像素坐标
distance_pp(Image_X1,Image_Y1,Image_X2,Image_Y2,DistanceImage)
*每个像素对应的世界坐标距离
DistanceOnePixel:=DistanceWorld/DistanceImage
*调整世界坐标到中心偏移量
OffSetX:=(Width/2)*DistanceOnePixel
OffSetY:=(Height/2)*DistanceOnePixel
*
*************************************************************3.图像转换****************************************************************************
*这张图 是 世界坐标系的参考姿态图 ,与外参demo 中游标卡尺的坐标系是类似的作用
read_image (ImagePespective, 'picture/image1.png')
*调整相机外参
*假如需要重新拍一张图 ,这个图 与世界坐标系 的姿态一致。由于是平面,不考虑 x y 的变化,只考虑z方向角度的变化。
*所以这里是第5个值 需要替换 ,RZ
*PoseCalibRot 是机器人的坐标系
* tuple_replace (PoseNewOrigin, 5, PoseCalib[5], PoseCalibRot)
*******************************************************************************************
*将摄像机位姿进行X,Y,Z的平移(矩阵乘积) 设定世界坐标
set_origin_pose (PoseNewOrigin, -OffSetX, -OffSetY, 0, PoseNewOriginFinal)
*生成map,消除径向畸变和视角畸变
gen_image_to_world_plane_map(Map1, CamParam, PoseNewOriginFinal, Width, Height, Width, Height,DistanceOnePixel, 'bilinear')
write_object(Map1, 'Map1.obj')
*矫正图像
map_image(ImagePespective,Map1, ImageMapped1)
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle3)
dev_display(ImageMapped1)
column:=511
*0.00021932
gen_contour_polygon_xld (Polygon, [451,451], [column,column+0.056/DistanceOnePixel])
dev_set_color('blue')
gen_cross_contour_xld(Cross, 451, column, 16, 0.785398)
disp_message (WindowHandle3, '56cm', 'window', 205, 195, 'red', 'false')
dev_display (Polygon)
disp_continue_message (WindowHandle3, 'black', 'true')
stop()
详细完整步骤:
调平角度的目的是为了设定一个正中心的标定板外参位姿为参考
cpp
*实时调整 相机视野内的标定板中心点的位置和角度 。 角度 保持在0度 ±4度。 位置在中心点 600,800 ±3.
*************************************************************1.初始化******************************************************************************
* 关闭窗口
dev_close_window ()
* 更新程序计数器,更新变量,更新图形窗口
dev_update_off ()
* 设置区域填充模式
dev_set_draw ('margin')
* 读取图像
read_image (Image, './图片/1')
* 获取图像类型,宽度,高度,缓存数据
get_image_size(Image, Width, Height)
* get_image_pointer1 (Image, Pointer, Type, Width, Height)
* 打开窗口
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle1)
* 设置字体信息
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
* 显示图像
dev_display (Image)
* 右下角显示运行字样字符串
disp_continue_message (WindowHandle1, 'black', 'true')
*
*************************************************************2.校正相机****************************************************************************
* 标定文件名
CaltabName := 'caltab_30mm.descr'
* [Focus,Kappa,Sx,Sy,Cx,Cy,Whith,Height]
* 焦距 初始畸变 像元尺寸 中心点 图像的宽 和 高
StartCamPar := [0.008,0,4.8e-006,4.8e-006,640,512,1280,1024]
*创建标定数据模型
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*设置相机类型并初始化标定数据模型里的摄像机内部参数
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
*为校正模型指定校正文件
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
*读取图像
read_image (Image, './图片/1')
*显示图像
dev_display (Image)
*获取校正板内边框以内的区域
find_caltab (Image, Caltab, CaltabName, 3, 112, 5)
*设置输出对象显示颜色
dev_set_color ('green')
*显示校正板内边框以内的区域
dev_display (Caltab)
*提取出图像中MARK点的位置并计算出摄像机外部参数
find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar, 128, 10, 18, 0.9, 15, 100, RCoord, CCoord, StartPose)
*设置输出对象显示颜色
dev_set_color ('red')
*显示MARK点的位置
disp_circle (WindowHandle1, RCoord, CCoord, gen_tuple_const(|RCoord|,2.5))
dev_set_color ('blue')
*显示MARK点的位置
disp_circle (WindowHandle1, RCoord[24], CCoord[24], 6)
StartRow:=RCoord[0]
StartColumn:=CCoord[0]
EndRow:=RCoord[6]
EndColumn:=CCoord[6]
dev_set_color('yellow')
Row:=[]
Column:=[]
for i:=0 to 6 by 1
Row:=[Row,RCoord[i]]
Column:=[ Column,CCoord[i]]
endfor
stop()
gen_cross_contour_xld(Cross, Row, Column, 6, 0.785398)
gen_contour_polygon_xld (Contour, Row, Column)
fit_line_contour_xld (Contour, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
gen_contour_polygon_xld (Contour, [RowBegin,RowEnd], [ColBegin,ColEnd])
disp_circle (WindowHandle1, RCoord[0], CCoord[0], 6)
disp_circle (WindowHandle1, RCoord[6], CCoord[6], 6)
angle_lx(RowBegin,ColBegin,RowEnd,ColEnd,Phi)
Angle:=Phi*180/3.1415926
disp_message (WindowHandle1, 'RCoord= '+RCoord[24], ' WindowHandle', RCoord[24], CCoord[24], 'yellow', 'false')
disp_message (WindowHandle1,'CCoord= '+CCoord[24], ' WindowHandle', RCoord[24]+40, CCoord[24], 'yellow', 'false')
disp_message (WindowHandle1, 'angle= '+Angle, 'WindowHandle', RCoord[0], CCoord[0], 'red', 'false')
dev_update_time ('on')
disp_continue_message (WindowHandle1, 'black', 'true')
*移动到中心点
get_image_size(Image, Width1, Height1)
vector_angle_to_rigid(RCoord[24], CCoord[24], rad(Angle), Height1/2, Width1/2, 0, HomMat2D)
affine_trans_image(Image, ImageAffinTrans, HomMat2D, 'constant', 'false')
write_image(ImageAffinTrans, 'bmp', 0, './图片/0')
stop ()
完整标定畸变矫正程序:
cpp
* This program measures the length of scratches in world
* coordinates in a perspectively distorted image
*3.外参-畸变图像校正-cameracal -调正了第一个图作为外参pose
*set_origin_pose(PoseCalib,0,0,0.003,PoseNewOrigin) 因为首张图已经被调整 因此该处dx dy 为0
*************************************************************1.初始化******************************************************************************
* 关闭窗口
dev_close_window ()
* 更新程序计数器,更新变量,更新图形窗口
dev_update_off ()
* 设置区域填充模式
dev_set_draw ('margin')
* 读取图像
read_image (Image, '图片/1')
* 获取图像类型,宽度,高度,缓存数据
get_image_pointer1 (Image, Pointer, Type, Width, Height)
* 打开窗口
dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle1)
* 设置字体信息
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
* 显示图像
dev_display (Image)
* 右下角显示运行字样字符串
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
* 1.内参标定 CamParam, PoseCalib
gen_self_Campar_and_PoseOrigin (WindowHandle1, Height, Width,\
CamParam, PoseCalib, CalibDataID)
stop()
*2.单像素对应距离 DistanceOnePixel
gen_self_DistanceOnePixel (PoseCalib, CamParam, PoseNewOrigin,\
DistanceOnePixel)
*3.求偏离值 把图像移动到正中间!
gen_self_FinalPose (WindowHandle1, CamParam, PoseNewOrigin, \
Width, Height, DistanceOnePixel, PoseCalib, PoseNewOriginFinal)
*4.map 消除径向畸变和视角畸变
read_image (ImagePespective, '图片/1')
*内参 CamParam,
* 外参 PoseNewOriginFinal,
*图像的宽度和高度, 像素Width, Height, Width, Height,
*单像素对应距离DistanceOnePixel 8.11503e-05
* DistanceOnePixel:=0.000 08 29788 0.08mm 1
gen_image_to_world_plane_map(Map1, CamParam, PoseNewOriginFinal, Width, Height, \
Width, Height,DistanceOnePixel, 'bilinear')
DistanceOnePixel:=0.0000828126
write_object(Map1, 'Map1.obj')
*3.83674e-05
*0.0000383674
read_object(Map1, 'Map1.obj')
*5.验证 和 测试 !
for Index := 1 to 1 by 1
read_image(Image1, '图片/6')
* 在这里对原始图像 Image1, 进行畸变矫正,ImageMapped1。
* 不失真的图
map_image(Image1,Map1, ImageMapped1)
*364 30mm 1像素 0.08mm
* 2像素 1280 1024 2560 *2000=500万像素
distance_pp(452 ,454 , 452 ,818, Distance)
*误差 0.2mm误差
*0.0302043
* X:=Distance*DistanceOnePixel
*验证精度是否足够
dev_get_window(WindowHandle)
* dev_open_window (0, 0, Width/2, Height/2, 'black', WindowHandle3)
dev_display(ImageMapped1)
column:=459
dev_set_color('blue')
dev_set_line_width(3)
*调正 ----验证 畸变矫正的效果
Genimage (ImageMapped1, Image, ImageAffinTrans, WindowHandle1)
dev_clear_window()
dev_display(ImageAffinTrans)
gen_contour_polygon_xld (Polygon, [452,452], [column,column+0.030/DistanceOnePixel])
dev_set_color('red')
dev_set_line_width(1)
gen_cross_contour_xld(Cross1, 451, column, 46, 0.785398)
gen_cross_contour_xld(Cross2, 451, column+0.030/DistanceOnePixel, 46, 0.785398)
disp_message (WindowHandle, '30cmm', 'window', 205, 195, 'red', 'false')
dev_display (Polygon)
dev_display (Cross1)
dev_display (Cross2)
disp_continue_message (WindowHandle, 'black', 'true')
stop()
endfor
三大函数
* 1.内参标定 CamParam, PoseCalib
cpp
* read_cam_par ('cam.dat', CamParam)
* 标定文件名
CaltabName := 'caltab_30mm.descr'
* [Focus,Kappa,Sx,Sy,Cx,Cy,Width,Height]
StartCamPar := [0.008, 0, 4.8e-006, 4.8e-006, 640, 512, 1280, 1024]
*创建标定数据模型
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*设置相机类型并初始化标定数据模型里的摄像机内部参数
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
*为校正模型指定校正文件
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
NumImages := 12
list_image_files('./图片', 'default', [], ImageFiles)
for i := 0 to NumImages by 1
*读取图像
read_image (Image, ImageFiles[i])
*显示图像
dev_display (Image)
gen_rectangle1(Rectangle, 1, 1, 1024,1280)
reduce_domain(Image, Rectangle, ImageReduced1)
min_max_gray ( ImageReduced1, Image, 5, Min, Max, Range)
scale_image (Image, ImageScaled, 255 / Range, -Min * 255 / Range)
*获取校正板内边框以内的区域
find_caltab (ImageScaled, Caltab, CaltabName, 3, 112, 5)
*设置输出对象显示颜色
dev_set_color ('green')
*显示校正板内边框以内的区域
dev_display (Caltab)
*提取出图像中MARK点的位置并计算出摄像机外部参数
find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar, \
128, 10, 18, 0.9, 15, 100, RCoord, CCoord, StartPose)
*设置输出对象显示颜色
dev_set_color ('red')
*显示MARK点的位置
disp_circle (WindowHandle1, RCoord, CCoord, gen_tuple_const(|RCoord|,2.5))
dev_set_part (0, 0, Height-1, Width-1)
*收集观察数据
set_calib_data_observ_points (CalibDataID, 0, 0, i, RCoord, CCoord, 'all', StartPose)
* stop()
endfor
dev_update_time ('on')
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
*开始校正摄像机 [-2.76405e-05, -7.47002e-06, 0.0684394, 10.0298, 5.70187, 358.571, 0]
calibrate_cameras (CalibDataID, Error)
*获取优化以后的摄像机内部参数
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
******保存相机内参,且该函数只能保存内参***
write_cam_par(CamParam,'cam.dat')
****************************
*获取优化以后的校正对象姿势,相对于当前参考相机。
get_calib_data (CalibDataID, 'calib_obj_pose', [0,0], 'pose', PoseCalib)
write_pose(PoseCalib, 'poseOrigin.dat')
return ()
*2.单像素对应距离 DistanceOnePixel
cpp
*矫正后再测量
*选取两个像素点 2个点求距离
Image_X1:=100
Image_Y1:=100
Distance_XY:=500
Image_X2:=Image_X1+Distance_XY
Image_Y2:=Image_Y1+Distance_XY
gen_cross_contour_xld(Cross1, Image_X1, Image_Y1, 46, 0.785398)
gen_cross_contour_xld(Cross2, Image_X2, Image_Y2, 76, 0.785398)
*考虑标定板厚度的影响 PoseNewOrigin在这里
*[0.0209422, -0.0257558, 0.56891, 7.69086, 10.9034, 359.249, 0]
* 0 旋转轴种类
* pose1:=[0,0,0.003,0,0,0,0]
* pose_compose(PoseCalib,pose1,PoseCompose1)
* 0.003 标定板的厚度 3mm 0.003m
set_origin_pose(PoseCalib,0,0,0,PoseNewOrigin)
*将像素坐标转化为世界坐标(单位m)
image_points_to_world_plane(CamParam, PoseNewOrigin, Image_Y1, Image_X1, 'm', World_X1, World_Y1)
image_points_to_world_plane(CamParam ,PoseNewOrigin, Image_Y2, Image_X2, 'm', World_X2, World_Y2)
*******************************************************************************************
*计算世界坐标距离
distance_pp(World_Y1, World_X1, World_Y2, World_X2, DistanceWorld)
*计算像素坐标
distance_pp(Image_X1,Image_Y1,Image_X2,Image_Y2,DistanceImage)
*每个像素对应的世界坐标距离
DistanceOnePixel:=DistanceWorld/DistanceImage
return ()
*3.求偏离值 把图像移动到正中间!
cpp
WindowHandle1Out := WindowHandle1
disp_3d_coord_system (WindowHandle1Out, CamParam, PoseNewOrigin, 0.05)
*调整世界坐标到中心偏移量
OffSetX:=(Width/2)*DistanceOnePixel
OffSetY:=(Height/2)*DistanceOnePixel
*
*************************************************************3.图像转换****************************************************************************
*这张图 是 世界坐标系的参考姿态图 ,与外参demo 中游标卡尺的坐标系是类似的作用
*调整相机外参
*假如需要重新拍一张图 ,这个图 与世界坐标系 的姿态一致。由于是平面,不考虑 x y 的变化,只考虑z方向角度的变化。
*所以这里是第5个值 需要替换 ,RZ
*PoseCalibRot 是机器人的坐标系
set_origin_pose (PoseNewOrigin, -OffSetX, -OffSetY, 0, PoseNewOriginFinal)
return ()