内容

  • 1.背景介绍
    • 1.1 问题
    • 1.2 思路
  • 2.操作流程

1.背景介绍

  2D视觉机器人指的是机器人通过2D相机提供的视觉信息,完成某些实际的功能。
  下面以眼在手上标定为例:

  上图中,相机③被固定在机械臂末端②标定板④即之后的工作平面,为了做手眼标定在工作平面上放一个标定板。
  标定过程中标定板④放在固定位置,由上图可知,标定板④基底①的相对位置不变,然后通过示教器控制机械臂带着相机在不同的位姿下对标定板④进行拍照,拍照的过程中保存当前拍到的标定板图片以及记录图片对应示教器上的世界坐标。
  眼在手上标定的目的是求出相机③坐标系到机械臂末端②坐标系的变换矩阵。

  ①为什么需要手眼标定

  假设以物体识别目标进行抓取为例,在工作平面④上面有一个方形物体⑤,装在机械臂末端上面的2D光学相机会对物体进行拍照捕捉,识别后的结果是给出当前物体⑤在相机成像平面内的像素坐标,然后要用机械臂去抓取该物体⑤。但得出的物体⑤的坐标信息是以相机坐标系为基准的,而输入给机械臂的信息是以机械臂基底①坐标系为基准的,这时候就需要将物体⑤的坐标信息转换到以机械臂基底①为基准的参数。

1.1 问题

  PS:关于上面例子中的问题,不是本文的重点,是通过三个4*4的矩阵相乘得到物体⑤在基底坐标系下的坐标,后面的博文会记录(https://blog.csdn.net/qq_45445740/article/details/123567627?spm=1001.2014.3001.5501),这里暂时不提。之前我一直困惑为什么2D相机没有深度信息,是怎么得到z轴方向的参数的?
  ②为什么需要相机标定

  因为物体⑤在相机③中的坐标是在相机成像平面内的一个2维坐标信息,而上面说的三个4*4的矩阵相乘是3维的,产生了新的问题:根据相机识别到物体的2维信息,如何转换为3维的目标信息?

1.2 思路

  相机标定是得到相机的内参矩阵和畸变系数。
  相机的内参矩阵

  其中,f表示焦距,cx表示使用像素来描述x轴方向焦距的长度,cy表示使用像素来描述y轴方向焦距的长度。一般来说,cx=w/2cy=h/2,w表示相机拍摄照片的像素宽度,h表示像素高度。

  根据视频中up主的思路,有了上面的相机内参矩阵,就可以得到角点在相机坐标系中的三维坐标。前提:需要假设物体⑤在工作平面上,且物体有固定的厚度,也就保证了物体的上表面中所有的点在z轴方向上到相机的距离是相同的。

  通过上面的公式求出X和Y。式中内参矩阵是标定得到已知的,Z是固定值,在代码中假设标定板放在世界坐标系中Z=0的平面上,x和y是角点的像素坐标也是已知值。

代码:https://blog.csdn.net/qq_45445740/article/details/122339711

2.操作流程

  • ①将相机固定在机械臂末端,调整好焦距和曝光,固定好棋盘格标定板,控制机器臂在不同姿态下对标定板拍照,拍摄的每张照片都要保证整个标定板都在相机的视野内,至少13张标定图片。
  • ②在程序中加载每张标定图片
  • ③首先提取每张照片的角点,使用cv::findChessboardCorners()函数提取角点,这里的角点专指的是标定板上的内角点,并且这些角点与标定板的边缘不接触。
// 使用该API对每张图片是否提取到角点进行判断
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners,int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );// Image:传入拍摄的棋盘图Mat图像,必须是8位的灰度或者彩色图像
// patternSize:每个棋盘图上内角点的行列数,一般情况下,行列数不要相同,便于后续标定程序识别标定板的方向
// corners:用于存储检测到的内角点图像坐标位置,一般用元素是Point2f的向量来表示:vector<Point2f> image_points_buf;
// flage:用于定义棋盘图上内角点查找的不同处理方式,有默认值
  • ④为了提高标定精度,需要在初步提取的角点信息上进一步提取亚像素信息,降低相机标定偏差,使用cv::find4QuadCornerSubpix()函数,这个方法是专门用来获取棋盘图上内角点的精确位置的。
