微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

像素单位的焦距是线性测量吗?

如何解决像素单位的焦距是线性测量吗?

我有一个水平倾斜变焦相机(焦距随时间变化)。对其基本焦距(例如时间点0的焦距)一无所知。但是,可以基于一些已知的约束和假设来跟踪一帧与另一帧之间的焦距变化(执行SLAM)。

如果我假设一个随机焦距(以像素为单位),例如1000像素。然后,逐帧跟踪新的焦距。我会相对得到正确的结果吗?每帧的结果(焦距)是否可以正确校正以符合地面真实焦距?

对于平移和倾斜,假设开始时为0将有效。尽管不正确,但新的tili-pan的估计值将正确直到偏移量。但是,我怀疑估计的焦距甚至在按比例缩放或偏移时都不会正确。是否正确?

解决方法

一个简短的简短答案-如果将平移-变焦变焦相机近似为薄镜头,那么这就是距离(z)和焦距(f)之间的关系:

enter image description here

这只是一个近似值。不完全正确。有关更精确的计算,请参见camera matrix。焦距是相机矩阵中的固有参数。即使不知道,也可以使用某些相机校准方法(例如DLT,Zhang's MethodRANSAC)来计算。有了相机矩阵后,焦距只是其中的一小部分。您会得到更多有用的东西。

OpenCV具有Zhang方法的内置实现。 (请查看此documentation进行说明,但代码旧且无法使用。下面是新的最新代码。)您需要通过相机拍摄国际象棋的一些图片。这是一些帮助代码:

import cv2
from matplotlib import pyplot as plt
import numpy as np
from glob import glob
from scipy import linalg

x,y = np.meshgrid(range(6),range(8))

world_points=np.hstack((x.reshape(48,1),y.reshape(48,np.zeros((48,1)))).astype(np.float32)

_3d_points=[]
_2d_points=[]

img_paths=glob('./*.JPG') #get paths of all checkerboard images

for path in img_paths:
    im=cv2.imread(path)
    
    ret,corners = cv2.findChessboardCorners(im,(6,8))
    
    if ret: #add points only if checkerboard was correctly detected:
        _2d_points.append(corners) #append current 2D points
        _3d_points.append(world_points) #3D points are always the same


ret,mtx,dist,rvecs,tvecs = cv2.calibrateCamera(_3d_points,_2d_points,(im.shape[1],im.shape[0]),None,None)

print ("Ret:\n",ret)
print ("Mtx:\n",mtx)
print ("Dist:\n",dist)

您可能想要不失真:校正径向失真

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,30,0.001)

# prepare object points,like (0,0),(1,(2,0) ....,5,0)
objp = np.zeros((6*8,3),np.float32)
objp[:,:2] = np.mgrid[0:6,0:8].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

for fname in img_paths:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # Find the chess board corners
    ret,corners = cv2.findChessboardCorners(gray,8),None)    
    
    # If found,add object points,image points (after refining them)
    if ret == True:
        objpoints.append(objp)

        cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        imgpoints.append(corners)

    if 'IMG_5456.JPG' in fname:
        plt.figure(figsize=(20,10))
        img_vis=img.copy()
        cv2.drawChessboardCorners(img_vis,ret) 
        plt.imshow(img_vis)
        plt.show() 

enter image description here

#Calibration
ret,tvecs = cv2.calibrateCamera(objpoints,imgpoints,gray.shape[::-1],None)

# Reprojection Error
tot_error = 0
for i in range(len(objpoints)):
    imgpoints2,_ = cv2.projectPoints(objpoints[i],rvecs[i],tvecs[i],dist)
    error = cv2.norm(imgpoints[i],imgpoints2,cv2.NORM_L2)/len(imgpoints2)
    tot_error += error

print ("Mean Reprojection error: ",tot_error/len(objpoints))

# undistort
mapx,mapy = cv2.initUndistortRectifyMap(mtx,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
# crop the image
x,y,w,h = roi
dst = dst[y:y+h,x:x+w]
plt.figure(figsize=(20,10))
#cv2.drawChessboardCorners(dst,ret) 
plt.imshow(dst)
plt.show() 

enter image description here

# Reprojection Error
tot_error = 0
for i in range(len(objpoints)):
    imgpoints2,tot_error/len(objpoints))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。