欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > 摄像头畸变矫正

摄像头畸变矫正

2025/2/22 2:12:46 来源:https://blog.csdn.net/zs3194068129/article/details/145626280  浏览:    关键词:摄像头畸变矫正

简单介绍

所谓畸变其实就是由摄像头引起的图片失真, 一般在广角摄像头表现明显, 原本平整的桌面通过镜头看像个球面,  直观的解释直线被拍成了曲线, 这让我想起来了一个表情包.

去畸变的办法

首先我们需要一个标准棋盘(印有特定的标定图案), 如图:


把它摊平放在桌子上, 然后用需要去畸变的相机对它进行拍摄, 拍几张(10~20张差不多)不同角度的棋盘图片, 保存好. 然后我们有两种方法进行畸变矫正.

1. 借助matlab的Camera Calibration Toolbox工具

我们打开matlab,


应用程序这里.


找到 Camera Calibration, 然后点击打开.


然后点击Add Images添加图片,


这里会弹出此弹框, 意思是选择我们棋盘格子的大小, 根据实际情况选择就行.


添加后会显示角点, 如果有不清楚的或者识别错误,红色边框, 可以删掉换一张图片就行.


导入多张图片后, 直接点击Calibrate 开始标定


完成后大致如上图, 会显示各个参数

  • 重投影误差(Reprojection Error):理想情况下应 < 0.5 像素.
  • 相机内参:
    1. 焦距(Focal Length)
    2. 主点(Principal Point)
    3. 畸变系数(Radial, Tangential)

      新版有这两项
  • 可视化:
  1. Show Undistorted Images 查看校正效果。
  2. Plot Reprojection Errors 分析误差分布。
    我2016版本并没有这个框

确认无误后可以点击 Export Camera Parameters导出数据, 则会导出到workspace当中生成mat文件
当然也可以点击第二个生成matlab代码进行后续操作

2. 使用OpenCV进行标定

OpenCV是计算机视觉库, 可以用来进行图像处理, 里面有很多函数, 我们可以借助它来进行畸变矫正.
首先我们将拍摄的照片全部保存到一个文件夹中然后, 然后我们需要手动指定实际拍摄图片中有多少个棋盘角点.
比如说这张图片, 是 9 X 5 的棋盘


对于所有的图片, 我们都需要进行同样的操作, 然后保存到列表中.类似于

# 每张图片的棋盘格参数, 9 X 6 格大小objp_dict = {1: (9, 5),2: (9, 6),3: (9, 6),4: (9, 6),5: (9, 6),6: (9, 6),7: (9, 6),8: (9, 6),9: (9, 6),10: (9, 6),11: (9, 6),12: (9, 6),13: (9, 6),14: (9, 6),15: (9, 6),16: (9, 6),17: (9, 6),18: (9, 6),19: (9, 6),20: (9, 6),}

根据指定的大小获取三维(np.zeros((nx*ny, 3), np.float32)) 理论坐标

    objp_list = []		 # 存储对象点corners_list = []	 # 存储角点# 遍历objp_dict的每个参数for k in objp_dict:nx, ny = objp_dict[k]	# 取出长宽# (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)objp = np.zeros((nx*ny, 3), np.float32)	              # 生成三维坐标,即每个点理论坐标应该是多少objp[:, : 2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2)  # 生成x和y的坐标,z坐标都是0

读取图片通过 cv2.cvtColor(灰度化) 和 cv2.findChessboardCorners(棋盘角点) 寻找真实的情况

# 对于识别的点应该的坐标序号初始化好后, 开始来读取图片中每个点的真实位置fname = 'camera_cal/calibration%s.jpg' % str(k)img = cv2.imread(fname)	# 读取一张图片# 转成灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 检测角点ret, corners = cv2.findChessboardCorners(gray, (nx, ny), None)

将返回值保存到列表中

        if ret == True:	 # 成功检测到了# Save object points and corresponding cornersobjp_list.append(objp)	#corners_list.append(corners)

