常见的光学成像畸变矫正算法有以下几种:
1. 相机内参矩阵法
2. 标定板法
3. 双线性插值法
4. 反向投影法
5. 射线追踪法
这里介绍其中一种常用的方法——相机内参矩阵法:
原理:相机内参矩阵是描述相机内部光学特性的参数矩阵,包括焦距、位置、旋转角度等。通过对相机内参矩阵进行矫正,可以消除由于像素点大小和位置误差、透镜成像失真等因素引起的畸变。具体来说,相机内参矩阵法包括两个步骤:将原始图像中的像点映射至归一化平面上的坐标系,再将归一化平面上的坐标系映射至校正后的图像坐标系。
流程:
1. 计算相机内参矩阵K,包括焦距fx, fy,主点位置cx, cy等参数。
2. 对原始图像中的每个像素点(x,y)计算归一化平面上的坐标系下的坐标(X,Y),其中 X=(x-cx)/fx, Y=(y-cy)/fy。
3. 进行畸变矫正,将归一化平面上的坐标系下的坐标映射至校正后的图像坐标系。
4. 将校正后的坐标重新映射至实际图像坐标中。
代码实现:
- import cv2
- import numpy as np
- # 计算相机内参矩阵K
- def get_K():
- # 假设相机焦距和主点位置已知
- fx, fy = 100, 100
- cx, cy = 320, 240
- K = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])
- return K
- # 对归一化平面上的坐标进行畸变矫正
- def undistort_pts(pts, K, D):
- npts = pts.shape[0]
- # 将像素坐标矩阵转换为归一化平面坐标矩阵
- pts_norm = cv2.undistortPoints(pts, K, D)
- # 将归一化平面坐标矩阵加载到图像上进行可视化比较
- img_norm = np.zeros((480, 640), dtype=np.uint8)
- for i in range(npts):
- x_norm, y_norm = pts_norm[i][0][0], pts_norm[i][0][1]
- x_img, y_img = int(x_norm*K[0, 0]+K[0, 2]), int(y_norm*K[1, 1]+K[1, 2])
- img_norm[y_img, x_img] = 255
- cv2.imshow('Normalized Image', img_norm)
- cv2.waitKey()
- return pts_norm
- # 对校正后的坐标重新映射至实际图像坐标中
- def redistort_pts(pts, K, D):
- npts = pts.shape[0]
- # 将归一化平面坐标矩阵转换为像素坐标矩阵
- pts_img = cv2.undistortPoints(pts, K, D, P=K)
- # 将像素坐标矩阵加载到图像上进行可视化比较
- img_redist = np.zeros((480, 640), dtype=np.uint8)
- for i in range(npts):
- x_img, y_img = int(pts_img[i][0][0]), int(pts_img[i][0][1])
- img_redist[y_img, x_img] = 255
- cv2.imshow('Redistorted Image', img_redist)
- cv2.waitKey()
- return np.squeeze(pts_img)
- # 测试代码
- if __name__ == "__main__":
- img = cv2.imread('distorted_image.jpg')
- # 获取相机内参矩阵
- K = get_K()
- # 计算畸变系数D,假定已知
- D = np.array([0.1, -0.2, 0, 0])
- # 提取待校正的特征点
- # 假定已经通过关键点检测或者其他方式得到了一个nptsx2的浮点型特征点矩阵pts
- pts = np.array([[200, 200], [400, 200], [300, 300], [200, 400]])
- # 进行畸变校正
- pts_norm = undistort_pts(pts, K, D)
- pts_redist = redistort_pts(pts_norm, K, D)
- # 绘制原始图像和校正后的图像
- img_vis = np.zeros((480, 640), dtype=np.uint8)
- for i in range(npts):
- x_img, y_img = int(pts[i][0]), int(pts[i][1])
- img_vis[y_img, x_img] = 255
- cv2.imshow('Original Image', img_vis)
- cv2.waitKey()
- for i in range(npts):
- x_img, y_img = int(pts_redist[i][0]), int(pts_redist[i][1])
- img_vis[y_img, x_img] = 255
- cv2.imshow('Redistored Image', img_vis)
- cv2.waitKey()
- cv2.destroyAllWindows()
复制代码
--- 光学专家Gpt |