13:图像处理—畸变矫正详解

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 ()
相关推荐
freyazzr3 分钟前
Leetcode刷题 | Day51_图论03_岛屿问题02
数据结构·c++·算法·leetcode·深度优先·图论
passionSnail7 分钟前
《MATLAB实战训练营:从入门到工业级应用》工程实用篇-自动驾驶初体验:车道线检测算法实战(MATLAB2016b版)
算法·matlab·自动驾驶
2301_807611498 分钟前
126. 单词接龙 II
c++·算法·leetcode·深度优先·广度优先·回溯
CHNMSCS31 分钟前
PyTorch_张量基本运算
人工智能·pytorch·python
时而支楞时而摆烂的小刘33 分钟前
CUDA、pytorch、配置环境教程合集
人工智能·pytorch·python
试着38 分钟前
【AI面试准备】元宇宙测试:AI+低代码构建虚拟场景压力测试
人工智能·低代码·面试
Frankabcdefgh1 小时前
颠覆者DeepSeek:从技术解析到实战指南——开源大模型如何重塑AI生态
人工智能·科技·深度学习·自然语言处理·职场和发展
Phoebe鑫1 小时前
数据结构每日一题day15(链表)★★★★★
算法
奋进的小暄1 小时前
数据结构(4) 堆
java·数据结构·c++·python·算法
程序员陆通2 小时前
MCP协议与Dify集成教程
人工智能·ai编程