OpenCvSharp函数:FitLine直线拟合
opencv
OpenCV: 开源计算机视觉库
项目地址:https://gitcode.com/gh_mirrors/opencv31/opencv
免费下载资源
·
FitLine直线拟合
函数说明:基于M-估计量(M-Estimator)算法对给定的一组二维或三维点坐点集拟合直线。
//函数原型1
void FitLine(InputArray points,
OutputArray line,
DistanceTypes distType,
double param,
double reps,
double aeps)
//函数原型2
Line2D FitLine(IEnumerable<Point> points,
DistanceTypes distType,
double param,
double reps,
double aeps)
//函数原型3
Line2D FitLine(IEnumerable<Point2f> points,
DistanceTypes distType,
double param,
double reps,
double aeps)
//函数原型4
Line3D FitLine(IEnumerable<Point3i> points,
DistanceTypes distType,
double param,
double reps,
double aeps)
//函数原型5
Line3D FitLine(IEnumerable<Point3f> points,
DistanceTypes distType,
double param,
double reps,
double aeps)
参数 | 说明 |
InputArray points IEnumerable<Point> points IEnumerable<Point2f> points IEnumerable<Point3i> points IEnumerable<Point3f> points | 待拟合直线的坐标点集(二维或三维) |
DistanceTypes distType | 距离计算方式:一般用L2或L1 |
double param | 参数C的取值:distType为Fair、Welsch、Huber时用到,默认为0即可,会自动取最优值 |
double reps | 半径(坐标原点到直线的距离)精确。建议为0.01 |
double aeps | 角度精确。建议为0.01 |
返回值(Line2D,Line3D) | 返回拟合直线。 a.Vy=1时,与垂直X轴垂直。Vx=1时,与Y轴垂直 b.直率斜率k=Vy/Vx c.截距b=Y1-k*X1 |
图像示例
源码示例
private string winName = "FitLine Demo";
public void Run() {
Cv2.NamedWindow(winName, WindowFlags.Normal);
Cv2.ResizeWindow(winName, new Size(800, 800));
Cv2.CreateTrackbar("偏移", winName, 100, OnChanged);
Cv2.SetTrackbarPos("偏移", winName, 50);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
private void OnChanged(int pos, IntPtr userData) {
//生成随机点
List<List<Point>> curves = new List<List<Point>>();
List<Point> rndPoints = new List<Point>();
Random random = new Random();
for (int col = 30; col < 450; col += 20) {
rndPoints.Add(new Point(500 - col, 50 + col / 2 + random.Next(-pos, pos)));
}
curves.Add(rndPoints);
rndPoints = new List<Point>();
for (int row = 30; row < 450; row += 20) {
rndPoints.Add(new Point(100 + row / 2 + random.Next(-pos, pos), row));
}
curves.Add(rndPoints);
rndPoints = new List<Point>();
for (int xy = 30; xy < 450; xy += 20) {
if (pos % 2 == 0) {
rndPoints.Add(new Point(xy, pos));
}
else {
rndPoints.Add(new Point(pos, xy));
}
}
curves.Add(rndPoints);
using Mat src = Mat.Zeros(new Size(500, 500), MatType.CV_8UC3);
foreach (var points in curves) {
foreach (var point in points) {
Cv2.Circle(src, point, 2, Scalar.Blue, -1);
}
//直线拟合
var line = Cv2.FitLine(points, DistanceTypes.L2, 0, 0.01, 0.01);
GetStartEndPoint(src, points, line, out Point startPoint, out Point endPoint);
Cv2.Line(src, startPoint, endPoint, Scalar.Red, lineType: LineTypes.AntiAlias);
Cv2.Circle(src, (int)line.X1, (int)line.Y1, 3, Scalar.Yellow, -1);
}
Cv2.ImShow(winName, src);
}
/// <summary>
/// 获取待拟合点集的起始与终止点
/// </summary>
/// <param name="src"></param>
/// <param name="points">待拟合点集</param>
/// <param name="line">拟合直线</param>
/// <param name="p1">起点</param>
/// <param name="p2">终止</param>
private void GetStartEndPoint(Mat src, List<Point> points, Line2D line, out Point p1, out Point p2) {
if (1 - line.Vx < 0.0001) {//水平线
var sort = points.OrderBy(z => z.X);
p1 = new Point(sort.First().X, line.Y1);
p2 = new Point(sort.Last().X, line.Y1);
}
else if (1 - line.Vy < 0.0001) {//垂直线
var sort = points.OrderBy(z => z.Y);
p1 = new Point(line.X1, sort.First().Y);
p2 = new Point(line.X1, sort.Last().Y);
}
else {
//原直线斜率,注意Y轴是向下的(斜率正负号与通常的坐标系相反)
var k1 = line.Vy / line.Vx;
//直线截距
var b1 = line.Y1 - k1 * line.X1;
IOrderedEnumerable<Point> sort;
if (k1 > 0) {//与普通坐标系统符号相反
//左上到右下
sort = points.OrderBy(z => z.Y).ThenBy(z => z.X);
}
else {
//左下到右上
sort = points.OrderBy(z => z.X).ThenBy(z => z.Y);
}
p1 = GetCrossPoint(sort.First(), k1, b1);
p2 = GetCrossPoint(sort.Last(), k1, b1);
Cv2.Line(src, p1, sort.First(), Scalar.Yellow);
Cv2.Line(src, p2, sort.Last(), Scalar.Yellow);
Cv2.PutText(src, $"k={k1.ToString("0.0000")},b={b1.ToString("0.0")}", p1, HersheyFonts.HersheySimplex, 0.5, Scalar.White);
}
}
/// <summary>
/// 获取经过point的与直线(斜率为k1,截距为b1)的垂直直线的交点
/// </summary>
/// <param name="point"></param>
/// <param name="k1">直线斜率</param>
/// <param name="b1">直线截距</param>
/// <returns></returns>
private Point GetCrossPoint(Point point,double k1,double b1) {
//与原直线垂直的直线的斜率 。斜率相乘等于-1
var k2 = -1.0D / k1;
//与原直线垂直的直线的截距
var b2 = point.Y - k2 * point.X;
//交点
Point crossPoint = new Point();
crossPoint.X = (int)((b2 - b1) / (k1 - k2));
crossPoint.Y = (int)((b2 * k1 - b1 * k2) / (k1 - k2));
return crossPoint;
}
GitHub 加速计划 / opencv31 / opencv
77.37 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:2 个月前 )
c3747a68
Added Universal Windows Package build to CI. 1 天前
9b635da5 - 1 天前
更多推荐
已为社区贡献7条内容
所有评论(0)