opencv-rust 系列2: camera_calibration

news2024/10/12 6:53:31

opencv-rust 系列2: camera_calibration

前言: 这里只是opencv-rust自带示例的中文注解. 略微增加了一些代码也是我在调试时用到的.

说明:

  1. camera_calibration.rs是opencv-rust自带的示例, 在examples目录中可以找到,我增加了一些中文注释如下.
  2. 如需运行可以在项目根目录执行命令: cargo run --example camera_calibration
  3. 在vscode软件内点击main函数上方绿色三角"Run"运行程序时, 当前位置是项目的根目录.
  4. 在命令行使用cargo run运行程序时, 当前位置是命令行所处目录.
  5. 为了保持统一,我使用项目根目录为当前目录设定, 所以运行本程序一定要在项目根目录.
  6. 使用highgui::imshow("Source", &img)?;显示窗口时不要使用中文!!! 建议 opencv 程序都不要使用中文.
  7. 文末贴两张图,你可以下载后以jpg后缀名保存到./examples/data目录,以供程序运行使用.
  8. 当然,Cargo.toml中需包含:
[dependencies]
opencv = "0.93.1"
  1. 源代码如下:
//! Port of code from the tutorial at: https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html

use std::error::Error;
use std::fs;
use opencv::core::{no_array, Point2f, Point3f, Size, TermCriteria, TermCriteria_EPS, TermCriteria_MAX_ITER, Vector};
use opencv::prelude::*;
use opencv::{calib3d, highgui, imgcodecs, imgproc};
use std::env;

fn main() -> Result<(), Box<dyn Error>> {

	// 获取当前工作目录
	let current_dir = env::current_dir().expect("无法获取当前目录");
	// 打印当前工作目录的路径
	println!("当前路径: {}", current_dir.display());

	// 设置校准的终止条件,包括最大迭代次数和最小精度
	let criteria = TermCriteria {
		typ: TermCriteria_EPS + TermCriteria_MAX_ITER, 	// 终止条件类型
		max_count: 30,									// 最大迭代次数
		epsilon: 0.001,									// 精度阈值
	};

	// 准备三维世界中的物体点,例如棋盘格的角点, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
	let objp_len = 6 * 7;	// 棋盘格的尺寸为6x7
	let objp = Vector::from_iter((0..objp_len).map(|i| Point3f::new(
		(i % 7) as f32, 	// x坐标
		(i / 7) as f32, 	// y坐标
		0.)));				// z坐标,假设棋盘格位于z=0的平面上

	// 读取当前目录下所有.jpg文件
	let images = fs::read_dir("./examples/data")?
		.into_iter()
		.flatten()
		.filter(|entry| entry.path().extension().map_or(false, |ext| ext == "jpg"));

	//对每张图片进行校正
	for image in images {
		// 初始化用于存储所有图像的物体点和图像点的数组
		let mut objpoints = Vector::<Vector<Point3f>>::new(); // 三维世界中的点
		let mut imgpoints = Vector::<Vector<Point2f>>::new(); // 图像平面中的点
		
		// 读取原始图像并显示 
		println!("准备读取图片: {}", image.path().to_string_lossy());
		let mut img = imgcodecs::imread_def(image.path().to_string_lossy().as_ref())?; 
		highgui::imshow("Origin", &img)?;
		highgui::wait_key(5000)?;

		
		let mut gray = Mat::default();
		// 将图像转换为灰度图
		imgproc::cvt_color_def(&img, &mut gray, imgproc::COLOR_BGR2GRAY)?;

		let mut corners = Vector::<Point2f>::default();
		// 在灰度图中查找棋盘格角点
		let ret = calib3d::find_chessboard_corners_def(&gray, Size::new(7, 6), &mut corners)?;
		if ret {
			println!("找到角点, 正在对该图校正");
			// 如果找到了角点,将其添加到物体点数组
			objpoints.push(objp.clone()); 
			// 使用亚像素级精度细化角点位置
			imgproc::corner_sub_pix(&gray, &mut corners, Size::new(11, 11), Size::new(-1, -1), criteria)?;

			// 在图像上绘制角点并显示
			calib3d::draw_chessboard_corners(&mut img, Size::new(7, 6), &corners, ret)?;
			highgui::imshow("Source", &img)?;
			// 将角点添加到图像点数组
			imgpoints.push(corners);

			// 相机校准
			let mut mtx = Mat::default();			// 相机内参矩阵
			let mut dist = Mat::default();			// 畸变系数
			let mut rvecs = Vector::<Mat>::new();	// 旋转向量
			let mut tvecs = Vector::<Mat>::new();	// 平移向量
			calib3d::calibrate_camera_def(
				&objpoints,
				&imgpoints,
				gray.size()?,
				&mut mtx,
				&mut dist,
				&mut rvecs,
				&mut tvecs,
			)?;

			//下面使用两种方法去除图像的畸变:
			// 方法1,使用cv.undistort()去除图像畸变
			let mut dst_undistort = Mat::default();
			calib3d::undistort_def(&img, &mut dst_undistort, &mtx, &dist)?;
			highgui::imshow("Result using undistort", &dst_undistort)?;

			// 方法2,使用remapping方法去除图像畸变
			let mut mapx = Mat::default();
			let mut mapy = Mat::default();
			calib3d::init_undistort_rectify_map(
				&mtx,
				&dist,
				&no_array(),
				&no_array(),
				img.size()?,
				f32::opencv_type(),
				&mut mapx,
				&mut mapy,
			)?;
			let mut dst_remap = Mat::default();
			imgproc::remap_def(&img, &mut dst_remap, &mapx, &mapy, imgproc::INTER_LINEAR)?;
			// 显示使用remap方法去畸变后的结果
			highgui::imshow("Result using remap", &dst_undistort)?;

			// 等待按键,然后继续处理下一张图像
			highgui::wait_key_def()?;
		}else {
			println!("没有找到角点, 该图不能进行校正");
		}
	}
	// 销毁所有OpenCV创建的窗口
	highgui::destroy_all_windows()?;
	Ok(())
}

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt第三课 ----------显示类的控件属性

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

