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

OpenCV单目相机内参标定C++

基于OpenCV 实现单目相机内参标定:

a.使用OpenCV实现内参标定过程。通过角点检测、亚像素角点定位、角点存储与三维坐标生成和摄像机标定分别获取左右相机的内参

b.具体地,使用库函数检测两组图像(左右相机拍摄图像)中棋盘格的角点;对检测到的角点进行亚像素级别的精确化,以提高角点位置的准确性;根据左右相机拍摄的棋盘格图像及角点位置,计算出两个相机的内参矩阵及畸变系数;生成畸变校正和图像校正的映射表

c.内参标定模块的输出是左右相机的内参矩阵和畸变系数,以及每幅图像的旋转向量和平移向量,最后计算并输出标定结果的总体平均误差,以评估标定过程的准确性。

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>
#include<sstream>
#include<opencv2/imgproc/types_c.h> 
#include <opencv2/core/utils/logger.hpp> //隐藏日志using namespace std;
using namespace cv;
int main()
{cv::utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//不再输出日志//或//utils::logging::setLogLevel(utils::logging::LOG_LEVEL_ERROR);//只输出错误日志int image_count = 20;//检测的图片数量Size image_size;Size board_size = Size(11, 8);//图片上棋盘格(标定板)的内角点个数(行、列的角点数)vector<Point2f> image_corners;//缓存每幅图像上检测到的角点vector<vector<Point2f>> corners_Seq;//保存检测到的所有角点vector<Mat> image_Seq;int count = 0;/*********************读入图像,检测角点********************************************/for (int i = 0; i < image_count; i++){//读入一系列图片string imageFileName, imageFileName1;stringstream StrStm;StrStm << "left";//StrStm << "F:/vsprojects2022/ConsoleApplication6/ConsoleApplication6/20241022/right";StrStm << i + 1;StrStm >> imageFileName;StrStm.str("");//清除数据流,以便下次使用imageFileName += ".bmp";cout << imageFileName << endl;Mat image = imread(imageFileName);image_size = image.size();Mat image_gray;Mat dstImage1;//cvtColor(image, image_gray, CV_RGB2GRAY); // opencv4版本中应改为 COLOR_RGB2GRAYcvtColor(image, image_gray, COLOR_RGB2GRAY);/*imshow("1",image_gray);waitKey(0);*///检测标定板的角点bool patternfound = findChessboardCorners(image, board_size, image_corners, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE);//+ CALIB_CB_FAST_CHECK);if (!patternfound){cout << "Can not find chessboard corners!" << endl;return -1;}else{/* 亚像素精确化 */cornerSubPix(image_gray, image_corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));/* 绘制检测到的角点并保存 *//*drawChessboardCorners(image, Size(7, 7), image_corners, patternfound);//红色为先检测的点resize(image, dstImage1, Size(image.cols / 5, image.rows / 5), 0, 0, INTER_LINEAR);imshow("1", dstImage1);waitKey(0);*/Mat imageTemp = image.clone();for (int j = 0; j < image_corners.size(); j++){circle(imageTemp, image_corners[j], 3, Scalar(0, 0, 255), -1, 8, 0);}string imageFileName;std::stringstream StrStm;StrStm << i + 1;StrStm >> imageFileName;imageFileName += "_corner.jpg";imwrite(imageFileName, imageTemp);//保存角点检测结果图count = count + image_corners.size();corners_Seq.push_back(image_corners);}image_Seq.push_back(image);}/****************************摄像机标定****************************************/Size square_size = Size(50, 50);                                      /**** 实际测量得到的标定板上每个棋盘格的大小   ****/vector<vector<Point3f>>  object_Points;                                      /****  保存标定板上角点的三维坐标   ****/Mat image_points = Mat(1, count, CV_32FC2, Scalar::all(0));          /*****   保存提取的所有角点   *****/vector<int>  point_counts;                                          /*****    每幅图像中角点的数量    ****/Mat intrinsic_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0));                /*****    摄像机内参数矩阵    ****///Mat distortion_coeffs = Mat(1, 4, CV_32FC1, Scalar::all(0));            /* 摄像机的4个畸变系数:k1,k2,p1,p2 */Mat distortion_coeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));            /* 摄像机的4个畸变系数:k1,k2,p1,p2 */vector<cv::Mat> rotation_vectors;                                      /* 每幅图像的旋转向量 */vector<cv::Mat> translation_vectors;                                  /* 每幅图像的平移向量 *//* 初始化标定板上角点的三维坐标 */for (int t = 0; t < image_count; t++){vector<Point3f> tempPointSet;for (int i = 0; i < board_size.height; i++){for (int j = 0; j < board_size.width; j++){/* 假设标定板放在世界坐标系中z=0的平面上 */Point3f tempPoint;tempPoint.x = i * square_size.width;tempPoint.y = j * square_size.height;tempPoint.z = 0;tempPointSet.push_back(tempPoint);}}object_Points.push_back(tempPointSet);}/* 初始化每幅图像中的角点数量,这里我们假设每幅图像中都可以看到完整的标定板 */for (int i = 0; i < image_count; i++){point_counts.push_back(board_size.width * board_size.height);}/*************************开始标定 *******************************///根据角点的世界坐标和像素坐标求参数calibrateCamera(object_Points, corners_Seq, image_size, intrinsic_matrix, distortion_coeffs, rotation_vectors, translation_vectors, 0);/***********************显示标定结果***************************/Mat rotation_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 保存每幅图像的旋转矩阵 */cout << "相机的内参矩阵" << intrinsic_matrix << endl;cout << "相机的畸变系数" << distortion_coeffs << endl;ofstream outfile;outfile.open("内参标定结果.txt");outfile << "相机的内参矩阵为:" << endl << intrinsic_matrix << endl;outfile << "相机的畸变系数为:" << endl << distortion_coeffs << endl;outfile.close();cout << "输出每幅图的旋转向量和平移向量" << endl;for (int i = 0; i < image_count; i++){cout << "第" << i + 1 << "幅图的旋转向量" << rotation_vectors[i] << endl;/* 将旋转向量转换为相对应的旋转矩阵 */Rodrigues(rotation_vectors[i], rotation_matrix);cout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;cout << rotation_matrix << endl;cout << "第" << i + 1 << "幅图像的平移向量:" << endl;cout << translation_vectors[i] << endl;}/******************对标定结果进行评价**********************************/cout << "开始评价标定结果………………" << endl;double total_err = 0.0;                   /* 所有图像的平均误差的总和 */double err = 0.0;                        /* 每幅图像的平均误差 */vector<Point2f>  image_points2;             /****   保存重新计算得到的投影点    ****/for (int i = 0; i < image_count; i++){vector<Point3f> tempPointSet = object_Points[i];/****    通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点     ****/projectPoints(tempPointSet, rotation_vectors[i], translation_vectors[i], intrinsic_matrix, distortion_coeffs, image_points2);/* 计算新的投影点和旧的投影点之间的误差*/vector<Point2f> tempImagePoint = corners_Seq[i];Mat tempImagePointMat = Mat(1, tempImagePoint.size(), CV_32FC2);Mat image_points2Mat = Mat(1, image_points2.size(), CV_32FC2);for (size_t i = 0; i != tempImagePoint.size(); i++){image_points2Mat.at<Vec2f>(0, i) = Vec2f(image_points2[i].x, image_points2[i].y);tempImagePointMat.at<Vec2f>(0, i) = Vec2f(tempImagePoint[i].x, tempImagePoint[i].y);}err = norm(image_points2Mat, tempImagePointMat, NORM_L2);total_err += err /= point_counts[i];cout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;}cout << "总体平均误差:" << total_err / image_count << "像素" << endl;Mat mapx = Mat(image_size, CV_32FC1);Mat mapy = Mat(image_size, CV_32FC1);Mat R = Mat::eye(3, 3, CV_32F);cout << "保存校正图像" << endl;for (int i = 0; i != image_count; i++){Mat newCameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));//根据标定结果进行图像的修正initUndistortRectifyMap(intrinsic_matrix, distortion_coeffs, R, getOptimalNewCameraMatrix(intrinsic_matrix, distortion_coeffs, image_size, 1, image_size, 0), image_size, CV_32FC1, mapx, mapy);Mat t = image_Seq[i].clone();cv::remap(image_Seq[i], t, mapx, mapy, INTER_LINEAR);string imageFileName;std::stringstream StrStm;StrStm << i + 1;StrStm >> imageFileName;imageFileName += "_校正后图像.jpg";imwrite(imageFileName, t);//保存畸变校正结果图}cout << "保存结束" << endl;//waitKey(0);system("pause");return 0;
}

