基于levmar(Levenberg-Marquardt 非线性最小二乘优化库)的椭圆拟合

1. 包含必要的头文件

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <cmath>

2. 定义生成椭圆点的函数

编写一个函数,接受椭圆的中心坐标、长轴半径、短轴半径、旋转角度和点的数量作为参数,生成椭圆上的点并存储到 std::vector<cv::Point2d> 中:

void generateEllipsePoints(double xc, double yc, double a, double b, double theta, int num_points, std::vector<cv::Point2d>& points) {points.clear(); // 清空之前的点double angle_step = 2 * M_PI / num_points; // 每个点的角度间隔for (int i = 0; i < num_points; ++i) {double angle = i * angle_step;// 计算椭圆上点的坐标double x = xc + a * cos(angle) * cos(theta) - b * sin(angle) * sin(theta);double y = yc + a * cos(angle) * sin(theta) + b * sin(angle) * cos(theta);points.emplace_back(x, y);}
}

3. 定义误差函数

编写一个误差函数,用于计算每个点到拟合椭圆的距离:

  • 计算当前参数下,所有点到椭圆的误差。
  • p 是当前优化的参数(5 个值)。
  • x 是计算得到的误差(x_r^2 / a^2 + y_r^2 / b^2 - 1)。
  • data 是传入的离散点数据。
void ellipse_residuals(double *p, double *x, int m, int n, void *data) {double xc = p[0];  // 椭圆中心 xdouble yc = p[1];  // 椭圆中心 ydouble a = p[2];   // 长轴半径double b = p[3];   // 短轴半径double theta = p[4];  // 旋转角度double cos_t = cos(theta);double sin_t = sin(theta);double *points = (double *)data;for (int i = 0; i < n; ++i) {double x_i = points[2 * i];     // x 坐标double y_i = points[2 * i + 1]; // y 坐标// 计算旋转后的坐标double x_r = (x_i - xc) * cos_t + (y_i - yc) * sin_t;double y_r = -(x_i - xc) * sin_t + (y_i - yc) * cos_t;// 计算残差x[i] = (x_r * x_r) / (a * a) + (y_r * y_r) / (b * b) - 1;}
}

4. 使用 levmar 进行椭圆拟合

  • 定义 points[] 存储数据点,每两个值是一对 (x, y)
  • p[] 存储初始参数,包括椭圆中心、长短轴、旋转角度。
  • opts[]levmar 的优化控制参数。
  • dlevmar_dif 进行优化,nullptr 代表不需要目标函数值。
  • 代码最终输出 xc, yc, a, b, theta,即拟合出的椭圆参数。