从0开始深度学习(8)——softmax回归

1 分类问题 深度学习从大方向上来说&#xff0c;就是回归预测和分类问题。 假设输入一个 2 ∗ 2 2*2 2∗2的灰度图像&#xff0c;可能属于“鸡、猫、狗”三个类别中的一个&#xff0c;那如何在计算机中表示标签呢&#xff1f;最常见的想法是 y { 1 , 2 , 3 } y \{1,2,3\} y{…

现金1.8kw, 年入150w, 财务不自由...

他的生活状态无疑是许多人梦寐以求的。拥有两套无贷款的房产&#xff0c;家庭和睦&#xff0c;两台车价值约50万元。现金资产高达1800万元&#xff0c;家庭年收入约150万元&#xff0c;职业稳定&#xff0c;属于中层管理阶层。 重要的是&#xff0c;孩子们的成绩优异&#xff0…

ListView的Items绑定和comboBox和CheckBox组合使用实现复选框的功能

为 ListView 控件的内容指定视图模式的方法&#xff0c;参考官方文档。 ComboBox 样式和模板 案例说明&#xff1a;通过checkBox和ComboBox的组合方式实现下拉窗口的多选方式&#xff0c;同时说明了ListView中Items项目的两种绑定方式. 示例&#xff1a; 设计样式 Xaml代码…

机器学习 | 特征选择如何减少过拟合?

在快速发展的机器学习领域&#xff0c;精确模型的开发对于预测性能至关重要。过度拟合的可能性&#xff0c;即模型除了数据中的潜在模式外&#xff0c;还拾取训练集特有的噪声和振荡&#xff0c;这是一个固有的问题。特征选择作为一种有效的抗过拟合武器&#xff0c;为提高模型…

好用,易用,高效,稳定 基于opencv 的 图像模板匹配 - python 实现

在定位、搜索固定界面图块时&#xff0c;经常用到模板匹配&#xff0c;opencv自带的图像模板匹配好用&#xff0c;易用&#xff0c;高效&#xff0c;稳定&#xff0c;且有多种匹配计算方式。 具体示例如下&#xff1a; 模板图&#xff1a; 待搜索图&#xff1a; 具体实现代码…

苹果正式宣布:iPhone全面开放近场通信(Near Field Communication,简称NFC)【使用安全元件提供app内NFC数据交换功能】

文章目录 引言I iPhone的NFC功能开发者用户数据交换的体验革新安全与隐私II 知识扩展:近场通信(NFC)技术钱包NFC开关打开读取NFC标签(NFC tags )权限demo引言 2014年iPhone 6开始,苹果首次引入了NFC功能,但最初只允许自家的Apple Pay进行移动支付。慢慢地适配了交通卡,增…

基于go开发的终端版即时通信系统(c-s架构)

项目架构图 类似一个聊天室一样 整体是一个客户端和服务端之间的并发多线程网络通信&#xff0c;效果可以翻到最后面看。 为了巩固基础的项目练手所以分为9个阶段进行迭代开发 版本⼀&#xff1a;构建基础Server 新建一个文件夹就叫golang-IM_system 第一阶段先将server的大…