// 查找棋盘角的亚像素精确位置
CV_EXPORTS_W bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size );// img:输入的Mat矩阵,最好是8位灰度图像,检测效率更高
// corners:初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示vector<Point2f/Point2d> iamgePointsBuf;
// region_size:角点搜索窗口的尺寸;
  • ⑤检查识别到的角点方向是否一致。由于在建立棋盘格上的三维坐标系的时候,我们默认是从棋盘格左上角到右下角建立的,如果识别反了,则会有个别图片棋盘格识别的角点和输入的棋盘格三维坐标对应不上。
  • ⑥在棋盘标定图上绘制找到的内角点(非必须,仅为了显示),使用cv::drawChessboardCorners()函数。
// 该函数绘制单个棋盘角,如果棋盘没有被发现,则绘制为红色的圆圈,如果棋盘被发现,则绘制为与线连接的彩色角。
CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize,InputArray corners, bool patternWasFound );// image:8位灰度或者彩色图像
// patternSize:每张标定棋盘上内角点的行列数
// corners:初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d> iamgePointsBuf;
// patternWasFound:标志位,用来指示定义的棋盘内角点是否被完整的探测到,true表示别完整的探测到,函数会用直线依次连接所有的内角点,作为一个整体,false表示有未被探测到的内角点,这时候函数会以(红色)圆圈标记处检测到的内角点;
//                  patternWasFound=ture时,依次连接各个内角点
//                  patternWasFound=false时,以(红色)圆圈标记处角点位置
  • ⑦开始相机标定,准备好cv::calibrateCamera()函数所需要的参数,因为第一个参数需要的是所有标定图片上所有检测到的角点在世界坐标系下的三维坐标,而这是2D相机,没有深度信息,所以我们假设标定板放在世界坐标系中 z=0 的平面上,即Z轴方向为0。
CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,InputArrayOfArrays imagePoints, Size imageSize,InputOutputArray cameraMatrix, InputOutputArray distCoeffs,OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) );// objectPoints:为世界坐标系中的三维点。在使用时,应该输入一个三维坐标点的向量的向量,即vector<vector<Point3f>> object_points。需要依据棋盘上单个黑白矩阵的大小,计算出(初始化)每一个内角点的世界坐标。
// imagePoints:为每一个内角点对应的图像坐标点。和objectPoints一样,应该输入vector<vector<Point2f>> image_points_seq形式的变量;
// imageSize:为图像的像素尺寸大小,在计算相机的内参和畸变矩阵时需要使用到该参数;
// cameraMatrix:为相机的内参矩阵,输入一个Mat cameraMatrix即可,如Mat cameraMatrix=Mat(3,3,CV_32FC1,Scalar::all(0));
// distCoeffs:为畸变矩阵,输入一个Mat distCoeffs=Mat(1,5,CV_32FC1,Scalar::all(0))即可;
// rvecs:为旋转向量,应该输入一个Mat类型的vector,即vector<Mat>rvecs;
// tvecs:为位移向量,和rvecs一样,应该为vector<Mat> tvecs;
// flags:为标定时所采用的算法。有如下几个参数:
//              CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,u0,v0的估计值。否则的话,将初始化(u0,v0)图像的中心点,使用最小二乘估算出fx,fy。
//              CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。
//              CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy将会被忽略。只有fx/fy的比值在计算中会被用到。
//              CV_CALIB_ZERO_TANGENT_DIST:设定切向畸变参数(p1,p2)为零。
//              CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:对应的径向畸变在优化中保持不变。
//              CV_CALIB_RATIONAL_MODEL:计算k4,k5,k6三个畸变参数。如果没有设置,则只计算其它5个畸变参数。
//              第九个参数criteria是最优迭代终止条件设定。/*在使用该函数进行标定运算之前,需要对棋盘上每一个内角点的空间坐标系的位置坐标进行初始化,
标定的结果是生成相机的内参矩阵cameraMatrix、相机的5个畸变系数distCoeffs,另外每张图像都会生成属于自己的平移向量和旋转向量。*/
  • ⑧对相机标定的结果进行评价,方法是通过相机标定得到的摄像机内外参数,然后对空间的三维点进行重新投影计算,得到空间三维点在图像上新的投影点的坐标,通过cv::projectPoints()函数计算得到新的二维投影点,然后通过cv::norm()计算新的投影点和旧的投影点之间的偏差,偏差越小,标定结果越好。
