OpenCV 求焦距[純粹收集]

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.

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *