相机校准,焦距值似乎太大

2024-06-16 16:44:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试用python和opencv进行相机校准,以找到相机矩阵。我从这个链接中使用了以下代码

https://automaticaddison.com/how-to-perform-camera-calibration-using-opencv/

import cv2 # Import the OpenCV library to enable computer vision
import numpy as np # Import the NumPy scientific computing library
import glob # Used to get retrieve files that have a specified pattern
 
# Path to the image that you want to undistort
distorted_img_filename = r'C:\Users\uid20832\3.jpg'
 
# Chessboard dimensions
number_of_squares_X = 10 # Number of chessboard squares along the x-axis
number_of_squares_Y = 7  # Number of chessboard squares along the y-axis
nX = number_of_squares_X - 1 # Number of interior corners along x-axis
nY = number_of_squares_Y - 1 # Number of interior corners along y-axis
 
# Store vectors of 3D points for all chessboard images (world coordinate frame)
object_points = []
 
# Store vectors of 2D points for all chessboard images (camera coordinate frame)
image_points = []
 
# Set termination criteria. We stop either when an accuracy is reached or when
# we have finished a certain number of iterations.
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
 
# Define real world coordinates for points in the 3D coordinate frame
# Object points are (0,0,0), (1,0,0), (2,0,0) ...., (5,8,0)
object_points_3D = np.zeros((nX * nY, 3), np.float32)       
 
# These are the x and y coordinates                                              
object_points_3D[:,:2] = np.mgrid[0:nY, 0:nX].T.reshape(-1, 2) 
 
def main():
     
  # Get the file path for images in the current directory
  images = glob.glob(r'C:\Users\Kalibrierung\*.jpg')
     
  # Go through each chessboard image, one by one
  for image_file in images:
  
    # Load the image
    image = cv2.imread(image_file)  
 
    # Convert the image to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  
 
    # Find the corners on the chessboard
    success, corners = cv2.findChessboardCorners(gray, (nY, nX), None)
     
    # If the corners are found by the algorithm, draw them
    if success == True:
 
      # Append object points
      object_points.append(object_points_3D)
 
      # Find more exact corner pixels       
      corners_2 = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)       
       
            # Append image points
      image_points.append(corners)
 
      # Draw the corners
      cv2.drawChessboardCorners(image, (nY, nX), corners_2, success)
 
      # Display the image. Used for testing.
      #cv2.imshow("Image", image) 
     
      # Display the window for a short period. Used for testing.
      #cv2.waitKey(200) 
                                                                                                                     
  # Now take a distorted image and undistort it 
  distorted_image = cv2.imread(distorted_img_filename)
 
  # Perform camera calibration to return the camera matrix, distortion coefficients, rotation and translation vectors etc 
  ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, 
                                                    image_points, 
                                                    gray.shape[::-1], 
                                                    None, 
                                                    None)

但我想我总是得到错误的参数。从校准结果来看,我的焦距在x和y方向约为1750。我认为这不可能是正确的,它几乎是正确的。相机文件显示焦距在4-7毫米之间。但我不确定,为什么校准后它会这么高。这是我的一些校准照片。也许他们有问题。我把棋盘移到相机下面的不同方向、角度和高度

我还想知道,为什么我不需要代码中正方形的大小。有人能给我解释一下吗?还是我把这个输入忘在什么地方了

enter image description hereenter image description hereenter image description here


Tags: ofthetoimagenumberforobjectcv2
1条回答
网友
1楼 · 发布于 2024-06-16 16:44:50

你的误解是关于“焦距”。这是一个超负荷的术语

  • 光学部分中的“焦距”(单位mm):它描述透镜平面和图像/传感器平面之间的距离
  • 相机矩阵中的“焦距”(单位像素):它描述了将真实世界映射到特定分辨率图片的比例因子

1750如果你有一张高分辨率的图片(全高清或其他什么),那么它可能是正确的

计算结果如下:

f [pixels] = (focal length [mm]) / (pixel pitch [µm / pixel])

(注意单位和前缀,1 mm=1000µm)

示例:具有1.40µm像素间距和4.38 mm焦距的像素4a手机的f=~3128.57(=fx=fy)

另一个示例:像素4a具有约77.7度的对角线视野,分辨率为4032 x 3024像素,因此对角线方向为5040像素。您可以计算:

f = (5040 / 2) / tan(~77.7° / 2)

f = ~3128.6 [pixels]

这个计算可以应用于任意的相机,你知道它的视野和图片大小。如果对角线分辨率不明确,则使用水平视野和水平分辨率。如果传感器不是16:9,但您从中拍摄的视频被剪切到16:9,则可能发生这种情况。。。假设作物只垂直生长,而水平生长不受影响


在这个代码中,为什么不需要棋盘方块的大小?因为它只校准内部参数(摄像机矩阵和失真系数)。这些并不取决于到板或场景中任何其他对象的距离

如果要校准外部参数,即立体设置中摄像机的距离,则需要给出正方形的大小

相关问题 更多 >