代码运行结果如下: 

相关文章:

OpenCV单目相机内参标定C++

基于OpenCV 实现单目相机内参标定&#xff1a; a.使用OpenCV库实现内参标定过程。通过角点检测、亚像素角点定位、角点存储与三维坐标生成和摄像机标定分别获取左右相机的内参。 b.具体地&#xff0c;使用库函数检测两组图像&#xff08;左右相机拍摄图像&#xff09;中棋盘格…...

基于MATLAB(DCT DWT)

第三章 图像数字水印的方案 3.1 图像数字水印的技术方案 在数据库中存储在国际互联网上传输的水印图像一般会被压缩&#xff0c;有时达到很高的压缩比。因此&#xff0c;数字水印算法所面临的第一个考验就是压缩。JPEG和EZW&#xff08;Embedded Zero-Tree Wavelet&#xff0…...

渗透基础-rcube_webmail版本探测

简介 本文介绍了开源产品RoundCube webmail邮件系统的版本探测思路&#xff0c;并用go语言实现工具化、自动化探测。 正文 0x01 探测思路研究 探测系统版本&#xff0c;最理想的方法就是系统主页html代码中有特定的字符串&#xff0c;比如特定版本对应的hash在主页的html代…...

linux下编译鸿蒙版boost库

我在上一篇文章中介绍了curl和openssl的编译方式&#xff08;linux下编译鸿蒙版curl、openssl-CSDN博客&#xff09;&#xff0c;这篇再介绍一下boost库的编译。 未经许可&#xff0c;请勿转载&#xff01; 一.环境准备 1.鸿蒙NDK 下载安装方式可以参考上篇文章&#xff0c…...

