重点讲一下坐标系变换:
//1,计算均值x,y
double 均值x = Convert.ToDouble(textBoxCpt1x.Text) + Convert.ToDouble(textBoxCpt2x.Text) +
Convert.ToDouble(textBoxCpt3x.Text) + Convert.ToDouble(textBoxCpt4x.Text) +
Convert.ToDouble(textBoxCpt5x.Text) + Convert.ToDouble(textBoxCpt6x.Text) +
Convert.ToDouble(textBoxCpt7x.Text) + Convert.ToDouble(textBoxCpt8x.Text) +
Convert.ToDouble(textBoxCpt9x.Text);
double 均值y = Convert.ToDouble(textBoxCpt1y.Text) +
Convert.ToDouble(textBoxCpt2y.Text) + Convert.ToDouble(textBoxCpt3y.Text) +
Convert.ToDouble(textBoxCpt4y.Text) + Convert.ToDouble(textBoxCpt5y.Text) +
Convert.ToDouble(textBoxCpt6y.Text) + Convert.ToDouble(textBoxCpt7y.Text) +
Convert.ToDouble(textBoxCpt8y.Text) + Convert.ToDouble(textBoxCpt9y.Text);
均值x = 均值x / 9.0f;//坐标中心就定在这里
均值y = 均值y / 9.0f;
//2,计算水平x角度,计算垂直y角度,计算平均角度
PointF[] arrptf = new PointF[9];
arrptf[0].X=(float)Convert.ToDouble(textBoxCpt1x.Text);arrptf[0].Y=(float)Convert.ToDouble(textBoxCpt1y.Text);
arrptf[1].X=(float)Convert.ToDouble(textBoxCpt2x.Text);arrptf[1].Y=(float)Convert.ToDouble(textBoxCpt2y.Text);
arrptf[2].X=(float)Convert.ToDouble(textBoxCpt3x.Text);arrptf[2].Y=(float)Convert.ToDouble(textBoxCpt3y.Text);
arrptf[3].X=(float)Convert.ToDouble(textBoxCpt4x.Text);arrptf[3].Y=(float)Convert.ToDouble(textBoxCpt4y.Text);
arrptf[4].X=(float)Convert.ToDouble(textBoxCpt5x.Text);arrptf[4].Y=(float)Convert.ToDouble(textBoxCpt5y.Text);
arrptf[5].X=(float)Convert.ToDouble(textBoxCpt6x.Text);arrptf[5].Y=(float)Convert.ToDouble(textBoxCpt6y.Text);
arrptf[6].X=(float)Convert.ToDouble(textBoxCpt7x.Text);arrptf[6].Y=(float)Convert.ToDouble(textBoxCpt7y.Text);
arrptf[7].X=(float)Convert.ToDouble(textBoxCpt8x.Text);arrptf[7].Y=(float)Convert.ToDouble(textBoxCpt8y.Text);
arrptf[8].X = (float)Convert.ToDouble(textBoxCpt9x.Text); arrptf[8].Y = (float)Convert.ToDouble(textBoxCpt9y.Text);
//下面用最小二乘求直线//中心水平线点,取4,5,6三个点
double a = 0; double b = 0; double c = 0; double d = 0;
for (int i = 3; i < 6; i++)
{
a += arrptf[i].X;
b += arrptf[i].Y;
c += arrptf[i].X * arrptf[i].Y;
d += arrptf[i].X * arrptf[i].X;
}
double xielv = (3 * c - a * b) / (3 * d - a * a);
double Aa = 0; double Bb = 0; double Cc = 0; double Dd = 0;
for (int i = 1; i < 8; i = i + 3)//中心垂直线点,取2,5,8三个点
{
Aa += arrptf[i].X;
Bb += arrptf[i].Y;
Cc += arrptf[i].X * arrptf[i].Y;
Dd += arrptf[i].X * arrptf[i].X;
}
double xielv2 = (3 * Cc - Aa * Bb) / (3 * Dd - Aa * Aa);
//3,计算毫米和像素的关系,像素距离与mm间隔关系
double tempDist水平 = 0;
for (int i = 3; i < 5; i++)//水平,两个间距
{
tempDist水平 += Math.Sqrt((arrptf[i].X - arrptf[i + 1].X) * (arrptf[i].X - arrptf[i + 1].X) +
(arrptf[i].Y - arrptf[i + 1].Y) * (arrptf[i].Y - arrptf[i + 1].Y));
}
textBox间距X.Text = ((float)(tempDist水平 / 2.0 * 0.5)).ToString();//+"pixels/mm"
double tempDist垂直 = 0;
for (int i = 1; i < 7; i = i + 3)//中心垂直线点,取2,5,8三个点,两个间距
{
tempDist垂直 += Math.Sqrt((arrptf[i].X - arrptf[i + 3].X) * (arrptf[i].X - arrptf[i + 3].X) +
(arrptf[i].Y - arrptf[i + 3].Y) * (arrptf[i].Y - arrptf[i + 3].Y));
}
textBox间距y.Text = ((float)(tempDist垂直 / 2.0 * 0.5)).ToString();//+"pixels/mm"
下面讲如何把像素坐标变成毫米坐标:根据我们上面得到的关系,步骤如下:
tempframept = m_roiCoord9点标定.m_RoiBase.mapPoint(new PointF((float)tempxx, (float)tempyy), 1);//比例
mappoint这个函数下面要说一堆话
这一步把要验证的像素点(tempxx,tempyy)坐标变换后,给点tempframept。
如何做到,第一,像素点(tempxx,tempyy)-(均值x, 均值y)=newpoint
第二,这个点newpoint旋转一定角度theta,根据上面斜率(xielv)得到,结果就是tempframept:
tempframept.x=?
tempframept.y=?
tempframept.x = newpoint.x * Math.Cos(theta) +newpoint.y * Math.Sin(theta);
tempframept.y =newpoint.y * Math.Cos(theta) - newpoint.x * Math.Sin(theta);
又用到这个公式了,围绕原点旋转的线
第三, float 示教点相对x = (float)((tempframept.X) / Convert.ToDouble(textBox间距X.Text));
float 示教点相对y = (float)((tempframept.Y ) / Convert.ToDouble(textBox间距y.Text));
第三步得到的已经是毫米坐标了,机器人示教点的相对坐标。
(机器人示教点.x+示教点相对x,机器人示教点.y+示教点相对y)就是机器人绝对坐标。
再看几个不一样的:多验证,没坏处