基于python的opencv相机标定(采用黑白棋盘格标定板)

基于python的相机标定(采用黑白棋盘格图片)

系列文章目录

[第一章 基于python的相机标定(采用黑白棋盘格图片)](https://blog.csdn.net/HWHXXX/article/details/119905200)

文章目录

  • 基于python的相机标定(采用黑白棋盘格图片)
  • 系列文章目录
  • 前言
  • 一、准备标定用的图片
  • 二、提取照片中棋盘格的角点
    • 1.载入需要用的库
    • 2.读取图片并提取角点
    • 3.标定相机


前言

工业相机在正常使用前需要进行相机标定,得出相机的内参矩阵与畸变系数。


一、准备标定用的图片

在标定之前,需要用待标定的相机拍摄用于标定相机的图片。
拍摄照片的质量一定程度上影响相机标定的效果,所以拍摄时一定要注意拍摄角度与环境光亮度。
1:在确定好标定板与相机之间的距离之后,对相机进行调焦,使得相机可以看清标定板。在调好焦之后就不能再次对相机进行调焦了。若再次调焦,则需重新进行相机标定。
2:环境光的补充,要使标定板尽量亮起来,如果太过灰暗,会影响拍摄照片的质量。
3:拍摄照片的角度,尽量让标定板出现在照片的每个区域(个人将图片区域划分为5个,如图1所示),然后在每个区域内标定板也可以垂直于相机拍摄,前倾,后倾,左倾,右倾等角度都可以拍摄,但需注意在每个区域内拍摄角度应保持均匀(不均匀的话个人认为会略微影响标定结果)。
基于python的opencv相机标定(采用黑白棋盘格标定板)_第1张图片
图1 个人划分的5个区域
4:拍摄照片需尽量清晰,即拍摄过程中如果为手持标定板拍摄,拿稳了,别抖。
5:拍摄照片总数量,在保证每个拍摄角度拍摄数量均匀的情况下,总数量应该为5的倍数,可以是15,20,25张等等。总量多少没关系的。

二、提取照片中棋盘格的角点

1.载入需要用的库

import cv2 as cv
import numpy as np
import time
import os

2.读取图片并提取角点

    w = 12  # 棋盘格角点每行数量
    h = 9  # 棋盘格角点每列数量
    # 生成棋盘格三维坐标
    obj_points = np.zeros(((w*h), 3), np.float32)
    obj_points[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)  # 将纯0数组进行编码,编码代表每一个角点的位置信息,例如[0., 0., 0.],[1., 0., 0.]
    obj_points = np.reshape(obj_points, (w*h, 1, 3))  # 将位置信息矩阵变为w*h个1行三列的矩阵
    # 计算棋盘格内角点的三维坐标及其在图像中的二维坐标
    all_obj_points = [] # 这两个空数组很关键,如果是一张图片进行标定代码测试,这个也需要创建,如果没有,会一直报错
    all_points = []
    file_path = './0820-A3-resize'  # 存图片的文件夹,但是这个读取方式有一个缺点,文件夹内只能有图片,不能有别的类型的文件,否则会报错
    for file_name in os.listdir(file_path):
        img = cv.imread(file_path + '/' + file_name)
        img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)  # 转为灰度图
        begin = time.time()
        ret, corners1 = cv.findChessboardCorners(img_gray, (w, h))  # 寻找内角点
        if ret == True:  # 如果寻找到足够数量的内焦点
            _, corners2 = cv.find4QuadCornerSubpix(img_gray, corners1, (5, 5))  # 细化内角点
            end = time.time()
            print((end-begin)/60)
            img_h, img_w = img.shape[:2]  # 获取图像尺寸
            all_obj_points.append(obj_points)  # 计算三维坐标
            all_points.append(corners2)  # 计算二维坐标
        else:
            end = time.time()
            print((end-begin)/60)
            img_h, img_w = img.shape[:2]

这段代码的主要功能就是读取所有图片并提取内角点。
函数都是opencv中写好的接口,主要用到的就是findChessboardCorners, find4QuadCornerSubpix
有兴趣可以网上查一下这两个函数,用起来都比较简单,源码原理的话,个人暂未进行深入研究。
主要输出参数为all_obj_points, all_points, img_w, img_h
第一个参数为内角点的世界坐标系中的坐标,第二个参数为内角点在图片中的坐标,第三参数为图像像素高度,第四个参数为图像像素宽度。

3.标定相机

    ret, camara_matrix, distcoeffs, rvecs, tvecs = cv.calibrateCamera(all_obj_points, all_points,
                                                                      (img_w, img_h), None, None)
    print("重投影参数:\n{}".format(ret))
    print("内参矩阵: \n{}".format(camara_matrix))
    print("畸变系数: \n{}".format(distcoeffs))
    print("旋转向量:\n{}".format(rvecs))
    print("平移向量:\n{}".format(tvecs))

标定相机的函数为calibrateCamera,五个输出参数上面代码所示。

你可能感兴趣的:(opencv,opencv,python)