当前位置: 首页 > 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…...

软件工程自动化浪潮下,工程师如何从代码生产者转型为系统架构师?

1. 软件工程的自动化浪潮&#xff1a;从手工艺到基础设施的必然之路最近和几个在头部大厂干了十几年的老同事聊天&#xff0c;话题总绕不开一个词&#xff1a;焦虑。不是对业务增长的焦虑&#xff0c;而是对自身角色价值的焦虑。一个在阿里做P8的朋友说&#xff0c;他团队里新来…...

OBS Source Record插件完全掌握指南:实现多源独立录制的终极解决方案

OBS Source Record插件完全掌握指南&#xff1a;实现多源独立录制的终极解决方案 【免费下载链接】obs-source-record 项目地址: https://gitcode.com/gh_mirrors/ob/obs-source-record 你是否曾经在直播或录制视频时&#xff0c;想要单独保存某个特定的画面源&#xf…...

LangGraph 生产级部署全解:FastAPI + Docker

一、部署架构总览 我们将基于你之前的带人工干预的双智能体系统&#xff0c;构建一个完整的生产级部署方案&#xff0c;包含三个核心部分&#xff1a; FastAPI 接口层&#xff1a;封装 Agent 为标准 HTTP 接口&#xff0c;支持任务启动、人工干预、状态查询Redis 持久化层&am…...

Obsidian+Cursor构建AI增强型项目规划与开发一体化工作流

1. 项目概述&#xff1a;构建你的数字项目规划中枢如果你和我一样&#xff0c;同时管理着好几个数字项目——可能是一个新的SaaS产品、一个开源工具&#xff0c;或者一个复杂的个人自动化脚本——你肯定体会过那种信息散落各处的痛苦。产品需求文档在Notion里&#xff0c;技术架…...

前后端分离林业产品推荐系统系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程

摘要 随着信息技术的快速发展&#xff0c;林业产品的销售和推广方式逐渐从传统线下模式转向数字化和智能化。林业产品种类繁多&#xff0c;消费者在选购时往往面临信息不对称的问题&#xff0c;难以高效匹配自身需求。同时&#xff0c;林业企业也缺乏精准的用户画像和推荐机制&…...

3个关键策略:qmcdump如何高效解密QQ音乐加密音频文件

3个关键策略&#xff1a;qmcdump如何高效解密QQ音乐加密音频文件 【免费下载链接】qmcdump 一个简单的QQ音乐解码&#xff08;qmcflac/qmc0/qmc3 转 flac/mp3&#xff09;&#xff0c;仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump 你是否…...

基于Tauri框架构建轻量级ChatGPT桌面客户端:从原理到实践

1. 项目概述&#xff1a;一个基于Tauri的ChatGPT桌面客户端 最近在折腾AI应用本地化部署的时候&#xff0c;发现了一个挺有意思的项目&#xff1a; pljhonglu/ChatGPT-T 。这是一个用Tauri框架开发的ChatGPT桌面客户端&#xff0c;它的前端界面直接复用了开源项目 chatgpt-…...

结构函数:电子封装热分析的关键技术解析

1. 结构函数&#xff1a;热分析领域的核心桥梁在电子封装设计与散热方案开发中&#xff0c;热特性分析一直是个令人头疼的问题。想象一下&#xff0c;你手里拿着一块正在发烫的芯片&#xff0c;却无法直接"看到"热量是如何在内部传递的——这就像医生无法用X光检查病…...

大语言模型微调实战:从LoRA到QLoRA,一站式开源框架详解

1. 项目概述与核心价值 如果你正在寻找一个能够一站式搞定主流大语言模型微调的开源项目&#xff0c;那么 ssbuild/llm_finetuning 绝对值得你花时间深入研究。这个项目本质上是一个基于 PyTorch 和 Hugging Face Transformers 生态的、高度工程化的微调框架。它最大的魅力在…...

OptiSearch:浏览器扩展实现AI与搜索引擎的无缝集成

1. 项目概述&#xff1a;当搜索遇到AI&#xff0c;一次查询&#xff0c;双重答案作为一名长期在信息检索和效率工具领域折腾的开发者&#xff0c;我一直在思考一个问题&#xff1a;我们每天在搜索引擎和AI聊天机器人之间要切换多少次标签页&#xff1f;搜索一个技术问题&#x…...