当前位置: 首页 > article >正文

C# 机器视觉-RANSAC算法拟合圆

我们在开发机器视觉的时候,很多情况下提取到圆的轮廓并不完整。那么我们就需要采取一些手段来将原本不完整的圆拟合成一个完整的圆。下面常用的是RANSAC算法来拟合圆。

static void RANSAC()

{

// 加载图像

Mat image = Cv2.ImRead("path_to_your_image.jpg", ImreadModes.Grayscale);

// 边缘检测

Mat edges = new Mat();

Cv2.Canny(image, edges, 100, 200);

// 寻找边缘点

Point[][] contours;

HierarchyIndex[] hierarchy;

Cv2.FindContours(edges, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

// 假设最长的轮廓是我们要拟合圆的边缘

var longestContour = contours.OrderByDescending(c => c.Length).FirstOrDefault();

// RANSAC参数

int iterations = 1000;

double distanceThreshold = 3.0; // 点到圆的最大距离

double bestCircularity = double.MaxValue; // 初始化为最大值

Point2f bestCircleCenter = new Point2f();

float bestCircleRadius = 0;

Random rand = new Random();

for (int i = 0; i < iterations; i++)

{

// 随机选择三个点

Point[] randomPoints = longestContour.OrderBy(x => rand.Next()).Take(3).ToArray();

// 计算这三个点定义的圆

Point2f center;

float radius;

if (TryFitCircleToPoints(randomPoints, out center, out radius))

{

// 计算适合这个圆的点的数量

var inliers = longestContour.Where(p => IsPointNearCircle(p, center, radius, distanceThreshold)).ToList();

int inliersCount = inliers.Count;

// 计算圆度

double circularity = CalculateCircularity(center, radius, inliers);

// 更新最佳圆

if (circularity < bestCircularity)

{

bestCircularity = circularity;

bestCircleCenter = center;

bestCircleRadius = radius;

}

}

}

// 输出最佳拟合圆的结果

Console.WriteLine($"Best circle center: {bestCircleCenter}, radius: {bestCircleRadius}, circularity: {bestCircularity}");

}

// 新增圆度计算方法

static double CalculateCircularity(Point2f center, float radius, List<Point> inliers)

{

double sumSquaredDifferences = inliers.Sum(point =>

{

double distanceToCenter = Math.Sqrt(Math.Pow(point.X - center.X, 2) +Math.Pow(point.Y - center.Y, 2));

return Math.Pow(distanceToCenter - radius, 2);

});

double circularity = Math.Sqrt(sumSquaredDifferences / inliers.Count);

return circularity;

}

static bool TryFitCircleToPoints(Point[] points, out Point2f center, out float radius)

{

// 三点确定一个圆的算法

// 使用三点坐标计算圆心和半径

center = new Point2f();

radius = 0f;

float x1 = points[0].X;

float y1 = points[0].Y;

float x2 = points[1].X;

float y2 = points[1].Y;

float x3 = points[2].X;

float y3 = points[2].Y;

float a = x1 - x2;

float b = y1 - y2;

float c = x1 - x3;

float d = y1 - y3;

float e = ((x1 * x1 - x2 * x2) + (y1 * y1 - y2 * y2)) / 2.0f;

float f = ((x1 * x1 - x3 * x3) + (y1 * y1 - y3 * y3)) / 2.0f;

float det = a * d - b * c;

if (Math.Abs(det) > 1e-6) // 非共线

{

// 计算圆心

center.X = (d * e - b * f) / det;

center.Y = (-c * e + a * f) / det;

// 计算半径

radius = (float)Math.Sqrt((center.X - x1) * (center.X - x1) + (center.Y - y1) * (center.Y - y1));

return true;

}

return false;

}

static bool IsPointNearCircle(Point point, Point2f center, float radius, double threshold)

{

// 计算点到圆的距离,并检查是否小于阈值

double distance = Math.Sqrt(Math.Pow(point.X - center.X, 2) + Math.Pow(point.Y - center.Y, 2)) - radius;

return Math.Abs(distance) <= threshold;

}


http://www.kler.cn/a/441381.html

相关文章:

  • Java 大视界 -- Java 大数据中的隐私增强技术全景解析(64)
  • 【2025年数学建模美赛F题】(顶刊论文绘图)模型代码+论文
  • 记录一个连不上docker中的mysql的问题
  • opengrok_使用技巧
  • 无人机如何自主侦察?UEAVAD:基于视觉的无人机主动目标探测与导航数据集
  • C++异步future
  • 基于RRT(Rapidly-exploring Random Tree)的无人机三维路径规划,MATLAB代码
  • 【Redis】一人一单秒杀活动
  • Spring Boot 启动时间优化全攻略
  • macos big sur 软件icons图标大全(新增至2719枚大苏尔风格图标)
  • Nodejs架构
  • 【MySQL中多表查询和函数】
  • Linux 入门指南(详细版:基于 CentOS,使用 WSL 环境)
  • 【Linux】软件包管理与vim工具使用详解
  • 微服务系统架构设计参考
  • 题目 3010: 奇偶数之和
  • 【算法day14】二叉树:搜索树的递归问题
  • 如何利用Python爬虫京东获得JD商品详情
  • 力扣-图论-12【算法学习day.62】
  • UE5制作伤害浮动数字
  • 如何在OpenCV中运行自定义OCR模型
  • RabbitMQ安装延迟消息插件(mq报错)
  • YOLO 数据增强 Python 脚本(可选次数,无限随机增强)- 一键执行搞定,自动化提升训练集质量 | 幽络源
  • 在 Docker 中运行 Golang 应用程序,如何做?
  • 电子应用设计方案-56:智能书柜系统方案设计
  • Mac 开机 一闪框 mediasharingd