opencv相机标定
python 完整标注流程,
python+opencv相机标定 - wenboz - 博客园
相机标定需要输出的参数:
焦距 像素或者物理单位mm
像素对应的物理长度
光心与物理senser中心的偏移量 一般用不到
x y 正交误差 是否垂直 返回度数,与90度的偏差相机的模型 成像模型 x y 与真实坐标系X Y Z坐标点 的关系
出来模型的参数 鱼眼相机 矫正。#include "cv.h"
#include "highgui.h"
#include "cxcore.h"opencv制作相机标定板:
//隐藏控制台窗口
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")int main(int argc, char*argv[])
{int width = 140;//棋盘格宽度int height = 140;//棋盘格高度IplImage *src = cvCreateImage(cvSize(980,1260), IPL_DEPTH_8U, 1);cvZero(src);for (int i = 0; i < src->height; i++){for (int j = 0; j < src->width; j++){if ((i / width + j / height) % 2 != 0){src->imageData[i*src->widthStep + j*src->nChannels] = 255;}}}cvNamedWindow("src");cvShowImage("src", src);cvSaveImage("ChessBoard.bmp", src, 0);cvWaitKey(0);return 0;}
相机标定
相机标定:简单的说,就是获得相机参数的过程。参数如:相机内参数矩阵,投影矩阵,旋转矩阵和平移矩阵等
- 什么叫相机参数?
简单的说,将现实世界中的人、物,拍成一张图像(二维)。人或物在世界中的三维坐标,和图像上对应的二维坐标间的关系。表达两种不同维度坐标间的关系用啥表示?用相机参数。
- 相机的成像原理
先来看一下,相机的成像原理: 如图所示,这是一个相机模型。将物体简化看成一个点。来自物体的光,通过镜头,击中图像平面(图像传感器),以此成像。d0是物体到镜头的距离,di时镜头到图像平面的距离,f是镜头的焦距。三者满足以下关系。 现在,简化上面的相机模型。 将相机孔径看成无穷小,只考虑中心位置的射线,这样就忽视了透镜的影响。然后由于d0远远大于di,将图像平面放在焦距处,这样物体在图像平面上成像为倒立的影像(没有透镜的影响,只考虑从中心的孔径进入的光线)。这个简化的模型就是针孔摄像机模型。然后,我们在镜头前,将图像平面放在焦距距离的位置,就可以简单获得一个笔直的图像(不倒立)。当然,这只是理论上的,你不可能将图像传感器从相机里拿出来,放在镜头前面。实际应用中,针孔摄像机应该是将成像后的图像倒过来,以获得正立的图像。 到此,我们获得了一个简化的模型,如下图: h0是物体的高,hi是图像上物体的高,f是焦距(距离),d0是图像到镜头的距离。四者满足如下关系: (1) 物体在图像中的高度hi,和d0成反比。也就是说,离镜头越远,物体在图像中越小,离得越近越大(好吧,这句话是废话)。 但通过这个式子,我们便能够预测三维中的物体,在图像(二维)中的位置。那么怎么预测?
- 相机标定
如下图所示,根据上面简化的模型,考虑三维世界中的一个点,和其在图像(二维)中的坐标关系。 (X,Y,Z)为点的三维坐标,(x,y)为其通过相机成像后在图像(二维)上的坐标。u0和v0是相机的中心点(主点),该点位于图像平面中心(理论上是这样。但实际的相机会有几个像素的偏差) 现在只考虑y方向上,由于需要将三维世界中的坐标,转换为图像上的像素(图像上的坐标,实际上是像素的位置),需要求y方向上焦距等于多少个像素(用像素值表示焦距),Py表示像素的高,焦距f(米或毫米)。垂直像素表示的焦距为 根据式子(1),只考虑y方向。我们三维世界中得点,在图像(二维)中y的坐标。 同理,得到x的坐标。 现在,将上图中的坐标系的原点O,移动到图像的左上角。由于(x,y)是关于(u0,v0)的偏移,上面表示图像(二维)中点的坐标的式子不变。将式子以矩阵的形式重写,得。 其中,等式左边的第一个矩阵,叫做“相机内参数矩阵”,第二个矩阵叫(投影矩阵)。
更为一般的情况,开始时的参考坐标系不位于主点(中心点),需要额外两个参数“旋转向量”和“平移向量”来表示这个式子,这两个参数在不同视角中是不一样的。整合后,上述式子重写为。
- 校正畸变 通过相机标定,获得了相机参数后,可以计算两个映射函数(x坐标和y坐标),它们分别给出了没有畸变的图像坐标。将畸变的图像重新映射成为没有畸变的图像。
代码:
做相机标定时,一般用标定板(棋盘)拍摄一组图像,利用这些图像提取角点,通过角点在图像中得坐标和三维世界中的坐标(通常自定义3维坐标),计算相机参数。
std::vector<cv::Point2f>imageConers;
//提取标定图像角点,保存角点坐标(二维)cv::findChessboardCorners(image,boardSize, //角点数目如(6,4)六行,四列imageConers);
函数calibrateCamera完成相机标定工作。
cv::calibrateCamera(objectPoints,//三维坐标imagePoints, //二维坐标imageSize,//图像大小camerMatirx,//相机内参数矩阵disCoeffs,//投影矩阵rvecs, //旋转tvecs,//平移
flag //标记opencv提供几种参数,可以参看在线的opencv document
);
计算畸变参数,去畸变
//计算畸变参数
cv::initUndistortRectifyMap(camerMatirx, disCoeffs,cv::Mat(), cv::Mat(), image.size(), CV_32FC1, map1, //x映射函数map2 //y映射函数);
//应用映射函数
cv::remap(image, //畸变图像
undistorted, //去畸变图像
map1, map2, cv::INTER_LINEAR);
现在整合代码。
- 示例:
标头.h
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\calib3d\calib3d.hpp>
#include <opencv2/features2d/features2d.hpp>
#include<string>
#include<vector>
class CameraCalibrator
{
private://世界坐标std::vector < std::vector<cv::Point3f >> objectPoints;//图像坐标std::vector <std::vector<cv::Point2f>> imagePoints;//输出矩阵cv::Mat camerMatirx;cv::Mat disCoeffs;//标记int flag;//去畸变参数cv::Mat map1, map2;//是否去畸变bool mustInitUndistort;///保存点数据void addPoints(const std::vector<cv::Point2f>&imageConers, const std::vector<cv::Point3f>&objectConers){imagePoints.push_back(imageConers);objectPoints.push_back(objectConers);}
public:CameraCalibrator() :flag(0), mustInitUndistort(true){}//打开棋盘图片,提取角点int addChessboardPoints(const std::vector<std::string>&filelist,cv::Size &boardSize){std::vector<cv::Point2f>imageConers;std::vector<cv::Point3f>objectConers;//输入角点的世界坐标for (int i = 0; i < boardSize.height; i++){for (int j = 0; j < boardSize.width; j++){objectConers.push_back(cv::Point3f(i, j, 0.0f));}}//计算角点在图像中的坐标cv::Mat image;int success = 0;for (int i = 0; i < filelist.size(); i++){image = cv::imread(filelist[i],0);//找到角点坐标bool found = cv::findChessboardCorners(image, boardSize, imageConers);cv::cornerSubPix(image, imageConers,cv::Size(5, 5),cv::Size(-1, -1),cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,30, 0.1));if (imageConers.size() == boardSize.area()){addPoints(imageConers, objectConers);success++;}//画出角点cv::drawChessboardCorners(image, boardSize, imageConers, found);cv::imshow("Corners on Chessboard", image);cv::waitKey(100);}return success;}//相机标定double calibrate(cv::Size&imageSize){mustInitUndistort = true;std::vector<cv::Mat>rvecs, tvecs;//相机标定return cv::calibrateCamera(objectPoints, imagePoints, imageSize,camerMatirx, disCoeffs, rvecs, tvecs, flag);}///去畸变cv::Mat remap(const cv::Mat &image){cv::Mat undistorted;if (mustInitUndistort){//计算畸变参数cv::initUndistortRectifyMap(camerMatirx, disCoeffs,cv::Mat(), cv::Mat(), image.size(), CV_32FC1, map1, map2);mustInitUndistort = false;}//应用映射函数cv::remap(image, undistorted, map1, map2, cv::INTER_LINEAR);return undistorted;}//常成员函数,获得相机内参数矩阵、投影矩阵数据cv::Mat getCameraMatrix() const { return camerMatirx; }cv::Mat getDistCoeffs() const { return disCoeffs; }
};
源.cpp
#include"标头.h"
#include<iomanip>
#include<iostream>
int main()
{CameraCalibrator Cc;cv::Mat image;std::vector<std::string> filelist;cv::namedWindow("Image");for (int i = 1; i <= 22; i++){///读取图片std::stringstream s;s << "D:/images/chessboards/chessboard" << std::setw(2) << std::setfill(‘0‘) << i << ".jpg";std::cout << s.str() << std::endl;filelist.push_back(s.str());image = cv::imread(s.str(),0);cv::imshow("Image", image);cv::waitKey(100);}//相机标定cv::Size boardSize(6, 4);Cc.addChessboardPoints(filelist, boardSize);Cc.calibrate(image.size());//去畸变image = cv::imread(filelist[1]);cv::Mat uImage=Cc.remap(image);cv::imshow("原图像", image);cv::imshow("去畸变", uImage);//显示相机内参数矩阵cv::Mat cameraMatrix = Cc.getCameraMatrix();std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl;std::cout << cameraMatrix.at<double>(0, 0) << " " << cameraMatrix.at<double>(0, 1) << " " << cameraMatrix.at<double>(0, 2) << std::endl;std::cout << cameraMatrix.at<double>(1, 0) << " " << cameraMatrix.at<double>(1, 1) << " " << cameraMatrix.at<double>(1, 2) << std::endl;std::cout << cameraMatrix.at<double>(2, 0) << " " << cameraMatrix.at<double>(2, 1) << " " << cameraMatrix.at<double>(2, 2) << std::endl;cv::waitKey(0);
}
实验结果:
看以看到,相机内参数矩阵为
172.654 、0、157.829
0、184.195、118.635
0 、0 、1
opencv相机标定相关推荐
- OpenCv相机标定——圆形标定板标定
OpenCv相机标定--圆形标定板标定 0.前言 1.标定图案 2.OpenCv标定 3.标定结果分析 0.前言 OpenCv中,相机标定所使用的标定图案分为棋盘格.对称圆形及非对称圆形特征图.A ...
- 制作OpenCV相机标定板棋盘格图像
一,OpenCV 相机标定中棋盘格图像要点 1,棋盘格的内部交点个数boardSize:水平方向(board_width, -w=4)和垂直方向(board_height, -h=5) 个人建议:棋盘 ...
- opencv相机标定和人头姿态估计案例
前言 头部驱动除了之前关注的表情驱动外,还有眼球驱动和头部方向驱动.本博客基于opencv官方文档和部分开源代码来研究如何基于人脸关键点获取头部的朝向. 国际惯例,参考博客: opencv:Camer ...
- OpenCV相机标定与畸变校正
点击我爱计算机视觉标星,更快获取CVML新技术 本文转载自OpenCV学堂. OpenCV单目相机标定,图像畸变校正 相机标定定义与原理 01 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点 ...
- opencv相机标定模块解析
第一部分,opencv 3.0 以后的接口: 主要解释的函数有: 1.单相机标定 ①. Rodrigues 罗德里格斯变换 ②.projectPoints 计算世界坐标系中的点在相机相平面的投影点. ...
- 基于python的opencv相机标定(采用黑白棋盘格标定板)
基于python的相机标定(采用黑白棋盘格图片) 系列文章目录 [第一章 基于python的相机标定(采用黑白棋盘格图片)](https://blog.csdn.net/HWHXXX/article/ ...
- python+OpenCV 相机标定
相机标定 目录 原理 相机标定结果 流程简介 实验过程 总结 代码及调试问题 相机标定在机器人视觉和畸变校正上都是很关键的一部分,接下来用张正友相机标定法标定我的手机(Vivo xpaly5A)后置摄 ...
- opencv相机标定(1)-畸变校正原理
理想相机成像模型 看到一篇博客,介绍的十分详细.参考 链接 (为了好理解,个人还是喜欢分四大坐标系,世界坐标系,摄像机坐标系,图像物理坐标系,图像像素坐标系) 1)世界坐标系->摄像机坐标系 R ...
- (十)OpenCV相机标定
一.基本原理 相机的基本原理介绍见 基本相机模型及参数 张正友标定法的推导介绍见 相机的内参矩阵表示的是将相机坐标系中的空间点变换到像素坐标系中: 相机的外参表示的是世界坐标系到相机坐标下的变换: 其 ...
最新文章
- 黑盒测试之边界值测试
- 我转行成为机器学习和无人车工程师,并收获Offer
- hdu2063 二分图(基础题)
- python抓取数据库_Python-7.爬取大量数据存入数据库
- beta版本项目冲刺
- 成功在家用ssh远程连上了学校电脑虚拟机当中的ubuntu(代价是虚拟机全部黑屏只能用SSH连接了!)
- 扇贝有道180927每日一句
- java记账软件开发_Java项目之家庭记账软件
- ANSYS网格划分---单元类型选择及步骤
- Excel RibbonUI:editBox控件使用
- 【ES6】for of用法
- Pytorch(一) —— 相关库和函数
- redis缓存服务器介绍与配置
- js浏览器的打印和去除页眉和页脚
- 【Spring Cloud 基础设施搭建系列】Spring Cloud Demo项目 将微服务运行在Docker上
- Android再进阶之广播发送、接收和注册过程
- 滑动窗口大杀器,牛逼
- 贝叶斯基础理论及思想介绍
- Windows服务器怎么才能长时间保持远程桌面不自动断开
- 腾讯米大师接入Demo
热门文章
- 秒赞机器人好友_空间说说秒赞机器人
- python3 列表倒叙_python的列表、元组、字典、集合
- linux 内存泄露工具,linux下检查内存泄露的工具--mtrace
- android上传项目到码云_上传代码到码云
- linux ssh别的机器,Linux SSH 登录其他机器
- java中文转拼音 多音字_java使用jpinyin汉语转拼音(支持多音字)
- 保存设置_如何设置石材雕刻机原点及断电后怎么保存原点坐标?
- Postman 最被低估的功能!
- 如何更快地将string转换成int/long
- 皮一皮:让我们一起,走近科学!