一种直线识别方案

司马昭
• 阅读 1264

本文介绍一种直线的识别方案。

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

$$\begin{cases}\frac{\sum_{i=1}^N(x_i,\overline{x})(y_i,\overline{y})}{\sum_{i=1}^N(x_i,\overline{x})^2}\\b=\overline{y}-k\overline{x}\end{cases}$$

  1. 得到直线方程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;
    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
10个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Wesley13 Wesley13
4年前
UIWebView长按保存图片和识别图片二维码的实现方案(使用缓存)
0x00需求:长按识别UIWebView中的二维码,如下图长按识别二维码0x01方案1:给UIWebView增加一个长按手势,激活长按手势时获取当前UIWebView的截图,分析是否包含二维码。核心代码:略优点:流程简单,可以快速实现。不足:无法实现保存UIWebView中图片,如果当前We
Stella981 Stella981
4年前
MacOS VSCode 安装 GO 插件失败问题解决
0x00问题重现Installinggolang.org/x/tools/cmd/guruFAILEDInstallinggolang.org/x/tools/cmd/gorenameFAILEDInstallinggolang.org/x/lint/golintFAILEDInst
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
4年前
MBR笔记
<bochs:100000000000e\WGUI\Simclientsize(0,0)!stretchedsize(640,480)!<bochs:2b0x7c00<bochs:3c00000003740i\BIOS\$Revision:1.166$$Date:2006/08/1117
Wesley13 Wesley13
4年前
67,盛最多水的容器
给定 _n_ 个非负整数 _a_1,_a_2,...,_a_n,每个数代表坐标中的一个点 (_i_, _ai_)。在坐标内画 _n_ 条垂直线,垂直线 _i_ 的两个端点分别为 (_i_, _ai_)和(_i_,0)。找出其中的两条线,使得它们与 _x_ 轴共同构成的容器可以容纳最多的水。说明:你不能倾斜容器,且 _n_ 的值至少为2。!