九点标定
原理:简单来理解,假如有人告诉你A坐标系(例如相机图像坐标系)的一点(x=10,y=20像素),在B坐标系(例如机械手所在坐标系)里看到的是(x1=2,y1=4), 接下来,他问你如果是(x'=20,y'=30)在B里看到的是多少呢?
下面分别提供Halcon、OpenCV和Accord的方法,实际测试了Halcon和Accord的方法,其结果一致。
Halcon 的方法:
*已知A坐标系的9个点 机械坐标
Ax:=[2,2.05,2.1,2,2.05,2.13,2,2.05,2.14]
Ay:=[2,2,2,2.1,2.1,2.1,2.2,2.2,2.2]
*待识别的B坐标点 图像坐标,和上面的A坐标系点一一对应
Bx:=[1000,1050,1100,1000,1050,1130,1000,1050,1140]
By:=[1000,1000,1000,1100,1100,1110,1200,1200,1200]
*得到目标变换矩阵HomMat2D
vector_to_hom_mat2d (Bx, By, Ax, Ay, HomMat2D)
*保存变换矩阵
serialize_hom_mat2d (HomMat2D, SerializedItemHandle)
open_file ('my_vector.mat', 'output_binary', FileHandle)
fwrite_serialized_item (FileHandle, SerializedItemHandle)
close_file (FileHandle)
stop ()
*读取变换矩阵,测试
open_file ('my_vector.mat', 'input_binary', FileHandle)
fread_serialized_item (FileHandle, SerializedItemHandle)
deserialize_hom_mat2d (SerializedItemHandle, HomMat2D_9p)
close_file (FileHandle)
*输入测试的图像坐标,得到机械坐标Qx,Qy
tx:=1050
ty:=1000
affine_trans_point_2d (HomMat2D_9p, tx, ty, Qx, Qy)
OpenCV的方法:
demo 测试
float[] camX = new[] { 150f, 150f, 150f, 340f, 340f, 340f, 520f, 520f, 520f };
float[] camY = new[] { 160f, 320f, 470f, 160f, 320f, 470f, 160f, 320f, 470f };
float[] robX = new[] { 2 + 1.5f, 2 + 1.50f, 2 + 1.50f, 2 + 3.40f, 2 + 3.40f, 2 + 3.40f, 2 + 5.20f, 2 + 5.20f, 2 + 5.20f };
float[] robY = new[] { 1.60f, 3.20f, 4.70f, 1.60f, 3.20f, 4.70f, 1.60f, 3.20f, 4.70f };
PointF test = new PointF(200, 400);
int cnt = camX.Length;
for (int i = 0; i < cnt; i++)
{
points_camera[i] = new PointF(camX[i], camY[i]);
points_robot[i] = new PointF(robX[i], robY[i]);
}
//OpenCV 的方法
//Mat warpMat = CvInvoke.EstimateAffine2D(points_camera, points_robot);
//var k = warpMat.ToImage<Gray, float>();
//Matrix<double> matrix = new Matrix<double>(2, 3, warpMat.DataPointer).Transpose(); //3x2
Accord方法:
public static float[] Calib(PointF[] camera, PointF[] physic)
{
var cnt = camera.Length;
PointF[] points_camera = new PointF[cnt];
PointF[] points_robot = new PointF[cnt];
for (int i = 0; i < cnt; i++)
{
points_camera[i] = new PointF((float)camera[i].X, (float)camera[i].Y);
points_robot[i] = new PointF((float)physic[i].X, (float)physic[i].Y);
}
// Set a fixed seed to transform RANSAC into a deterministic algorithm
Accord.Math.Random.Generator.Seed = 0;
Accord.Imaging.RansacHomographyEstimator est = new Accord.Imaging.RansacHomographyEstimator(0.01, 0.99);
var matrix = est.Estimate(points_camera, points_robot);
return matrix.Elements;
}
public static PointF Calc(float[] elements, PointF target)
{
Accord.Imaging.MatrixH matrix = new Accord.Imaging.MatrixH(elements);
var tranformed = matrix.TransformPoints(new Accord.Imaging.PointH(target.X, target.Y));
var x = tranformed[0].X;
var y = tranformed[0].Y;
return new PointF(x, y);
}