OpenCV 求焦距[純粹收集]
OpenCV 求焦距[純粹收集]
資料來源:
C++ OPENCV 相機內部參數
00.https://www.itread01.com/article/1515554521.html
01.https://www.oudahe.com/p/46522/
python OPENCV 相機內部參數
02.https://www.itread01.com/article/1525761600.html
03.https://blog.csdn.net/u010128736/article/details/52875137
GITHUB:https://github.com/jash-git/OpenCV-focal-length
C++
#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; } };
#include"CameraCalibrator.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); }
Python
#coding:utf-8 import cv2 import numpy as np import glob # 找棋盤格角點 # 閾值 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) #棋盤格模板規格 w = 9 h = 6 # 世界座標系中的棋盤格點,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z座標,記為二維矩陣 objp = np.zeros((w*h,3), np.float32) objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2) # 儲存棋盤格角點的世界座標和影象座標對 objpoints = [] # 在世界座標系中的三維點 imgpoints = [] # 在影象平面的二維點 images = glob.glob('calib/*.png') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 找到棋盤格角點 ret, corners = cv2.findChessboardCorners(gray, (w,h),None) # 如果找到足夠點對,將其儲存起來 if ret == True: cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria) objpoints.append(objp) imgpoints.append(corners) # 將角點在影象上顯示 cv2.drawChessboardCorners(img, (w,h), corners, ret) cv2.imshow('findCorners',img) cv2.waitKey(1) cv2.destroyAllWindows() # 標定 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) # 去畸變 img2 = cv2.imread('calib/00169.png') h, w = img2.shape[:2] newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h)) # 自由比例引數 dst = cv2.undistort(img2, mtx, dist, None, newcameramtx) # 根據前面ROI區域裁剪圖片 #x,y,w,h = roi #dst = dst[y:y+h, x:x+w] cv2.imwrite('calibresult.png',dst) # 反投影誤差 total_error = 0 for i in xrange(len(objpoints)): imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist) error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2) total_error += error print "total error: ", total_error/len(objpoints) © 2020 GitHub, Inc.