hom_mat2d_to_affine_par 的c#实现
背景:为课室贡献一个通用函数,实现halcon算子的同等效果,查询csdn未果,deepseek二哥与chtgpt大哥给不了最终程序,在大哥与二哥帮助下,最终实现同等效果。
踩坑:1、缩放在x、y方向只输出正值,为负值时的翻转与对称的成像需要通过剪切值的正反去修正;
2、矩阵获得的变换过程对求解公式有影响,此处矩阵获得方式与halcon二维仿射变换矩阵获得方式一致(变换顺序:平移→旋转→剪切→缩放)
///
/// 根据齐次变换矩阵计算仿射变换的参数
///
/// 输入一个变换矩阵(变换顺序:平移→旋转→剪切→缩放)
///
/// 输出角度参数类型,0:弧度值;1:角度值
/// 沿着X方向的缩放因子,范围:大于等于0
/// 沿着Y方向的缩放因子,范围:大于等于0
/// AngType0时旋转弧度,AngType1时旋转角度
/// Y轴倾斜角度/剪切量,AngType0时弧度,AngType1时角度
/// 沿着 X 方向的平移
/// 沿着 Y 方向的平移
/// 返回值为0时正常;-1为函数异常;-2矩阵数组超出9位或后三位非法,不为001
int HomMat2dToAffinePar(double[] homMat, int AngType, out double Sx, out double Sy, out double Phi, out double Theta, out double Tx, out double Ty)
{
Sx = 0; Sy = 0;
Phi = 0; Theta = 0;
Tx = 0; Ty = 0;
try
{
// 验证输入数组有效性
if (homMat.Length != 9 || homMat[6] != 0 || homMat[7] != 0 || homMat[8] != 1)
{
return -2;
}
// 提取平移参数
Tx = homMat[2];
Ty = homMat[5];
// 提取线性变换部分
double a = homMat[0];
double b = homMat[1];
double c = homMat[3];
double d = homMat[4];
// 计算X轴缩放和旋转角度
Sx = Math.Sqrt(a * a + c * c);
if (Sx < 1e-10)
{ return -1; }
// 计算旋转角度
Phi = Math.Atan2(c, a); // 弧度
// 计算Y轴缩放
double cosPhi = Math.Cos(Phi);
double sinPhi = Math.Sin(Phi);
Sy = Math.Sqrt(Math.Pow((b * cosPhi + d * sinPhi), 2) + Math.Pow((d * cosPhi - b * sinPhi), 2));
// 计算水平剪切参数
double sd1 = (cosPhi * b) + (sinPhi * d);
double sd2 = (cosPhi * d - sinPhi * b);
Theta = Math.Atan(sd1 / sd2);
// 根据缩放只输出正值对水平剪切的影响,修改剪切值
if (sd2 <= 0)
{
Theta = sd1 <= 0 ? (Math.PI + Theta) : (-1 * (Math.PI + Theta));
}
else
{
Theta = (Theta * -1);
}
// 将弧度标准化到[-π, π]范围
if (Phi > Math.PI)
{
Phi -= (2 * Math.PI);
}
else if (Phi < -Math.PI)
{
Phi += (2 * Math.PI);
}
if (Theta > Math.PI)
{
Theta -= (2 * Math.PI);
}
else if (Theta < -Math.PI)
{
Theta += (2 * Math.PI);
}
// 将弧度转为角度
if (AngType == 1)
{
Phi = Phi * (180 / Math.PI);
Theta = Theta * (180 / Math.PI);
}
return 0;
}
catch (Exception e)
{
return -1;
}
}
使用演示:在任意函数中实现
double[] g_CalibBYto6AxisHomMat3Test = { 0.99950, 0.000441, -160.94621, 0.00135, -1.000664, 110.402229, 0, 0, 1 };
double Sx = 0;
double Sy = 0;
double Rot = 0;
double Theta = 0;
double Tx = 0;
double Ty = 0;
HomMat2dToAffinePar(g_CalibBYto6AxisHomMat3Test, 0, out Sx, out Sy, out Rot, out Theta, out Tx, out Ty);
测试结果:halcon算子hom_mat2d_to_affine_par与c#函数对比一致