合工大苍穹战队视觉组培训Day9——相机标定
生活随笔
收集整理的這篇文章主要介紹了
合工大苍穹战队视觉组培训Day9——相机标定
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
目錄
學習目標:
學習內容:
學習時間:
學習產出:
一、前期準備
二、采集相關數(shù)據(jù)
三、進行標定
四、用cv::undistort方法去除畸變
五、效果
?六、心得
學習目標:
- pnp解算
- 相機標定
- 去畸變
學習內容:
? ? ? ? ?直接用電腦的攝像頭標定一個相機,標定完后使用cv::undistort方法去除相機的畸變。
學習時間:
- 2022年8月1日到2022年8月4日
學習產出:
一、前期準備
這次長話短說吧,網上相關資料很多,可以參考https://blog.csdn.net/LuohenYJ/article/details/104697062
標定板我用的
可以去這個網站:Camera Calibration Pattern Generator – calib.io去生成
攝像頭是電腦的攝像頭。
二、采集相關數(shù)據(jù)
#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; // readif (frame.empty()) break; // check if at endimshow("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#ga354e0d7c86d0d9da75de9b9701a9a87ecornerSubPix(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為0for (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; }//執(zhí)行相機標定// Mat cameraMatrix; // 相機參數(shù)矩陣 Mat disCoffes; // 失真系數(shù) 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);// 寫出數(shù)據(jù)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) {// 讀取相機矩陣、畸變系數(shù)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:代碼僅供參考。
五、效果
?六、心得
我覺得做的不是很好很對,很多東西還是得進一步弄好,等我多學點再后續(xù)更新吧。
總結
以上是生活随笔為你收集整理的合工大苍穹战队视觉组培训Day9——相机标定的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 输入法汇总
- 下一篇: HID报文讲解