我想找到一种快速实现图像点畸变和不畸变的方法。以下是我当前的实现,效果很好
# Given a set of distorted image points, I can use cv2.undistortpoints
def undistort_points(points, kmat, distcoeff):
undistorted_pts_normed = cv2.undistortPoints(points, kmat, distcoeff).squeeze()
cx = kmat[0,2]
cy = kmat[1,2]
fx = kmat[0,0]
fy = kmat[1,1]
undistorted_uv = np.empty(undistorted_pts_normed.shape)
undistorted_uv[:,0] = fx * undistorted_pts_normed[:,0] + cx
undistorted_uv[:,1] = fy * undistorted_pts_normed[:,1] + cy
ret = [Point(x=int(pt[0]),y=int(pt[1])) for pt in undistorted_uv]
# To distort the points I use the distortion equations
def distort_points(points, kmat, distcoeff):
cx = kmat[0,2]
cy = kmat[1,2]
fx = kmat[0,0]
fy = kmat[1,1]
k1,k2,p1,p2,k3 = distcoeff
# Convert to normalized points
normed_points = np.empty(points.shape)
normed_points[:,0] = (points[:,0] - cx)/fx
normed_points[:,1] = (points[:,1] - cy)/fy
# Apply distortion
r2 = normed_points[:,0]**2 + normed_points[:,1]**2 # r squared
radial_dist = (1 + k1*r2 + k2*(r2**2) + k3*(r2**3))[...,np.newaxis]
tangential_dist = np.empty(normed_points.shape)
tangential_dist[:,0] = p2 * (r2 + 2 * (normed_points[:,0]**2)) + 2 * p1 * normed_points[:,0] * normed_points[:,1]
tangential_dist[:,1] = p1 * (r2 + 2 * (normed_points[:,1]**2)) + 2 * p2 * normed_points[:,0] * normed_points[:,1]
distorted_points = radial_dist * normed_points + tangential_dist
# Return points in uv space
distorted_uv = np.empty(distorted_points.shape)
distorted_uv[:,0] = fx * distorted_points[:,0] + cx
distorted_uv[:,1] = fy * distorted_points[:,1] + cy
return distorted_uv
我遇到过
cv2.initUndistortRectifyMap
,我可以运行一次来存储每个像素的映射以进行反失真,从而使反失真非常有效。但是,我不确定如何使用 mapx 和 mapy 作为图像点而不是完整图像。下面显示了我如何计算 mapx 和 mapy 映射。
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(kmat, distcoeff, (1920, 1080), 0, (1920, 1080))
mapx, mapy = cv2.initUndistortRectifyMap(kmat, distcoeff, None, newcameramtx, (1920, 1080), 5)
我还想知道是否可以使用相同的映射从未扭曲点转换为扭曲点。任何帮助将不胜感激!
图像点,还是整个图像?
镜头畸变方程在一个方向上是封闭形式,但在另一个方向上需要数值反演(几次迭代)。 OpenCV 具有双向功能,可对各个点进行操作。
扭曲整个图像的每个单独的像素坐标不算作“点”。
扭曲整个图像是另一回事,并使用其他函数。该变换在 other 方向上速度很快,但需要针对 one 方向进行一次性映射反转(迭代数值运算)。