>>> 点击进入:OpenCV专栏<<<
相机去畸变利用的是张氏矫正法,里面使用了极大似然估计,模拟近似畸变系数,所以需要N>=4个匹配点对。(一般来说,一张图片,全捕捉到或者全丢失。)
计算畸变系数,使用的API为:cv2.calibrateCamera。由于这里求的是畸变系数,是一个比例,所以传参不用考虑实际尺寸。传入单位尺寸即可。这里需要传入
函数的使用:
角点检测与FindChessboardCorners函数
# -*- coding:utf-8 -*-
'''
@Author: knocky
@Blog: https://blog.csdn.net/zzx188891020
@E-mail: [email protected]
@File: calibrate.py
@CreateTime: 2020/6/8 22:26
'''
import glob
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 相机校正:外参,内参,畸变系数
def cal_calibrate_params(file_paths):
'''
说明:cv2.calibrateCamera需要直接传入所有图片的关键点List ,所以需要构造成响应的格式。
通过cv2.findChessboardCorners找到全部内角点,如果有一个丢失,则此图片失效。
'''
# 存储角点数据的坐标
object_points = [] # 角点在三维空间的位置
image_points = [] # 角点在图像空间中的位置
# 生成角点在真实世界中的位置
objp = np.zeros((nx * ny, 3), np.float32)
# 生成对应的角点(x,y)集合,扫描的顺序为先行后列
# [[0, 0],[1, 0],[2, 0],[3, 0],[4, 0]..... [5, 5],[6, 5],[7, 5], [8, 5]
objp[:, :2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2)
# 角点检测
for file_path in file_paths:
img = cv2.imread(file_path)
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 角点检测
# rect:输出是否找到角点,找到角点返回1,否则返回0
# coners: shape(54,1,2) 54 是坐标点个数, 2 是(x,y)
# [[[545.3228 343.05032]] [[602.6792 342.8268 ]] [[660.09796 341.2892 ]]....
rect, coners = cv2.findChessboardCorners(gray, (nx, ny), None)
imgcopy = img.copy()
# 检测完角点之后我们可以将将测到的角点绘制在图像上
cv2.drawChessboardCorners(imgcopy, (nx, ny), coners, rect)
# 这个是自定义函数,绘制对比图
plot_contrast_image(img, imgcopy)
if rect == True:
object_points.append(objp)
image_points.append(coners)
# 相机校正
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None)
return ret, mtx, dist, rvecs, tvecs
# 图像去畸变:利用相机校正的内参,畸变系数
def img_undistort(img, mtx, dist):
dis = cv2.undistort(img, mtx, dist, None, mtx)
return dis
# 绘制对比图
def plot_contrast_image(origin_img, converted_img, origin_img_title="origin_img", converted_img_title="converted_img",
converted_img_gray=False):
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 20))
ax1.set_title = origin_img_title
ax1.imshow(origin_img)
ax2.set_title = converted_img_title
if converted_img_gray == True:
ax2.imshow(converted_img, cmap="gray")
else:
ax2.imshow(converted_img)
plt.show()
if __name__ == '__main__':
"参数设置"
nx = 9
ny = 6
file_paths = glob.glob("../camera_cal/calibration*.jpg")
ret, mtx, dist, rvecs, tvecs = cal_calibrate_params(file_paths)
if np.all(mtx != None):
img = cv2.imread("../test/test1.jpg")
undistort_img = img_undistort(img, mtx, dist)
plot_contrast_image(img, undistort_img)
print("done")
else:
print("failed")
使用objp[:, :2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2)构造目标点的相对坐标,如何与扫描顺序正好匹配呢?
这里提到了,好像和设置的坐标有关系。
一分钟详解OpenCV之相机标定函数calibrateCamera()
根据输出的20张图来看,几乎都是一个输出模式,所以感觉只要按照一个固定的方式设置就可以,不用纠结乱序问题。