CV_EXPORTS_W void projectPoints( InputArray objectPoints,InputArray rvec,InputArray tvec,InputArray cameraMatrix, InputArray distCoeffs,OutputArray imagePoints,OutputArray jacobian = noArray(),double aspectRatio = 0 );// objectPoints:物体点的坐标,为3xN或者Nx3的矩阵,这儿N是视图中的所有所有点的数目。
// rvec:旋转向量,1x3或者3x1。
// InputArray tvec:平移向量,1x3或者3x1。
// cameraMatrix:摄像机内参数矩阵。
// distCoeffs:形变参数向量,4x1或者1x4,为[k1,k2,p1,p2]。如果是NULL,所有形变系数都设为0。
// imagePoints:输出数组,存储图像点坐标。大小为2xN或者Nx2,这儿N是视图中的所有点的数目。
// jacobian = noArray():默认参数,Nx10矩阵,从上到下分为4个部分。
// aspectRatio = 0 :默认参数,关于形变系数的图像上点的导数,Nx4矩阵。
CV_EXPORTS_W double norm(InputArray src1, InputArray src2,int normType = NORM_L2, InputArray mask = noArray());// src1:输入矩阵1
// src2:输入矩阵2
// normType:为范数的类型,默认的是L2范数
  • ⑨开始眼在手上的标定,通过cv::calibrateHandEye()函数,四个输入,两个输出,其中R_gripper2base和t_gripper2base由示教器获得,即机械臂末端到机械人基底的旋转矩阵和平移向量;R_target2cam和t_target2cam可通过相机标定中的输出rvecs和tvecs得到。rvecs表示旋转向量,可通过cv::Rodrigues()将旋转向量转为旋转矩阵R_target2cam,tvecs就等于t_target2cam平移向量。
#include <opencv2/calib3d.hpp>cv::calibrateHandEye(InputArrayOfArrays R_gripper2base,InputArrayOfArrays t_gripper2base,InputArrayOfArrays R_target2cam,InputArrayOfArrays t_target2cam,OutputArray R_cam2gripper,OutputArray t_cam2gripper,HandEyeCalibrationMethod method = CALIB_HAND_EYE_TSAI
)   // R_gripper2base:描述为将在机械臂末端坐标系(夹爪坐标系,gripper)中的点转换到机器人基坐标系(base)中。表示机械臂末端坐标系(夹爪坐标系,gripper)到机器人基坐标系(base)的变换矩阵中的旋转矩阵部分,包含了3x3的旋转矩阵和3x1的旋转向量。
// t_gripper2base:和R_gripper2base同理,表示的是平移向量的部分。
// R_target2cam:描述为将在目标标定板坐标系(target)中的点转换到相机坐标系(cam)中。表示目标标定板坐标系(target)到相机坐标系(cam)的变换矩阵中的旋转矩阵部分,包含了3x3的旋转矩阵和3x1的旋转向量。
// t_target2cam:和R_target2cam同理,表示的是平移向量的部分。
// R_cam2gripper描述为将在相机坐标系(cam)中的点转换到机械臂末端坐标系(夹爪坐标系,gripper)中。表示相机坐标系(cam)到机械臂末端坐标系(夹爪坐标系,gripper)的变换矩阵中的旋转矩阵部分,包含了3x3的旋转矩阵和3x1的旋转向量。
// t_cam2gripper:和R_cam2gripper同理,表示的是平移向量的部分。
// method = CALIB_HAND_EYE_TSAI:有五种计算方法,一般选择TSAI。
  • ⑩最终得到R_cam2gripper和t_cam2gripper,拼接成相机到机械臂末端的变换矩阵。

关于手眼标定结果的应用:
https://blog.csdn.net/qq_45445740/article/details/123567627?spm=1001.2014.3001.5501
感谢视频讲解:https://www.bilibili.com/video/BV17K4y1u7iJ?spm_id_from=333.1007.top_right_bar_window_history.content.click