将列表带入 cv2.calibrateCamera 中即可得到参数 内参矩阵(mtx)和畸变系数(dist)

    img = cv2.imread('test_images/straight_lines1.jpg')		# 这里得保证所有图像的大小一致img_size = (img.shape[1], img.shape[0])		# 获取测试图片的尺寸#  获取相关参数ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objp_list, corners_list, img_size,None,None)

最后使用 cv2.undistort 将图片进行去畸变即可

# 去畸变img = mpimg.imread('camera_cal/calibration5.jpg')	 #  读取图像dst = cv2.undistort(img, mtx, dist, None, mtx)

下面来康康完整代码:

import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import pickledef calibrate_camera():# Mapping each calibration image to number of checkerboard corners# Everything is (9,6) for now# 每张图片的棋盘格参数, 9 X 6 格大小objp_dict = {1: (9, 5),2: (9, 6),3: (9, 6),4: (9, 6),5: (9, 6),6: (9, 6),7: (9, 6),8: (9, 6),9: (9, 6),10: (9, 6),11: (9, 6),12: (9, 6),13: (9, 6),14: (9, 6),15: (9, 6),16: (9, 6),17: (9, 6),18: (9, 6),19: (9, 6),20: (9, 6),}# List of object points and corners for calibrationobjp_list = []		 # 存储对象点corners_list = []	 # 存储角点# Go through all images and find corners# 遍历objp_dict的每个参数for k in objp_dict:nx, ny = objp_dict[k]	# 取出长宽# Prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)objp = np.zeros((nx*ny, 3), np.float32)	              # 生成三维坐标,即每个点理论坐标应该是多少objp[:, : 2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2)  # 生成x和y的坐标,z坐标都是0# 对于识别的点应该的坐标序号初始化好后, 开始来读取图片中每个点的真实位置# Make a list of calibration imagesfname = 'camera_cal/calibration%s.jpg' % str(k)img = cv2.imread(fname)	# 读取一张图片# Convert to grayscale	转成灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# Find the chessboard corners# 检测角点ret, corners = cv2.findChessboardCorners(gray, (nx, ny), None)# If found, save & draw cornersif ret == True:	 # 成功检测到了# Save object points and corresponding cornersobjp_list.append(objp)	#corners_list.append(corners)# Draw and display the corners#cv2.drawChessboardCorners(img, (nx, ny), corners, ret)#plt.imshow(img)#plt.show()#print('Found corners for %s' % fname)else:	# 否则没有检测到print('Warning: ret = %s for %s' % (ret, fname))# Calibrate camera and undistort a test imageimg = cv2.imread('test_images/straight_lines1.jpg')		# 这里得保证所有图像的大小一致img_size = (img.shape[1], img.shape[0])		# 获取测试图片的尺寸#  获取相关参数ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objp_list, corners_list, img_size,None,None)return mtx, distif __name__ == '__main__':mtx, dist = calibrate_camera()save_dict = {'mtx': mtx, 'dist': dist}		# 得到数据#  将mtx和dist通过pickle保存至calibrate_camera.p中#  pickle库将此序列转化成二进制字节流存入.p文件中, wb:w--写入, b--以二进制形式with open('calibrate_camera.p', 'wb') as f:pickle.dump(save_dict, f)# Undistort example calibration image# 去畸变img = mpimg.imread('camera_cal/calibration5.jpg')	 #  读取图像dst = cv2.undistort(img, mtx, dist, None, mtx)plt.imshow(dst)	# 显示矫正结果plt.savefig('example_images/undistort_calibration.png')		# 然后保存图片

参考资料:
代码来自github的开源项目
Lane Detection with OpenCV
十年前的牢项目了, 还是很有参考意义的
上海交通大学AuTop战队开源算法讲解(三)标定与透视变换
摄像头校准之白平衡&畸变&坏点

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词