int main() {double xc = 0.0; // 椭圆中心 x 坐标double yc = 0.0; // 椭圆中心 y 坐标double a = 5.0;   // 长轴半径double b = 3.0;   // 短轴半径double theta = M_PI / 4; // 旋转角度 45 度int num_points = 100;     // 生成 100 个点std::vector<cv::Point2d> ellipse_points;generateEllipsePoints(xc, yc, a, b, theta, num_points, ellipse_points);// 将 std::vector<cv::Point2d> 转换为 double 数组double* points = new double[2 * num_points];for (int i = 0; i < num_points; ++i) {points[2 * i] = ellipse_points[i].x;points[2 * i + 1] = ellipse_points[i].y;}// 初始猜测参数 [xc, yc, a, b, theta]double p[5] = {0.0, 0.0, 5.0, 3.0, M_PI / 4};// 设置优化参数double opts[LM_OPTS_SZ], info[LM_INFO_SZ];opts[0] = LM_INIT_MU;  // 初始阻尼因子opts[1] = 1e-10;       // 终止条件:误差变化opts[2] = 1e-10;       // 终止条件:参数变化opts[3] = 1e-10;       // 终止条件:梯度opts[4] = LM_DIFF_DELTA; // 数值微分步长// 运行优化int m = 5;  // 参数数目int n = num_points;  // 观测值数目(残差数)dlevmar_dif(ellipse_residuals, p, nullptr, m, n, 1000, opts, info, nullptr, nullptr, points);// 输出拟合结果std::cout << "拟合椭圆参数:" << std::endl;std::cout << "xc = " << p[0] << ", yc = " << p[1] << std::endl;std::cout << "a = " << p[2] << ", b = " << p[3] << std::endl;std::cout << "theta = " << p[4] * 180 / M_PI << "°" << std::endl;// 清理内存delete[] points;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/20783.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fastgpt学习(5)- FastGPT 私有化部署问题解决

1.☺ 问题描述&#xff1a; Windows系统&#xff0c;本地私有化部署&#xff0c;postgresql数据库镜像日志持续报错" data directory “/var/lib/postgresql/data” has invalid permissions "&#xff0c;“ DETAIL: Permissions should be urwx (0700) or urwx,gr…

基于SpringBoot+vue粮油商城小程序系统

粮油商城小程序为用户提供方便快捷的在线购物体验&#xff0c;包括大米、面粉、食用油、调味品等各种粮油产品的选购&#xff0c;用户可以浏览商品详情、对比价格、下单支付等操作。同时&#xff0c;商城还提供优惠活动、积分兑换等福利&#xff0c;让用户享受到更多实惠和便利…

Python编程之数据分组

有哪些方式可以进行数据分组利用Pandas库进行分组使用itertools库的groupby分组操作构建Python字典方式实现(小规模数据,不适用数量特别大的情况,不需要依赖其它python库)利用NumPy的groupby函数分组操作利用Python的Dask库提供的函数进行分组下面看一个如何去实现坐标数据…

【Linux】认识协议、Mac/IP地址和端口号、网络字节序、socket套接字

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 1、初识协议2、Mac、IP地址3、端口号4、网络字节序5、socket 1、初识协议 协议就是一种约定。如何让不同厂商生产的计算机之间能…

ubuntu 安装docker

ubuntu 安装docker 官网地址 https://docs.docker.com/engine/install/ubuntu/ 尽量根据官网的来&#xff0c;网上找的很多都是一大堆各种报错 卸载旧版本 新机器不需要操作 卸载的非官方包是&#xff1a; docker.iodocker-composedocker-compose-v2docker-docpodman-docker…

环境变量2

目录 环境变量PATH 如何改变PATH 我们今天继续来学习环境变量2&#xff01;&#xff01;&#xff01; 环境变量PATH PATH的作用是知道命令的搜索路径&#xff0c;我们都知道Linux上的命令行指令&#xff0c;ll&#xff0c;pwd什么的为什么我们写出来系统就知道是什么并且运…

网络安全中的机器学习

当涉及到网络安全时&#xff0c;技术一直是保护系统免受攻击和数据泄露的关键。在这篇论文中&#xff0c;我将介绍一些当前在网络安全领域使用的关键技术&#xff0c;包括加密&#xff0c;身份验证和防火墙。 首先&#xff0c;加密是网络安全中最常见的技术之一。加密是指使用算…

sass报错:[sass] Undefined variable. @import升级@use语法注意事项

今天创建vue3项目&#xff0c;迁移老项目代码&#xff0c;使用sass的时候发现import语法已经废弃&#xff0c;官方推荐使用use替换。 这里我踩了一个坑找半天的问题&#xff0c;原因是sass升级到1.85之后 定义变量前加上 - 就是表示变量私有&#xff0c;即使使用use导出 在新的…

嵌入式经常用到串口,如何判断串口数据接收完成?

说起通信&#xff0c;首先想到的肯定是串口&#xff0c;日常中232和485的使用比比皆是&#xff0c;数据的发送、接收是串口通信最基础的内容。这篇文章主要讨论串口接收数据的断帧操作。 空闲中断断帧 一些mcu&#xff08;如&#xff1a;stm32f103&#xff09;在出厂时就已经在…

激光雷达YDLIDAR X2 SDK安装

激光雷达YDLIDAR X2 SDK安装 陈拓 2024/12/15-2024/12/19 1. 简介 YDLIDAR X2官方网址https://ydlidar.cn/index.html‌YDLIDAR X2 YDLIDAR X2是一款高性能的激光雷达传感器&#xff0c;具有以下主要特点和规格参数‌&#xff1a; ‌测距频率‌&#xff1a;3000Hz ‌扫描频…

deepseek本地调用

目录 1.介绍 2.开始调用 2.1模型检验 2.2 通过url调用 3.总结 1.介绍 这篇博客用来教你如何从本地调用ollama中deepseek的模型接口&#xff0c;直接和deepseek进行对话。 2.开始调用 2.1模型检验 首先要保证ollama已经安装到本地&#xff0c;并且已经下载了deepseek模型…

word$deepseep

1、进入官网地址。 DeepSeek 2、进入DeepSeek的API文档 3、点击DeepSeek开放平台左侧的“API Keys”, 再点击“创建API Key” 4、在弹出的对话框中&#xff0c;输入自己的API Key名称&#xff0c;点击创建。 sk-0385cad5e19346a0a4ac8b7f0d7be428 5、打开Word文档。 6、Word找…

自制简单的图片查看器(python)

图片格式&#xff1a;支持常见的图片格式&#xff08;JPG、PNG、BMP、GIF&#xff09;。 import os import tkinter as tk from tkinter import filedialog, messagebox from PIL import Image, ImageTkclass ImageViewer:def __init__(self, root):self.root rootself.root.…

DeepSeek多模态统一模型Janus算法解析

&#xfeff;DeepSeek多模态统一模型算法解析与功能抢先体验 &#xfeff; 多模态统一模型是一种能够同时处理多模态输入&#xff08;如文本、图像、视频等&#xff09;并进行理解和生成任务的人工智能模型。这种模型可以将将多模态理解&#xff08;如视觉问答、图像描述等&a…

分享8款AI生成PPT的工具!含测评

随着人工智能技术的飞速进步&#xff0c;制作PPT变得愈发便捷&#xff0c;仅需输入主题指令&#xff0c;便能在瞬间获得一份完整的演示文稿。尤其在制作篇幅较长的PPT时&#xff0c;手动编写每一页内容并设计格式和排版&#xff0c;不仅效率低下&#xff0c;而且耗时耗力。 本…

猿大师办公助手对比其他WebOffice在线编辑Office插件有什么优势

1. 原生Office功能完整嵌入&#xff0c;排版一致性保障 猿大师办公助手直接调用本地安装的微软Office、金山WPS或永中Office&#xff0c;支持所有原生功能&#xff08;如复杂公式、VBA宏等&#xff09;&#xff0c;确保网页编辑与本地打开的文档排版完全一致。 提供OLE嵌入和完…

关于C#的一些基础知识点汇总

1.C#结构体可以继承接口吗&#xff1f;会不会产生GC&#xff1f; 在 C# 中&#xff0c;结构体不能继承类&#xff0c;但可以实现接口。 代码&#xff1a; interface IMyInterface {void MyMethod(); }struct MyStruct : IMyInterface {public void MyMethod(){Console.Write…

【第一节】C++设计模式(创建型模式)-工厂模式

目录 前言 一、面向对象的两类对象创建问题 二、解决问题 三、工厂模式代码示例 四、工厂模式的核心功能 五、工厂模式的应用场景 六、工厂模式的实现与结构 七、工厂模式的优缺点 八、工厂模式的扩展与优化 九、总结 前言 在面向对象系统设计中&#xff0c;开发者常…

CUDA兼容NVIDA版本关系

CUDA组成 兼容原则 CUDA 驱动(libcuda.so)兼容类型要求比CUDA新向后兼容无主版本一致&#xff0c;子版本旧兼容需要SASS、NVCC比CUDA老向前兼容提取对应兼容包 向后兼容&#xff1a;新版本支持旧版本的内容&#xff0c;关注的是新版本能否处理旧版本的内容。 向前兼容&#…

便捷批量字符一键查找替换工具

软件介绍 今天要给大家分享一款超好用的批量字符替换工具。它操作便捷&#xff0c;只需一键&#xff0c;就能帮你轻松查找替换内容。 这款工具的兼容性堪称强大&#xff0c;支持 txt、reg、bat、cmd、htm、html、xml、asp、aspx、php、php3、php4、php5、jsp、asax、java、cp…