沈阳化工大学第十一届程序设计沈阳区竞赛:凿冰 Action(博弈论,思维)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 北极探险队有新收获了&#xff01;&#xff01;&#xff01; 北极探险队发现了NNN条长度不一的冰柱&#xff0c;由于冰柱里封存有价值的生物&#xff0c;现在需要两名生物学家小A和小…

TON生态小游戏开发:推广、经济模型与UI设计的建设指南

随着区块链技术的快速发展&#xff0c;基于区块链的Web3游戏正引领行业变革。而TON生态小游戏&#xff0c;借助Telegram庞大的用户基础和TON&#xff08;The Open Network&#xff09;链上技术&#xff0c;已成为这一领域的明星之一。国内外开发者正迅速涌入&#xff0c;开发和…

如何在算家云搭建Kolors(图像生成)

一、模型介绍 Kolors 是快手 Kolors 团队基于潜在扩散的大规模文本转图片生成模型。经过数十亿个文本-图片对的训练&#xff0c;Kolors 在视觉质量、复杂语义准确性和中英文文本渲染方面均比开源和闭源模型具有显著优势。此外&#xff0c;Kolors 支持中英文输入&#xff0c;在…

C语言基础语法——类型转换

数据有不同的类型&#xff0c;不同类型数据之间进行混合运算时涉及到类型的转换问题。 转换的方法有两种&#xff1a; 自动类型转换&#xff08;隐式转换&#xff09;&#xff1a;遵循一定的规则&#xff0c;由编译系统自动完成强制类型转换&#xff08;显示转换&#xff09;…

http协议概述与状态码

目录 1.HTTP概述 1.1请求报文起始行与开头 ​1.2响应报文起始行 ​ 1.3响应报文开头 ​ 2.http状态协议码 1.HTTP概述 默认端口 80 HTTP超文本传输与协议: 数据请求和响应 传输:将网站的数据传递给用户 超文本:图片 视频等 请求request:打开网站 访问网站 响应r…

Python数据分析-垃圾邮件分类

一、研究背景 随着电子通信技术的飞速发展&#xff0c;电子邮件已经成为人们日常工作和生活中不可或缺的一部分。然而&#xff0c;伴随着这一趋势&#xff0c;垃圾邮件&#xff08;Spam&#xff09;的数量也在急剧增加。垃圾邮件不仅会占用用户的邮箱空间&#xff0c;还可能含…

设置dl服务解决github pushTimed out问题

提交代码到GitHub&#xff0c;一直提示提交失败 我们一般是fq挂的dl服务器进行的&#xff0c;而git需要配置下dl&#xff0c;此时我们要将dl服务器对应的IP地址和端口为我们所调用。 查找dl服务器&#xff08;windows直接搜索dl服务器设置&#xff0c;mac参考官网&#xff09…

【北京迅为】《STM32MP157开发板嵌入式开发指南》-第二十二章 安装VMware Tool 工具

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

学习python自动化——pytest单元测试框架

一、什么是pytest 单元测试框架&#xff0c;unittest&#xff08;python自带的&#xff09;&#xff0c;pytest&#xff08;第三方库&#xff09;。 用于编写测试用例、收集用例、执行用例、生成测试结果文件&#xff08;html、xml&#xff09; 1.1、安装pytest pip instal…

【ARM Linux驱动开发】嵌入式ARM Linux驱动开发基本步骤

【ARM Linux驱动开发】嵌入式ARM Linux驱动开发基本步骤 文章目录 开发环境驱动开发&#xff08;以字符设备为例&#xff09;安装驱动应用程序开发附录&#xff1a;压缩字符串、大小端格式转换压缩字符串浮点数压缩Packed-ASCII字符串 开发环境 首先需要交叉编译器和Linux环境…

豆包PixelDance指南:字节跳动推出的AI视频生成大模型,突破多主体互动难关

豆包PixelDance是由字节跳动旗下火山引擎发布的AI视频生成大模型。它是业界首个突破多主体互动难关的视频生成模型&#xff0c;支持多风格多比例的一致性多镜头生成。PixelDance基于DiT架构&#xff0c;具备高效的DiT融合计算单元&#xff0c;能够实现复杂的多主体运动交互和多…

【高等数学】 一元函数积分学

1. 不定积分的计算 1.1. 基本积分表 知识点 例题 1.2. 凑微分&#xff08;第一类换元法&#xff09; 知识点 本质&#xff1a;利用复合函数求导法则的逆运算 第一步&#xff0c;识别或者凑出来复合函数的导函数 如果被积函数具备以下特点&#xff1a; 1.它由两项相乘来表…