VisionPro二开之九点标定 方式1: CogCalibNPointToNPointTool
方式2 安装
平移九点标定 using System ; using System. Collections. Generic ; using MathNet. Numerics. LinearAlgebra ; namespace 平移标定的数学公式{ public class CoordinateCalibration { // 存储标定点对 private List< ( PointF image, PointF robot) > calibrationPoints= new List< ( PointF, PointF) > ( ) ; // 仿射变换参数 [a, b, c; d, e, f] private Matrix< double > transformMatrix; public struct PointF { public float X; public float Y; public PointF ( float x, float y) { X= x; Y= y; } } // 添加标定点 public void AddCalibrationPoint ( PointF imagePoint, PointF robotPoint) { calibrationPoints. Add ( ( imagePoint, robotPoint) ) ; } // 执行标定计算 public bool CalculateCalibration ( ) { if ( calibrationPoints. Count< 3 ) { Console. WriteLine ( "至少需要3个标定点" ) ; return false ; } // 构建矩阵方程 A * params = B // 参数矩阵 params = [a, b, c, d, e, f]^T int n= calibrationPoints. Count; Matrix< double > A= Matrix< double > . Build. Dense ( 2 * n, 6 ) ; Matrix< double > B= Matrix< double > . Build. Dense ( 2 * n, 1 ) ; for ( int i= 0 ; i< n; i++ ) { var ( image, robot) = calibrationPoints[ i] ; // 填充A矩阵 - X坐标相关行 A[ 2 * i, 0 ] = image. X; // x A[ 2 * i, 1 ] = image. Y; // y A[ 2 * i, 2 ] = 1 ; // 1 A[ 2 * i, 3 ] = 0 ; A[ 2 * i, 4 ] = 0 ; A[ 2 * i, 5 ] = 0 ; // 填充A矩阵 - Y坐标相关行 A[ 2 * i+ 1 , 0 ] = 0 ; A[ 2 * i+ 1 , 1 ] = 0 ; A[ 2 * i+ 1 , 2 ] = 0 ; A[ 2 * i+ 1 , 3 ] = image. X; // x A[ 2 * i+ 1 , 4 ] = image. Y; // y A[ 2 * i+ 1 , 5 ] = 1 ; // 1 // 填充B矩阵 B[ 2 * i, 0 ] = robot. X; B[ 2 * i+ 1 , 0 ] = robot. Y; } // 使用最小二乘法求解 try { // A * params = B => params = (A^T * A)^-1 * A^T * B var AtA= A. Transpose ( ) * A; var AtA_inv= AtA. Inverse ( ) ; var AtB= A. Transpose ( ) * B; var paramsVector= AtA_inv* AtB; // 转换为2x3变换矩阵 transformMatrix= Matrix< double > . Build. Dense ( 2 , 3 ) ; transformMatrix[ 0 , 0 ] = paramsVector[ 0 , 0 ] ; // a transformMatrix[ 0 , 1 ] = paramsVector[ 1 , 0 ] ; // b transformMatrix[ 0 , 2 ] = paramsVector[ 2 , 0 ] ; // c transformMatrix[ 1 , 0 ] = paramsVector[ 3 , 0 ] ; // d transformMatrix[ 1 , 1 ] = paramsVector[ 4 , 0 ] ; // e transformMatrix[ 1 , 2 ] = paramsVector[ 5 , 0 ] ; // f return true ; } catch ( Exception ex) { Console. WriteLine ( $"标定计算失败: { ex. Message } " ) ; return false ; } } // 图像坐标转机械手坐标 public PointF ImageToRobot ( PointF imagePoint) { if ( transformMatrix== null ) { throw new InvalidOperationException ( "尚未执行标定计算" ) ; } // 构建输入向量 [x, y, 1] Vector< double > input= Vector< double > . Build. Dense ( new [ ] { imagePoint. X, imagePoint. Y, 1.0 } ) ; // 计算输出 [X, Y] Vector< double > output= transformMatrix* input; return new PointF ( ( float ) output[ 0 ] , ( float ) output[ 1 ] ) ; } // 机械手坐标转图像坐标(逆变换) public PointF RobotToImage ( PointF robotPoint) { if ( transformMatrix== null ) { throw new InvalidOperationException ( "尚未执行标定计算" ) ; } // 仿射变换的逆变换需要计算矩阵的逆 Matrix< double > invTransform= Matrix< double > . Build. Dense ( 3 , 3 ) ; invTransform[ 0 , 0 ] = transformMatrix[ 0 , 0 ] ; invTransform[ 0 , 1 ] = transformMatrix[ 0 , 1 ] ; invTransform[ 0 , 2 ] = transformMatrix[ 0 , 2 ] ; invTransform[ 1 , 0 ] = transformMatrix[ 1 , 0 ] ; invTransform[ 1 , 1 ] = transformMatrix[ 1 , 1 ] ; invTransform[ 1 , 2 ] = transformMatrix[ 1 , 2 ] ; invTransform[ 2 , 0 ] = 0 ; invTransform[ 2 , 1 ] = 0 ; invTransform[ 2 , 2 ] = 1 ; try { var inv= invTransform. Inverse ( ) ; Vector< double > input= Vector< double > . Build. Dense ( new [ ] { robotPoint. X, robotPoint. Y, 1.0 } ) ; Vector< double > output= inv* input; return new PointF ( ( float ) output[ 0 ] , ( float ) output[ 1 ] ) ; } catch { Console. WriteLine ( "逆变换计算失败,可能矩阵不可逆" ) ; return new PointF ( 0 , 0 ) ; } } } } 二 使用 using System ; using System. Collections. Generic ; using System. ComponentModel ; using System. Data ; using System. Drawing ; using System. Linq ; using System. Text ; using System. Threading. Tasks ; using System. Windows. Forms ; namespace 平移标定的数学公式{ public partial class Form1 : Form { public Form1 ( ) { InitializeComponent ( ) ; } private void button1_Click ( object sender, EventArgs e) { var calibrator= new CoordinateCalibration ( ) ; // 添加9个标定点(示例数据,实际应用中需要真实测量) // 格式:(图像坐标X, 图像坐标Y), (机械手坐标X, 机械手坐标Y) calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 1588.7726f , 596.46368f ) , new CoordinateCalibration. PointF ( 140 , 10 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 2092.5125f , 601.88007f ) , new CoordinateCalibration. PointF ( 140 , - 10 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 2599.6616f , 608.51514f ) , new CoordinateCalibration. PointF ( 140 , - 30 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 1586.8936f , 1092.2368f ) , new CoordinateCalibration. PointF ( 160 , 10 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 2088.5759f , 1099.787f ) , new CoordinateCalibration. PointF ( 160 , - 10 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 2588.5093f , 1111.1132f ) , new CoordinateCalibration. PointF ( 160 , - 30 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 1573.5547f , 1592.8459f ) , new CoordinateCalibration. PointF ( 180 , 10 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 2082.4187f , 1601.0065f ) , new CoordinateCalibration. PointF ( 180 , - 10 ) ) ; calibrator. AddCalibrationPoint ( new CoordinateCalibration. PointF ( 2583.4763f , 1615.3347f ) , new CoordinateCalibration. PointF ( 180 , - 30 ) ) ; // 执行标定计算 if ( calibrator. CalculateCalibration ( ) ) { // 测试转换 var testImagePoint= new CoordinateCalibration. PointF ( 1200 , 1500 ) ; var robotPoint= calibrator. ImageToRobot ( testImagePoint) ; MessageBox. Show ( $"图像坐标( { testImagePoint. X } , { testImagePoint. Y } ) -> 机械手坐标( { robotPoint. X } , { robotPoint. Y } )" ) ; // 测试逆转换 var backToImage= calibrator. RobotToImage ( robotPoint) ; MessageBox. Show ( $"机械手坐标( { robotPoint. X } , { robotPoint. Y } ) -> 图像坐标( { backToImage. X } , { backToImage. Y } )" ) ; } } } }