(二)2D视觉机器人的手眼标定流程记录相关推荐

  1. SCARA四轴机器人eye-to-hand手眼标定(九点标定)

    SCARA四轴机器人eye-to-hand手眼标定(九点标定) 9点法标定是工业上使用广泛的二维手眼标定,它分为eye_in_hand和eye_to_hand两种.在做项目时,用到的是eye-to-h ...

  2. scare机器人如何手眼标定_标定系列一 | 机器人手眼标定的基础理论分析

    旷视MegMaster机器人系列是旷视自主研发的一系列AI智能机器人硬件设备,基于旷视全球领先的人工智能算法及机器人技术,可实现搬运.分拣.托举.存储等功能,被广泛应用于物流仓储.工厂制造等场景.旷视 ...

  3. 四轴平面机器人的手眼标定

    四轴平面机器人的手眼标定 介绍 在实际的机器人应用中,通常会给机器人配备视觉传感器,视觉传感器用于感知周围环境.但是,通过视觉传感器获取的场景坐标是基于视觉坐标系下的,机器人并不能直接使用,要获取机器 ...

  4. scare机器人如何手眼标定_基于视觉伺服的工业机器人系统研究(摄像机标定、手眼标定、目标单目定位)...

    击上方"新机器视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 标定技术 常见的机器人视觉伺服中要实现像素坐标与实际坐标的转换,首先 ...

  5. scare机器人如何手眼标定_Epson四轴机器人的手眼标定(原理并附上halcon代码)...

    关于机器人视觉的手眼标定的原理,勇哥先放上一些教程资源: 众所周知,目前机器视觉项目,很大一部分都是引导机器人去取料 放料等工作. 这个里面就有个非常重要的工作要做.就是将相机的坐标系  映射到机器人 ...

  6. 手眼标定详述(坐标系介绍,二维、三维的手眼标定方法@九点法、AX=XB)

    手眼标定 1. 写在前面 2. 手眼标定基本分类 2.1 手眼标定坐标系 2.2 眼在手外(EYE TO HEAD) 2.3 眼在手上(EYE IN HEAD) 3. 九点法(二维)- 算法实现流程 ...

  7. Amy-Tabb机器人世界手眼标定(2、实验结果)

    四轴机器人手眼标定课设_HITSZ阿星的博客-CSDN博客 上面这个文章已经把环境搭配好了,接下来参考论文对试验进行复现 build后用终端输入命令 /home/jqx/RWHEC-Tabb-Ahma ...

  8. (已修正精度 1mm左右)Realsense d435i深度相机+Aruco+棋盘格+OpenCV手眼标定全过程记录

    文章目录 2023.5更新 ------------------下面为原文--------------------- 一.前期准备 1.1 手眼标定原理 1.2 Aruco返回位姿的原理 1.3 生成 ...

  9. Amy-Tabb机器人世界手眼标定(3、论文分析)

    目录 3.误差 3.1.平均旋转误差er 3.2.平均平移误差 3.3.平均组合旋转和平移误差ec 3.4.重投影均方根误差(rrmse) 3.5.重建精度误差 (rae) 3.6.模拟数据集里的误差 ...

最新文章

  1. java别踩白块_java别踩白块(基础功能)
  2. ‘pip 安装第三方库速度太慢’的解决办法
  3. WinAPI: PolyBezier - 绘制贝塞尔线
  4. python海伦公式_少儿编程Python第2课-if语句(海伦公式)
  5. python运维开发常用模块(四)文件对比模块difflib
  6. java capacity_关于Java中StringBuffer的capacity问题
  7. Java并发编程—volatile关键字(保证变量的可见性、有序性机制)
  8. cstring 不明确_股价不可预测明确时间点的涨跌
  9. 分割字符串,字符串去除空格
  10. 《现在的泪,都是当年脑子进的水》读书笔记
  11. Boundary Representations
  12. Mysql:实战2000W条数据实现全文检索
  13. 没有项目经验,如何书写漂亮的简历?
  14. 全球及中国应用商店优化ASO工具行业竞争现状与发展战略规划研究报告2022-2028年
  15. 计算机考研面试有英语听力吗,复试英语听力与口语应该这样准备
  16. 基于 HTML5 Canvas 的简易 2D 3D 编辑器
  17. 实验三:基于A*算法的迷宫
  18. carplay是否可以用安卓系统_carplay能连接安卓手机吗
  19. .net简单web开发
  20. 【笔试真题】字节跳动产品岗笔试主观题解析!!

热门文章

  1. java使用poi操作word实现电子签章
  2. oppo r9plus 无限制重启前的日志。
  3. Golang 控制台百行代码贪吃蛇小游戏
  4. FPGA初学记录——数字时钟系统搭建(上)
  5. Elasticsearch——Boolean query
  6. 003_HDFS详解
  7. android4.0.3源码之硬件gps简单移植
  8. 知识博主要知识变现赚钱,是先做流量或是先做课程?
  9. Prolog 列表练习 2
  10. 笔试ing..不断记录耶~