滚雪球学Redis[6.3讲]:Redis分布式锁的实战指南:从基础到Redlock算法

全文目录&#xff1a; &#x1f389;前言&#x1f6a6;Redis分布式锁的概念与应用场景&#x1f343;1.1 什么是分布式锁&#xff1f;&#x1f342;1.2 应用场景 ⚙️使用Redis实现分布式锁&#x1f33c;2.1 基本思路&#x1f33b;2.2 示例代码&#x1f940;2.3 代码解析 &#…...

springboot二手汽车交易平台-计算机毕业设计源码82053

目录 1 绪论 1.1研究背景 1.2研究意义 1.3国内外研究现状 2 二手汽车交易平台系统分析 2.1 可行性分析 2.2 系统流程分析 2.3 功能需求分析 2.4 性能需求分析 3 二手汽车交易平台概要设计 3.1 系统体系结构设计 3.2总体功设计 3.3子模块设计设计 3.4 数据库设计 …...

typescript 中的类型推断

在 TypeScript 中&#xff0c;类型推断&#xff08;Type Inference&#xff09;是一种编译器自动确定变量或表达式类型的能力。这大大减少了需要显式声明类型的代码量&#xff0c;使得代码更加简洁和易读。TypeScript 的类型推断机制非常强大&#xff0c;可以在很多情况下自动推…...

linux 隐藏文件

在Linux中&#xff0c;隐藏文件以点&#xff08;.&#xff09;开头的文件或文件夹被认为是隐藏文件。隐藏文件通常用于存储系统配置文件或敏感文件。 以下是几种不同的方法来隐藏文件或文件夹&#xff1a; 方法1&#xff1a;在文件或文件夹名字前面加上点&#xff08;.&#…...

【网络协议栈】Tcp协议(上)结构的解析 和 Tcp中的滑动窗口(32位确认序号、32位序号、4位首部长度、6位标记位、16为窗口大小、16位紧急指针)

绪论​ “没有那么多天赋异禀&#xff0c;优秀的人总是努力翻山越岭。”本章主要讲到了再五层网络协议从上到下的第二层传输层中使用非常广泛的Tcp协议他的协议字段结构&#xff0c;通过这些字段去认识其Tcp协议运行的原理底层逻辑和基础。后面将会再写一篇Tcp到底是通过什么调…...

手表玻璃盖板视觉贴合

在手表生产过程中&#xff0c;贴合加工是一个至关重要的环节&#xff0c;它涉及将手表的盖板与LCM模组或各种功能片进行精准贴合。这一过程不仅要求高度的精度&#xff0c;还追求效率与稳定性&#xff0c;以满足现代可穿戴设备日益增长的市场需求。然而&#xff0c;当前行业在这…...

电信和互联网行业数据安全评估师CCRC-DSA人才强基计划

