手眼标定(九点法)

一、用途

为了确定像素坐标系和空间机械手坐标系的坐标转化关系,我们介绍一种工业上使用广泛的二维手眼标定方法——九点法。在实际运动中,相机检测到目标在图像中的像素位置后,通过标定好的坐标转换矩阵,将相机的像素坐标,变换到机械手的空间坐标系中,然后根据机械手坐标系,计算出各个电机该如何运动,从而控制机械手到达指定位置。

根据相机的装载位置分为
不在手上(eye-to-hand):相机固定在一个地方,机械手的运动不会带着相机一起移动。
在手上(eye-in-hand):相机安装在机械手上,随着机械手一起移动。较为常用。

九点标定的作用:

1、求解x和y方向的分辨率

2、求解图像坐标到x,y坐标的仿射变换矩阵

3、根据变换矩阵来实现像素坐标与实际坐标的转换

二、坐标系的转换

三、标定的步骤

1. 放置标定板:在拍摄区域内固定放置一个已知标定板,标定板上有一系列已知大小的点或者二维码,一般使用棋盘格。

2. 拍摄图像:使用摄像机或者相机对标定板进行拍摄,保证标定板占满图像,并尽量多角度、多位置进行拍摄。

3. 提取角点:从拍摄的图像中利用图像处理算法自动或者手动提取出标定板上的角点,这些角点就是用来标定的关键点。

4. 设定初始估计参数:根据相机的参数和标定板的尺寸,设定一个初始的相机姿态参数的估计值。

5. 优化参数:使用数学优化方法,将拍摄图像中提取的角点与实际标定板上的角点进行匹配,使用这些匹配点对来优化相机姿态参数的估计值,使得投影误差最小。

6. 重复迭代:使用优化后的参数再次提取拍摄图像中的角点,然后再次优化相机姿态参数的估计值,直到优化结果收敛。

7. 标定结果评估:计算标定误差,判断标定结果的准确性和稳定性。 8. 应用标定参数:将标定得到的相机参数应用于后续的图像处理、计算机视觉等应用中

四、关于图像分辨率求解

这里使用最简单得线性标定,即不考虑相机的畸变而只考虑空间坐标转换。每个坐标点有X,Y两个变量,可列两个方程,相机内参有5个未知数,外参平移和旋转各3个,共有11个变量,因此至少需要6个特征点来求解。

经过图像处理,我们可以得到九个点的图像上的坐标,然后按照从左到右,从上到下的规律排好,利用这些点去计算分辨率

//pt:点集;hj:行距;lj:列距
bool CvGetClibrateData(CvPoint *pt, double hj, double lj, double &dx, double &dy)
{
	//pt的排列原则从左到右,从上到下,可以使用sort函数排序
	//具体的sort就不写了,感兴趣的同学自己研究一下,在这里我默认他排好序了
	//pt的排序结果
	// 0 1 2
	// 3 4 5
	// 6 7 8
    //因此接下来的求解方法全是数学问题
	//x方向分辨率
	dx = (pt[1].x - pt[0].x) + (pt[2].x - pt[1].x);
	dx += (pt[4].x - pt[3].x) + (pt[5].x - pt[4].x);
	dx += (pt[7].x - pt[6].x) + (pt[8].x - pt[7].x);
	dx = dx / (6 * lj);
 
	//y方向分辨率
	dy = (pt[3].y - pt[0].y) + (pt[6].y - pt[3].y);
	dy += (pt[4].y - pt[1].y) + (pt[7].y - pt[4].y);
	dy += (pt[5].y - pt[2].y) + (pt[8].y - pt[5].y);
	dy = dy / (6 * hj);
    return true;
}

五、关于仿射矩阵的作用

从一个坐标系到另一个坐标系的变换,通常使用仿射矩阵。使用Opencv的函数

Mat*  getAffineTransform( const CvPoint2D32f* src,const CvPoint2D32f*  dst, CvMat*  map_matrix );
src:输入图像的三角形顶点坐标。
dst:输出图像的相应的三角形顶点坐标。
map_matrix:指向2×3输出矩阵的指针。

旋转矩阵

Mat cv::getRotationMatrix2D(Point2f center,double angle,double 	scale )		
参数:
center	旋转图像所要围绕的中心点
angle	旋转的角度. 在OpenCV中正角度是逆时针的
scale	缩放因子,可选的

这两个函数就是已知图像上三点坐标,和XY坐标系中对应的三点坐标,然后求解一个变换矩阵。

参考:

仿射变换 — OpenCV 2.3.2 documentation

手眼标定(九点法)_九点标定_MrLi1的博客-CSDN博客

工业图像处理实战--九点标定法_PangCoder的博客-CSDN博客

手眼标定_全面细致的推导过程_坐标转换和相机内参的关系_骑士——永不止步的博客-CSDN博客

以下是九点手眼标定的完整Python代码: ```python import numpy as np import cv2 # 定义棋盘格行列数 rows = 6 cols = 8 # 设置世界坐标系中棋盘格点的三维坐标 objp = np.zeros((rows * cols, 3), np.float32) objp[:, :2] = np.mgrid[0:rows, 0:cols].T.reshape(-1, 2) * 25 # 存储棋盘格角点的像素坐标 imgpoints = [] # 存储棋盘格角点的世界坐标 objpoints = [] # 加载图像 img = cv2.imread('image.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 查找棋盘格角点 ret, corners = cv2.findChessboardCorners(gray, (rows, cols), None) # 如果找到角点,则加入到imgpoints和objpoints中 if ret == True: objpoints.append(objp) corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) imgpoints.append(corners2) # 绘制角点并显示图像 img = cv2.drawChessboardCorners(img, (rows, cols), corners2, ret) cv2.imshow('img', img) # 进行相机标定 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) # 打印相机内参和畸变系数 print("相机内参:") print(mtx) print("畸变系数:") print(dist) # 保存相机内参和畸变系数 np.savez('calibration.npz', mtx=mtx, dist=dist) cv2.waitKey(0) cv2.destroyAllWindows() ``` 注意,以上代码中的`criteria`变量未定义。它是一个用于角点精细化的条件参数,可以设置为: ```python criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) ``` 另外,为了使用该代码,需要将`image.jpg`替换为你的棋盘格图像文件路径。执行完代码后,将会输出相机内参和畸变系数,并保存为`calibration.npz`文件。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值