iced源码分析
前言
iced是一个比较流行的UI库,设计思路还是挺有意思的,不过因为rust复杂的语法,这个库确实很难让一个不精通rust的开发者那么容易理解。这里记录下这几天的阅读源码心得。
正文
iced核心包括四个模块。
- iced库,主要控制应用状态、核心是application。
- iced core这是真正的iced的核心库,主要功能包括三部分
- 通过winit创建窗口,以及处理窗口的点击事件
- 在窗口回调杨中,使用widget库绘制图像
- 而widget的绘制则是通过tiny_skia或者wgup提供的renderer绘制图像。
- tiny_skia或者wgup提提供的renderer绘制图像
- winit提供窗口管理
所以iced_core才是真的库核心。管理所有业务逻辑,而iced源码基本上只是提供用户最基本的基本调用
下面跟踪一下applaction的构造过程。我们参考一下计数器的实例代码,分析一下构造过程。
pub fn main() -> iced::Result {iced::run("A cool counter", Counter::update, Counter::view)
}#[derive(Default)]
struct Counter {value: i64,
}#[derive(Debug, Clone, Copy)]
enum Message {Increment,Decrement,
}impl Counter {fn update(&mut self, message: Message) {match message {Message::Increment => {self.value += 1;}Message::Decrement => {self.value -= 1;}}}fn view(&self) -> Column<Message> {column![button("Increment").on_press(Message::Increment),text(self.value).size(50),button("Decrement").on_press(Message::Decrement)].padding(20).align_x(Center)}
}t
iced::run
提供静态函数,用于创建applaction。便于用户使用具体构造函数我们看下
pub fn run<State, Message, Theme, Renderer>(title: impl application::Title<State> + 'static,update: impl application::Update<State, Message> + 'static,view: impl for<'a> application::View<'a, State, Message, Theme, Renderer>+ 'static,
) -> Result
whereState: Default + 'static,Message: std::fmt::Debug + Send + 'static,Theme: Default + program::DefaultStyle + 'static,Renderer: program::Renderer + 'static,
{application(title, update, view).run()
}
这段代码主要是str实现了titile接口,Fn实现了Update。Fn实现了View接口。
impl<State> Title<State> for &'static str {fn title(&self, _state: &State) -> String {self.to_string()}
}impl<T, State, Message, C> Update<State, Message> for T
whereT: Fn(&mut State, Message) -> C,C: Into<Task<Message>>,
{fn update(&self,state: &mut State,message: Message,) -> impl Into<Task<Message>> {self(state, message)}
}impl<'a, T, State, Message, Theme, Renderer, Widget>View<'a, State, Message, Theme, Renderer> for T
whereT: Fn(&'a State) -> Widget,State: 'static,Widget: Into<Element<'a, Message, Theme, Renderer>>,
{fn view(&self,state: &'a State,) -> impl Into<Element<'a, Message, Theme, Renderer>> {self(state)}
}
关于返回值,因为Element都为每种widget实现了From接口,所以都会自动转化位Element。返回值是编译器自动转化。
最终我们得到了Applaction。
pub fn application<State, Message, Theme, Renderer>(title: impl Title<State>,update: impl Update<State, Message>,view: impl for<'a> self::View<'a, State, Message, Theme, Renderer>,
) -> Application<impl Program<State = State, Message = Message, Theme = Theme>>
whereState: 'static,Message: Send + std::fmt::Debug + 'static,Theme: Default + DefaultStyle,Renderer: program::Renderer,
{......
}
注意这里的Theme是通过外层widget确认的。而renderer却比较奇葩,这是一个非常奇怪的东西。他的根trait是core模块的render.rs 定义的。在不同的绘制的目的,有不同的嘴trait。比如core目录下的image.rs 下的renderer
pub trait Renderer: crate::Renderer {/// The image Handle to be displayed. Iced exposes its own default implementation of a [`Handle`]////// [`Handle`]: Self::Handletype Handle: Clone;/// Returns the dimensions of an image for the given [`Handle`].fn measure_image(&self, handle: &Self::Handle) -> Size<u32>;/// Draws an [`Image`] inside the provided `bounds`.fn draw_image(&mut self, image: Image<Self::Handle>, bounds: Rectangle);
}
最终是在不同绘制库,有不同的具体实现。比如tiny_skia。则实现了image的特殊绘制接口,比如:
impl core::image::Renderer for Renderer {type Handle = core::image::Handle;fn measure_image(&self, handle: &Self::Handle) -> crate::core::Size<u32> {self.engine.raster_pipeline.dimensions(handle)}fn draw_image(&mut self, image: core::Image, bounds: Rectangle) {let (layer, transformation) = self.layers.current_mut();layer.draw_raster(image, bounds, transformation);}
}
下面开始分析一下程序运行的流程。
applaction是一个包装,核心是 raw: 的program。
struct Instance<State, Message, Theme, Renderer, Update, View> {update: Update,view: View,_state: PhantomData<State>,_message: PhantomData<Message>,_theme: PhantomData<Theme>,_renderer: PhantomData<Renderer>,}
这正run的函数是:
fn run(self,settings: Settings,window_settings: Option<window::Settings>,) -> ResultwhereSelf: 'static,Self::State: Default,{self.run_with(settings, window_settings, || {(Self::State::default(), Task::none())})}/// Runs the [`Program`] with the given [`Settings`] and a closure that creates the initial state.fn run_with<I>(self,settings: Settings,window_settings: Option<window::Settings>,initialize: I,) -> ResultwhereSelf: 'static,I: FnOnce() -> (Self::State, Task<Self::Message>) + 'static,{use std::marker::PhantomData;struct Instance<P: Program, I> {program: P,state: P::State,_initialize: PhantomData<I>,}impl<P: Program, I: FnOnce() -> (P::State, Task<P::Message>)>shell::Program for Instance<P, I>{type Message = P::Message;type Theme = P::Theme;type Renderer = P::Renderer;type Flags = (P, I);type Executor = P::Executor;fn new((program, initialize): Self::Flags,) -> (Self, Task<Self::Message>) {let (state, task) = initialize();(Self {program,state,_initialize: PhantomData,},task,)}fn title(&self, window: window::Id) -> String {self.program.title(&self.state, window)}fn update(&mut self,message: Self::Message,) -> Task<Self::Message> {self.program.update(&mut self.state, message)}fn view(&self,window: window::Id,) -> crate::Element<'_, Self::Message, Self::Theme, Self::Renderer>{self.program.view(&self.state, window)}fn subscription(&self) -> Subscription<Self::Message> {self.program.subscription(&self.state)}fn theme(&self, window: window::Id) -> Self::Theme {self.program.theme(&self.state, window)}fn style(&self, theme: &Self::Theme) -> Appearance {self.program.style(&self.state, theme)}fn scale_factor(&self, window: window::Id) -> f64 {self.program.scale_factor(&self.state, window)}}#[allow(clippy::needless_update)]let renderer_settings = crate::graphics::Settings {default_font: settings.default_font,default_text_size: settings.default_text_size,antialiasing: if settings.antialiasing {Some(crate::graphics::Antialiasing::MSAAx4)} else {None},..crate::graphics::Settings::default()};Ok(shell::program::run::<Instance<Self, I>,<Self::Renderer as compositor::Default>::Compositor,>(Settings {id: settings.id,fonts: settings.fonts,default_font: settings.default_font,default_text_size: settings.default_text_size,antialiasing: settings.antialiasing,}.into(),renderer_settings,window_settings,(self, initialize),)?)}
注意这里是program是在iced目录下。这里核心是调用winit的program,最关键的参数是(self, initialize)这个元组。这个参数是构成winit的program。
pub fn run<P, C>(settings: Settings,graphics_settings: graphics::Settings,window_settings: Option<window::Settings>,flags: P::Flags,
) -> Result<(), Error>whereP: Program + 'static,C: Compositor<Renderer = P::Renderer> + 'static,P::Theme: DefaultStyle,
{}
这个东西就比较复杂,这里主要核心是runtime模块通过userinterface管理关键的绘制工具,以及winit的库的消息进行绘制。
这个东西比较复杂,不再详细介绍。
后记
这里最关键的完整绘制winit申请绘制,以及绘制模块比如skia额绘制过程没有详细介绍,这里暂时不详细介绍了,等待以后有空再补充把。
相关文章:
iced源码分析
前言 iced是一个比较流行的UI库,设计思路还是挺有意思的,不过因为rust复杂的语法,这个库确实很难让一个不精通rust的开发者那么容易理解。这里记录下这几天的阅读源码心得。 正文 iced核心包括四个模块。 iced库,主要控制应用…...
Hadoop的MapReduce详解
文章目录 Hadoop的MapReduce详解一、引言二、MapReduce的核心概念1、Map阶段1.1、Map函数的实现 2、Reduce阶段2.1、Reduce函数的实现 三、MapReduce的执行流程四、MapReduce的使用实例Word Count示例1. Mapper类2. Reducer类3. 执行Word Count 五、总结 Hadoop的MapReduce详解…...
【Python系列】字典灵活的数据存储与操作
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
【MCU】微控制器的编程技术:ISP 与 IAP
在嵌入式领域中,将程序下载到内置 Flash 有两种技术 ISP (In-system programming) ISP 即在系统编程,是指一些可编程逻辑器件、微控制器、芯片组和其他嵌入式设备在安装到完整嵌入式系统后能够进行编程,而不需要在将芯片安装到系统中之前对…...
TCP/IP 协议:网络世界的基石(2/10)
一、引言 在当今数字化时代,互联网已经成为人们生活中不可或缺的一部分。而在互联网的背后,TCP/IP 协议扮演着至关重要的角色,堪称互联网的基石。 TCP/IP 协议是一组用于数据通信的协议集合,它的名字来源于其中最重要的两个协议…...
小R的二叉树探险 | 模拟
问题描述 在一个神奇的二叉树中,结构非常独特: 每层的节点值赋值方向是交替的,第一层从左到右,第二层从右到左,以此类推,且该二叉树有无穷多层。 小R对这个二叉树充满了好奇,她想知道…...
Redis ⽀持哪⼏种数据类型?适⽤场景,底层结构
目录 Redis 数据类型 一、String(字符串) 二、Hash(哈希) 三、List(列表) 四、Set(集合) 五、ZSet(sorted set:有序集合) 六、BitMap 七、HyperLogLog 八、GEO …...
十、事件类型(鼠标事件、焦点.. 、键盘.. 、文本.. 、滚动..)、事件对象、事件流(事件捕获、事件冒泡、阻止冒泡和默认行为、事件委托)
1. 事件类型 1.1 鼠标事件 1.1.1 click 鼠标点击 1.1.2 mouseenter 鼠标进入 1.1.3 mouseleave 鼠标离开 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widt…...
RabbitMQ学习-One
同步调用和异步调用 1.假设我们现在又两个服务,分别是修改商品服务和查询商品服务,每个服务都有自己的数据库; 2.左侧的流程假设我们总共需要耗时40ms; 3.因为不同服务数据库不一样,所以我们就要考虑修改了左边服务的…...
蓝队基础,网络七杀伤链详解
声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&#…...
机器学习实战:银行客户是否认购定期存款
项目结构与步骤 1. 项目概述 项目名称:葡萄牙银行电话营销活动分析与定期存款认购预测目标:通过分析银行的电话营销数据,构建模型预测客户是否会认购定期存款。数据来源:葡萄牙银行营销活动数据集关键挑战:数据不平衡…...
【一篇搞定配置】网络分析工具WireShark的安装与入门使用
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀各种软件安装与配置_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1.…...
气膜场馆照明设计:科技与环保的完美结合—轻空间
气膜场馆的照明设计,选用高效节能的400瓦LED灯具,结合现代节能技术,提供强大而均匀的光照。LED灯具在光效和寿命方面优势显著,不仅降低运营能耗,还有效减少碳排放,为绿色场馆建设贡献力量。 科学分布&…...
C语言程序编译和链接
编译环境和运行 编译环境也可以称为翻译环境,是将源代码转换为机器可以识别的二进制指令; 运行环境也可以称为执行环境,用于实际执行代码; 翻译环境 翻译环境由编译和链接两个部分组成,而编译又可以分解为&#x…...
springBoot整合 Tess4J实现OCR识别文字(图片+PDF)
1. 环境准备 JDK 8 或更高版本Maven 3.6 或更高版本Spring Boot 2.4 或更高版本Tesseract OCR 引擎Tess4J 库 2. 安装 Tesseract OCR 引擎 下载地址: Home UB-Mannheim/tesseract Wiki GitHub linux直接安装:sudo apt-get install tesseract-ocr 3.…...
阿里数字人工作 Emote Portrait Alive (EMO):基于 Diffusion 直接生成视频的数字人方案
TL;DR 2024 年 ECCV 阿里智能计算研究所的数字人工作,基于 diffusion 方法来直接的从音频到视频合成数字人,避免了中间的三维模型或面部 landmark 的需求,效果很好。 Paper name EMO: Emote Portrait Alive - Generating Expressive Portra…...
Java将PDF保存为图片
将 PDF 文件转换为图片是常见的需求之一,特别是在需要将 PDF 内容以图像形式展示或处理时。其中最常用的是 Apache PDFBox。 使用 Apache PDFBox Apache PDFBox 是一个开源的 Java 库,可以用来处理 PDF 文档。它提供了将 PDF 页面转换为图像的功能。 …...
医药企业的终端市场营销策略
近年来,随着医药行业的快速发展,终端市场逐渐成为企业竞争的关键领域。在政策趋严、市场环境变化以及数字化转型的大背景下,医药企业如何在终端市场中立于不败之地?本文结合我们在医药数字化领域的经验,为大家剖析终端…...
使用EFK收集k8s日志
首先我们使用EFK收集Kubernetes集群中的日志,本次实验讲解的是在Kubernetes集群中启动一个Elasticsearch集群,如果企业内已经有了Elasticsearch集群,可以直接将日志输出至已有的Elasticsearch集群。 文章目录 部署elasticsearch创建Kibana创建…...
Vue3 + TypeScript 项目搭建
Vue3 TypeScript 项目搭建 环境准备 首先确保你的开发环境满足以下要求: # 检查 Node.js 版本 (需要 14.0 或更高版本) node -v# 检查 npm 版本 npm -v# 安装或更新 Vue CLI npm install -g vue/cli创建项目 使用 Vue CLI 创建项目: # 创建项目 np…...
Python操作neo4j库py2neo使用(一)
Python操作neo4j库py2neo使用(一) 安装(只用于测试) docker-compose .yml 文件 version: 3.8 services:neo4j:image: neo4j:5.6.0-enterprise #商业版镜像hostname: neo4jcontainer_name: neo4jports:- "7474:7474"-…...
(原创)Android Studio新老界面UI切换及老版本下载地址
前言 这两天下载了一个新版的Android Studio,发现整个界面都发生了很大改动: 新的界面的一些设置可参考一些博客: Android Studio新版UI常用设置 但是对于一些急着开发的小伙伴来说,没有时间去适应,那么怎么办呢&am…...
Linux——用户级缓存区及模拟实现fopen、fweite、fclose
linux基础io重定向-CSDN博客 文章目录 目录 文章目录 什么是缓冲区 为什么要有缓冲区 二、编写自己的fopen、fwrite、fclose 1.引入函数 2、引入FILE 3.模拟封装 1、fopen 2、fwrite 3、fclose 4、fflush 总结 前言 用快递站讲述缓冲区 收件区(类比输…...
CKA认证 | Day2 K8s内部监控与日志
第三章 Kubernetes监控与日志 1、查看集群资源状态 在 Kubernetes 集群中,查看集群资源状态和组件状态是非常重要的操作。以下是一些常用的命令和解释,帮助你更好地管理和监控 Kubernetes 集群。 1.1 查看master组件状态 Kubernetes 的 Master 组件包…...
大模型部署,运维,测试所需掌握的知识点
python环境部署: python3 -m site --user-base 返回用户级别的Python安装基础目录 sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 将python3的默认路径/usr/bin/python3替…...
JDBC编程---Java
目录 一、数据库编程的前置 二、Java的数据库编程----JDBC 1.概念 2.JDBC编程的优点 三.导入MySQL驱动包 四、JDBC编程的实战 1.创造数据源,并设置数据库所在的位置,三条固定写法 2.建立和数据库服务器之间的连接,连接好了后ÿ…...
什么是沙箱(Sandbox)技术
沙箱技术是一种重要的计算机安全机制,主要用于隔离程序运行环境,以防止恶意代码或应用程序对系统和数据造成破坏。通过限制代码的访问权限和行为,沙箱为程序提供了一个受控且隔离的执行环境。 核心特点 隔离性沙箱运行的程序被限制在一个受控…...
TCP socket api详解
文章目录 netstat -nltpaccept简单客户端工具 telnet 指定服务连接connect异常处理version 1 单进程版version 2 多进程版version 3 -- 多线程版本version 4 ---- 线程池版本 创建套接字socket sockaddr_in结构体 bind 之后就和UDP不一样了。 因为TCP是一个面向连接的服务器&…...
Linux——环境变量
环境变量一般指的是在操作系统重用来指定操作系统运行环境的一些参数,这些参数会被bash使用,而bash是被我们用户使用的,也就是说,这些环境变量间接的也是被我们用户使用的。环境变量通常都有某些特殊的用途,它在系统重…...
Windows Pycharm 远程 Spark 开发 PySpark
一、环境版本 环境版本PyCharm2024.1.2 (Professional Edition)Ubuntu Kylin16.04Hadoop3.3.5Hive3.1.3Spark2.4.0 二、Pycharm远程开发 文件-远程-开发 选择 SSH连接,连接虚拟机,选择项目目录即可远程开发...
【es6进阶】vue3中的数据劫持的最新实现方案的proxy的详解
vuejs中实现数据的劫持,v2中使用的是Object.defineProperty()来实现的,在大版本v3中彻底重写了这部分,使用了proxy这个数据代理的方式,来修复了v2中对数组和对象的劫持的遗留问题。 proxy是什么 Proxy 用于修改某些操作的默认行为࿰…...
【Isaac Sim】加载自带模型或示例时报 Isaac Sim is not responding
Isaac Sim对电脑配置要求很高,开机第一次打开 Isaac Sim 时,直接就报 Isaac Sim is not responding 卡死了,这是由于第一次需要加载一些资源,耗时会导致 Isaac Sim 无响应,这里等一会会自动给回复。 加载自带模型或示…...
React (三)
文章目录 项目地址十二、性能优化12.1 使用useMemo避免不必要的计算12.2 使用memo缓存组件,防止过度渲染12.3 useCallBack缓存函数12.4 useCallBack里访问之前的状态(没懂)十三、Styled-Components13.1 安装13.2给普通html元素添加样式13.3 继承和覆盖样式13.4 给react组件添…...
C0031.在Clion中使用mingw编译器来编译opencv的配置方法
mingw编译器编译opencv库的配置方法...
多目标跟踪算法
文章目录 一、传统方法1. 基于卡尔曼滤波器的方法1.1 Kalman Filter(卡尔曼滤波器) 2. 基于数据关联的方法2.1 匈牙利算法 二、深度学习方法1. 基于检测的多目标跟踪1.1 SORT算法1.2 DeepSort1.3 BoT-SORT 2. 基于特征关联和增强的方法2.1 ByteTrack 3. 基于Transformer的方法3…...
【CSS in Depth 2 精译_059】9.2 把 CSS 模块组合成更大的结构
当前内容所在位置(可进入专栏查看其他译好的章节内容) 【第九章 CSS 的模块化与作用域】 ✔️ 9.1 模块的定义 9.1.1 模块和全局样式9.1.2 一个简单的 CSS 模块9.1.3 模块的变体9.1.4 多元素模块 9.2 将模块组合为更大的结构 ✔️ 9.2.1 模块中多个职责的…...
uniapp+vue3+ts H5端使用Quill富文本插件以及解决上传图片反显的问题
uniappvue3ts H5端使用Quill富文本插件以及解决上传图片反显的问题 1.在项目中安装Quill npm i quill1.3.72.需要显示富文本的页面完整代码 <template><view><div ref"quillEditor" style"height: 65vh"></div></view> &…...
shell(二)
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
在使用PCA算法进行数据压缩降维时,如何确定最佳维度是一个关键问题?
一、PCA算法的基本原理 PCA算法的核心思想是通过正交变换,将一组可能相关的变量转换成一组线性不相关的变量,称为主成分。这组主成分能够以最小的信息损失来尽可能多地保留原始数据集的变异性。具体来说,PCA算法包括以下几个步骤:…...
学习嵩山版《Java 开发手册》:编程规约 - 命名风格(P1 ~ P2)
概述 《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结,他旨在提升开发效率和代码质量 《Java 开发手册》是一本极具价值的 Java 开发规范指南,对于提升开发者的综合素质和代码质量具有重要意义 学习《Java 开发手册》是一个提升 Jav…...
#渗透测试#红蓝攻防#HW#SRC漏洞挖掘01之静态页面渗透
免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停…...
开源POC库推荐
声明 学习视频来自 B 站UP主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 ✍🏻作者简介:致…...
深度学习每周学习总结J6(ResNeXt-50 算法实战与解析 - 猴痘识别)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 目录 0. 总结ResNeXt基本介绍 1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数:定义损失函数&…...
用vite下载的react + TS的项目,组件会调用两次
解决方案: 去掉main.tsx文件中的StrictMode...
STM32F4----DCA数字量转换成模拟量
STM32F4----DCA数字量转换成模拟量 基本原理 上一节讲诉了ADC的具体原理与程序搭建https://blog.csdn.net/qq_35970934/article/details/143999874?spm1001.2014.3001.5501。这节讲DAC的原理和程序,在实际应用中,我们经常需要调节电压的输出大小&…...
springboot3如何集成knife4j 4.x版本及如何进行API注解
1. 什么是Knife4j knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案, 取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍!knife4j的前身是swagger-bootstrap-ui,swagger-bootstrap-ui自1.9.6版本后,正式更名为knife4j为了契合微服务的架构发展,由于原来…...
【Linux网络 (二)】套接字编程
Linux: 网络 一、前言二、端口号 (port)1)port、套接字概念2)端口号 vs 进程id3)端口号和进程关系 三、认识TCP/Udp协议1)连接性解释2)可靠性解释3)面向数据报/字节流解释 四、网络字节序五、struct sockad…...
SQL 语句执行计划中的连接方式
SQL 语句执行计划中的连接方式 join操作 join操作基本分为3大类:外连接(细分为:左连接(Left outer join/ left join)、右连接(right outer join/ right join)、全连接(full outer …...
3、集线器、交换机、路由器、ip的关系。
集线器、交换机、路由器三者的关系 1、集线器2、交换机(每个交换机是不同的广播域,ip地址起到划分广播域的作用)3、 路由器4、ip地址 1、集线器 一开始两台电脑通信就需要网线就可以,但是三台或者更多主机通信时,就需…...
OpenCV相机标定与3D重建(3)校正鱼眼镜头畸变的函数calibrate()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::fisheye::calibrate 函数是 OpenCV 中用于校正鱼眼镜头畸变的一个重要函数。该函数通过一系列棋盘格标定板的图像来计算相机的内参矩阵和畸变…...