“电信和互联网行业数据安全人才强基计划”&#xff08;以下简称“强基计划”&#xff09;自 2022 年 4 月启动伊始&#xff0c;始终秉持以人才需求为导向&#xff0c;以体系化能力建设为重点&#xff0c;扎实铸就数据安全人才培养品牌&#xff0c;力促行业数据安全人才培养工作…...

MQTTnet 4.3.7.1207 (最新版)使用体验,做成在线客服聊天功能,实现Cefsharp的物联的功能(如远程打开新网址)

一、MQTTnet 4.3.x版本客户端 将客户端集成到 cefsharp 定制浏览器中,实现物联网功能 网上很多代码是3.x版本代码,和4.x版本差异性较大,介绍较为简单或不系统 二、部分代码说明 初始化,初始化》连接服务端》发布上线信息(遗嘱)ConnectAsync等 订阅主题:SubscribeAsync 接…...

将java项目jar包打包成exe服务

1.结构展示 2.注意事项 前提: 环境准备:jdk8 和 .net支持 { 1.控制面板》程序和功能》启用和关闭windows功能》.net的勾选》2.jdk8自行百度安装环境3.其他项目必须的软件环境安装等&#xff08;数据库...&#xff09; }第一次准备: 1.将打包好的jar包放到premiumServices.exe…...

Django请求响应对象

在 Django 中&#xff0c;请求&#xff08;request&#xff09;和响应&#xff08;response&#xff09;对象是处理 HTTP 请求和返回 HTTP 响应的核心。它们分别由 Django 的 HttpRequest 和 HttpResponse 类表示。 HttpRequest 对象 HttpRequest 对象包含了客户端发送的所有…...

DevExpress中文教程 - 如何在静态SSR模式下使用Blazor Drawer组件?

Microsoft的 .NET 8 UI框架引入了静态服务器端呈现模式&#xff08;静态SSR&#xff09;——组件在服务器端呈现&#xff0c;然后返回到客户端&#xff0c;没有任何交互&#xff0c;DevExpress Blazor Drawer组件需要交互式呈现模式来动态地改变其IsOpen状态。 在本文中&#…...

商汤科技十周年公布新战略,将无缝集成算力、模型及应用

10月18日&#xff0c;恰逢商汤科技十周年庆典&#xff0c;“2024商汤十周年国际论坛&#xff1a;迈向AI 2.0共融新时代”在香港科学园成功举办。 据「TMT星球」了解&#xff0c;来自全球的行业领袖、政府代表、AI专家共聚于此&#xff0c;共同探讨AI行业的未来。 活动上&…...

【如何获取股票数据07】Python、Java等多种主流语言实例演示获取股票行情api接口之沪深A股历史分时MA数据获取实例演示及接口API说明文档

最最近一两年内&#xff0c;股票量化分析逐渐成为热门话题。而从事这一领域工作的第一步&#xff0c;就是获取全面且准确的股票数据。因为无论是实时交易数据、历史交易记录、财务数据还是基本面信息&#xff0c;这些数据都是我们进行量化分析时不可或缺的宝贵资源。我们的主要…...

Rust语法基础

注释 所有的开发者都在努力使他们的代码容易理解,但有时需要额外的解释。在这种情况下,开发者在他们的源码中留下注释,编译器将会忽略掉这些内容,但阅读源码的人可能会发现有用。 和大多数的编程语言一样,主要有一下两种: 单行注释 // 多行注释 /* */ 基本数据类型 Ru…...

AWS WAF实现API安全防护

在当今的互联网环境中,API安全防护变得越来越重要。本文将介绍如何使用AWS WAF(Web Application Firewall)来实现有效的API安全防护策略。 背景 我们有一个API服务,其URL模式如下: https://dev.example.com/bff-app/sec/v1/module-a/feature-a/sub-feature-a我们需要使用AWS…...

vue将table转换为pdf导出

安装依赖&#xff1a; 首先&#xff0c;你需要安装 jspdf 和 html2canvas 这两个库。 npm install jspdf html2canvas创建Vue组件&#xff1a; 创建一个Vue组件&#xff0c;用于显示表格并提供导出PDF的功能。 <template> <div> <div id"table-contain…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...

【阅读笔记】MemOS: 大语言模型内存增强生成操作系统

核心速览 研究背景 ​​研究问题​​&#xff1a;这篇文章要解决的问题是当前大型语言模型&#xff08;LLMs&#xff09;在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色&#xff0c;但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成&#xff08;RA…...