(Halcon)轮廓等分切割(项目分析)
目标:获取绿色圆所在位置(可用于点焊/点胶引导)
实现思路
一,相机标定板标定(如果实战用于点焊/点胶引导需要做图像畸变校正以减小误差)
相机标定
如何做一个C#仿Halcon Calibration插件-CSDN博客
二,九点标定(图像位姿与点焊/点胶坐标转换)
三,获取指定位置全部轮廓 segment_contours_xld
四,get_contour_global_attrib_xld 获取Attrib值,通过值判定拟合类型
详情可以参考之前博客
Halcon XLD轮廓分割_halcon轮廓分割-CSDN博客
五,轮廓拟合(直线/圆/椭圆)获取每个轮廓的端点/半径/起始角度信息
六,获取所有轮廓的长度信息
七,创建列表保存所有信息
八,判定长度信息与落点位置(例如黄色轮廓不满足两次落点间隔,则粉色轮廓的初次落点位置为(指定间隔长度-黄色轮廓长度)以此类推,直至落点布满全部轮廓)
难点解析
指定点在指定直线指定间隔平移 与 指定点在圆弧上指定间隔平移
一,指定点在指定直线指定间隔平移
解决方法,线性代数
Row 初始行坐标
Column 初始列坐标
Length 直线偏移距离
num 可绘制点数
for Index := 0 to num by 1
Rnew:=-Length*sin(Angle)*Index+Row
Cnew:=Length*cos(Angle)*Index+Column
gen_cross_contour_xld (Cross1, Rnew, Cnew, 6, Angle)
endfor
二,指定点在圆弧上指定间隔平移
解决方案,旋转矩阵
实现效果
更改分割间隔
C#分割测试代码
private void btn_Seg1_Click(object sender, EventArgs e)
{
showWorkMsg(listView1, "计时开始", Color.Tan);
HObject ho_Cross=null, ho_Cross1 = null;
HTuple hv_HomMat2DIdentity = new HTuple(), hv_HomMat2DTranslate = new HTuple(), hv_HomMat2DRotate = new HTuple();
HTuple hv_R1 = new HTuple(), hv_C1 = new HTuple();
HTuple hv_R = new HTuple(),hv_C = new HTuple();
HOperatorSet.GenEmptyObj(out ho_Cross1);
HOperatorSet.GenEmptyObj(out ho_Cross);
//获取长度
double ClipLength = Convert.ToDouble(tbx_length.Text);
//获取分割数量
int NumCilp = Convert.ToInt32(Math.Floor(Length / ClipLength));
//获取单个角度
double AngleStep = (hv_end_angle.D - hv_start_angle.D) / NumCilp;
//X偏移
double X = ((-hv_ra) * (hv_start_angle.TupleSin()));
//Y偏移
double Y = (hv_ra * (hv_start_angle.TupleCos()));
//创建矩阵
hv_HomMat2DIdentity.Dispose();
HOperatorSet.HomMat2dIdentity(out hv_HomMat2DIdentity);
hv_HomMat2DTranslate.Dispose();
HOperatorSet.HomMat2dTranslate(hv_HomMat2DIdentity, X, Y, out hv_HomMat2DTranslate);
hv_R.Dispose();
hv_R = new HTuple();
hv_C.Dispose();
hv_C = new HTuple();
//循环获取点和轮廓
for (int i = 0; i < NumCilp+1; i++)
{
hv_HomMat2DRotate.Dispose();
HOperatorSet.HomMat2dRotate(hv_HomMat2DTranslate, i * AngleStep , hv_R_Centr,
hv_C_Centr, out hv_HomMat2DRotate);
hv_R1.Dispose(); hv_C1.Dispose();
HOperatorSet.AffineTransPoint2d(hv_HomMat2DRotate, hv_R_Centr, hv_C_Centr,
out hv_R1, out hv_C1);
ho_Cross1.Dispose();
HOperatorSet.GenCrossContourXld(out ho_Cross1, hv_R1, hv_C1, 60, 0.785398);
HOperatorSet.ConcatObj(ho_Cross, ho_Cross1,out ho_Cross);
HTuple ExpTmpLocalVar_R = hv_R.TupleConcat(hv_R1);
hv_R.Dispose();
hv_R = ExpTmpLocalVar_R;
HTuple ExpTmpLocalVar_C = hv_C.TupleConcat(hv_C1);
hv_C.Dispose();
hv_C = ExpTmpLocalVar_C;
double rrr = Convert.ToDouble(hv_R1.D);
double ccc = Convert.ToDouble(hv_C1.D);
showWorkMsg(listView1,"R:"+ rrr.ToString("0.000") +" , C:"+ ccc.ToString("0.000"), Color.Teal);
}
HW.DispObj(ho_Cross);
showWorkMsg(listView1, hv_R.ToString(), Color.Teal);
showWorkMsg(listView1, hv_C.ToString(), Color.Teal);
showWorkMsg(listView1, "计时结束", Color.Tan);
}