软件编程
位置:首页>> 软件编程>> C#编程>> c# 圆形识别方案和直线识别方案的参考示例

c# 圆形识别方案和直线识别方案的参考示例

作者:louzi  发布时间:2022-03-10 13:44:11 

标签:c#,圆形识别,直线识别

圆形识别方案

识别流程

  • 判断是否为封闭图形;

  • 根据圆的方程,取输入点集中的1/6、3/6、5/6处的三个点,求得圆的方程,获取圆心及半径;

  • 取点集中的部分点,计算点到圆心的距离与半径的比例,与设定的阈值比较,得出结果。~~~~

实现


public static bool IsCircle(List<Point> points, out Point center, out double radius)
{
int len = points.Count;
center = new Point();
radius = 0;

// 判断是否为封闭图形
if (!IsClosedFigure(points))
return false;

int judgePointNum = len * 50 / 100;
if (len < judgePointNum)
return false;

// 取链表上三个点作为判断圆的根据
Point p1 = points[len / 6];
Point p2 = points[len / 2];
Point p3 = points[len * 5 / 6];
if ((Math.Abs(p1.X - p2.X) < 100 && Math.Abs(p1.Y - p2.Y) < 100)
|| (Math.Abs(p1.X - p3.X) < 100 && Math.Abs(p1.Y - p3.Y) < 100)
|| (Math.Abs(p2.X - p3.X) < 100 && Math.Abs(p2.Y - p3.Y) < 100))
return false;

// 三个点确定圆的方程,获取圆心坐标及半径
GetCircle(p1, p2, p3, out center, out radius);

// 获取圆上平均分部的多个点,判断其到圆心的距离与半径之差是否在精度内
for (int i = 0; i < judgePointNum; ++i)
{
// 获取圆上点
Point p = points[len * i / judgePointNum];
double deviation = Math.Abs(GetDistance(center, p) - radius);

// 点在圆上的偏移量与半径的比值若大于固定值,则不为圆
if (deviation/radius > MaxRatio)
 return false;
}

return true;
}

直线识别方案

步骤

1.使用最小二乘法回归直线:

c# 圆形识别方案和直线识别方案的参考示例

2.得到直线方程y=kx+b后,计算所有点到直线的距离,若在阈值范围内,认为是直线。

实现


/// <summary>
/// 最小二乘法求回归直线方程
/// </summary>
/// <param name="points">输入数据</param>
/// <param name="k">直线斜率</param>
/// <param name="b">直线截距</param>
/// <param name="type">直线类型 1:水平线 2:垂直线 3:一般直线</param>
/// <returns></returns>
public static bool IsLine(List<Point> points, out double k, out double b, out int type)
{
k = 0;
b = 0;
type = 0;

if (points.Count < 2) return false;

double averageX = 0, averageY = 0, n = 0;
n = points.Count;
foreach (Point p in points)
{
averageX += p.X;
averageY += p.Y;
}
averageX /= n;
averageY /= n;

double numerator = 0, denominator = 0;
foreach (Point p in points)
{
numerator += (p.X - averageX) * (p.Y - averageY);
denominator += (p.X - averageX) * (p.X - averageX);
}

if (numerator == 0) //平行于X轴为水平线,返回纵坐标平均值
{
b = averageY;
type = 1;
}
else if (denominator == 0)//平行于Y轴为垂直线,返回横坐标平均值
{
b = averageX;
type = 2;
}
else
{
type = 3;
}

k = numerator / denominator;
b = averageY - k * averageX;

foreach (Point p in points)
{
dis = GetPoint2LineDistance(p, k, b, type);
if (dis > MAX_POINT_LINE_DIS) return false; //点到拟合直线距离过大
}

return true;
}

/// <summary>
/// 计算点到直线的距离
/// </summary>
/// <param name="p">待计算点</param>
/// <param name="k">直线斜率</param>
/// <param name="b">直线截距</param>
/// <param name="type">直线类型 1:水平线 2:垂直线 3:一般直线</param>
/// <returns>距离</returns>
private static double GetPoint2LineDistance(Point p, double k, double b, int type)
{
if (type == 1)
{
return Math.Abs(p.Y - b);
}
else if (type == 2)
{
return Math.Abs(p.X - b);
}
else
{
double numerator = 0, denominator = 0;
numerator = Math.Abs(k * p.X - p.Y + b);
denominator = Math.Sqrt(k * k + 1);
return numerator / denominator;
}
}

来源:https://www.cnblogs.com/louzixl/p/14381179.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com