当前位置:网站首页>合工大苍穹战队视觉组培训Day9——相机标定
合工大苍穹战队视觉组培训Day9——相机标定
2022-08-05 05:59:00 【工大电科小趴菜】
目录
学习目标:
- pnp解算
- 相机标定
- 去畸变
学习内容:
直接用电脑的摄像头标定一个相机,标定完后使用cv::undistort方法去除相机的畸变。
学习时间:
- 2022年8月1日到2022年8月4日
学习产出:
一、前期准备
这次长话短说吧,网上相关资料很多,可以参考https://blog.csdn.net/LuohenYJ/article/details/104697062
标定板我用的
可以去这个网站:Camera Calibration Pattern Generator – calib.io去生成
摄像头是电脑的摄像头。
二、采集相关数据
#include "opencv2/opencv.hpp"
#include <string>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
VideoCapture inputVideo(0);
//inputVideo.set(CV_CAP_PROP_FRAME_WIDTH, 320);
//inputVideo.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
if (!inputVideo.isOpened())
{
cout << "Could not open the input video " << endl;
return -1;
}
Mat frame;
string imgname;
int f = 1;
while (1) //Show the image captured in the window and repeat
{
inputVideo >> frame; // read
if (frame.empty()) break; // check if at end
imshow("Camera", frame);
char key = waitKey(1);
if (key == 27)break;
if (key == 'q' || key == 'Q')
{
imgname = to_string(f++) + ".jpg";
imwrite(imgname, frame);
}
}
cout << "Finished writing" << endl;
return 0;
}
三、进行标定
//加载图片//
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
// 保存多张图片对象点列表
vector<vector<Point3f>> objectPoints;
// 保存多张图片的角点列表
vector<vector<Point2f>> cornerPoints;
int main(){
// 图片像素尺寸
Size imgSize;
// 图片路径
cv::String src_path = "./assets/camerargb_*.jpg";
std::vector<String> filenames;
cv::glob(src_path, filenames);//获取路径下所有文件名
cout << "filenames.size:" << filenames.size() << endl;
for (auto& imgName : filenames) {
// 读取图片
Mat img = imread(imgName, IMREAD_COLOR);
// 获取图片像素尺寸
imgSize = img.size();
std::cout << "name: " << imgName<< " imgSize: " << imgSize << std::endl;
//...
}
return 0;
}
//查找角点//
// 棋盘格的尺寸(宽6,高9)
const Size patternSize(6, 9);
// 黑方格的大小 20mm
const int squareSize = 20;
/**
* 在指定图片中查找角点,并将结果输出到corners中
* @param img 待检测图片
* @param corners 检测到的焦点列表
* @return 是否检测到角点(两个黑方格的交点)
*/
bool findCorners(Mat &img, vector<Point2f> &corners) {
Mat gray;
// 将图片转成灰度图
cvtColor(img, gray, COLOR_RGB2GRAY);
// 查找当前图片所有的角点
bool patternWasFound = findChessboardCorners(gray, patternSize, corners);
if (patternWasFound) { // 找到角点
// 提高角点的精确度
// 原理:https://docs.opencv.org/4.1.0/dd/d1a/group__imgproc__feature.html#ga354e0d7c86d0d9da75de9b9701a9a87e
cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1),
TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1));
}
// 将所有的焦点在原图中绘制出来
drawChessboardCorners(img, patternSize, corners, patternWasFound);
// 绘制完角点之后,显示原图
imshow("src", img);
if (!patternWasFound){
cout << "角点检测失败!" << endl;
}
return patternWasFound;
}
// 保存多张图片对象点列表
vector<vector<Point3f>> objectPoints;
// 保存多张图片的角点列表
vector<vector<Point2f>> cornerPoints;
void calcObjectPoints(vector<Point3f> &objPoint) {
// 计算uv空间中角点对应的相机坐标系坐标值,设Z为0
for (int i = 0; i < patternSize.height; ++i)
for (int j = 0; j < patternSize.width; ++j)
objPoint.emplace_back(j * squareSize, i * squareSize, 0);
}
// 图片像素尺寸
Size imgSize;
int main(){
// 图片路径
cv::String src_path = "./assets/camerargb_*.jpg";
std::vector<String> filenames;
cv::glob(src_path, filenames);//获取路径下所有文件名
cout << "filenames.size:" << filenames.size() << endl;
for (auto& imgName : filenames) {
// 读取图片
Mat img = imread(imgName, IMREAD_COLOR);
// 获取图片像素尺寸
imgSize = img.size();
std::cout << "name: " << imgName<< " imgSize: " << imgSize << std::endl;
// 声明每张图片的角点
vector<Point2f> corners;
bool found = findCorners(img, corners);
if (found) {
vector<Point3f> objPoints;
calcObjectPoints(objPoints);
// 找到角点,证明这张图是有效的
objectPoints.push_back(objPoints);
cornerPoints.push_back(corners);
}
}
return 0;
}
//执行相机标定//
Mat cameraMatrix; // 相机参数矩阵
Mat disCoffes; // 失真系数 distortion coefficients
Mat rvecs; // 图片旋转向量
Mat tvecs; // 图片平移向量
calibrateCamera(objectPoints, cornerPoints, imgSize, cameraMatrix, disCoffes, rvecs, tvecs);
cout << "标定矩阵:" << cameraMatrix << endl;
cout << "畸变矩阵:" << disCoffes << endl;
// save2xml(cameraMatrix, distCoffes);
waitKey();
//保存标定结果//
void save2xml(const Mat &cameraMatrix, const Mat &disCoffes) {
// 获取当前时间
time_t tm;
time(&tm);
struct tm *t2 = localtime(&tm);
char buf[1024];
strftime(buf, sizeof(buf), "%c", t2);
// 写出数据
String inCailFilePath = "./inCailFilePath.xml";
FileStorage inCailFs(inCailFilePath, FileStorage::WRITE);
inCailFs << "calibration_time" << buf;
inCailFs << "cameraMatrix" << cameraMatrix;
inCailFs << "distCoffes" << disCoffes;
inCailFs.release();
}
//我最后输出了yml文件,也可以是xml文件格式//
四、用cv::undistort方法去除畸变
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
int main(int argc, char **argv) {
// 读取相机矩阵、畸变系数
cv::FileStorage fs("你的yml文件", FileStorage::READ);
int image_width{0}, image_height{0};
fs["image_width"] >> image_width;
fs["image_height"] >> image_height;
Size image_size = Size(image_width, image_height);
Mat intrinsic_matrix, distortion_coeffs;
fs["cameraMatrix"] >> intrinsic_matrix;
fs["distCoeffs"] >> distortion_coeffs;
fs.release();
std::cout << intrinsic_matrix << std::endl;
std::cout << distortion_coeffs << std::endl;
std::cout << image_size << std::endl;
const Mat &image0 = imread("./calib_chess_img/image_0.jpg", IMREAD_COLOR);
Mat image;
undistort(image0, image, intrinsic_matrix, distortion_coeffs);
imshow("original", image0);
imshow("undistorted", image);
waitKey();
return 0;
}
PS:代码仅供参考。
五、效果
六、心得
我觉得做的不是很好很对,很多东西还是得进一步弄好,等我多学点再后续更新吧。
边栏推荐
猜你喜欢
滚动条问题,未解决
(四)旋转物体检测数据roLabelImg转DOTA格式
【FAQ】CCAPI Compatible EOS Camera List (Updated in August 2022)
Q 2020, the latest senior interview Laya soul, do you know?
淘宝客APP带自营商城本地生活CPS外卖优惠电影票话费更新渠道跟单生活特权V3
日本卫生设备行业协会:日本温水喷淋马桶座出货量达1亿套
Late night drinking, 50 classic SQL questions, really fragrant~
人人AI(吴恩达系列)
export使用
In-depth analysis if according to data authority @datascope (annotation + AOP + dynamic sql splicing) [step by step, with analysis process]
随机推荐
Matplotlib绘图笔记
八大排序之堆排序
ev加密视频转换成MP4格式,亲测可用
边缘盒子+时序数据库,美的数字化平台 iBUILDING 背后的技术选型
【FAQ】什么是 Canon CCAPI
Nacos集群搭建
LaTeX uses frame to make PPT pictures without labels
BIO, NIO, AIO practical study notes (easy to understand theory)
Quick Start to Drools Rule Engine (1)
vscode notes
VSCode编写OpenCV
D39_ coordinate transformation
农场游戏果园系统+牧场养殖系统+广告联盟模式流量主游戏小程序APP V1
香港国际珠宝展及香港国际钻石、宝石及珍珠展揭幕
淘宝宝贝页面制作
vs2017关于函数命名方面的注意事项
淘宝客APP带自营商城本地生活CPS外卖优惠电影票话费更新渠道跟单生活特权V3
Alibaba Cloud Video on Demand
(JLK105D)中山爆款LED恒流电源芯片方案
MySQL表操作练习