opencv 棋盘标定

版权声明:本文为u012678352原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.youkuaiyun.com/u012678352/article/details/80899931

代码记录

import glob
from typing import Tuple

import cv2 as cv
import numpy as np


def generate_pattern(checkerboard_size, num_of_row, num_of_col):
    """
    自定义生成棋盘格图片
    :param checkerboard_size: 棋盘格大小,此处100即可
    :param num_of_row: 棋盘格横向内角数
    :param num_of_col: 棋盘格纵向内角数
    :return:
    """
    black = np.zeros((checkerboard_size, checkerboard_size, 3), np.uint8)
    white = np.zeros((checkerboard_size, checkerboard_size, 3), np.uint8)
    black[:] = [0, 0, 0]  # 纯黑色
    white[:] = [255, 255, 255]  # 纯白色

    black_white = np.concatenate([black, white], axis=1)
    black_white2 = black_white
    white_black = np.concatenate([white, black], axis=1)
    white_black2 = white_black

    # 横向连接
    if num_of_row % 2 == 1:
        for i in range(1, (num_of_row + 1) // 2):
            black_white2 = np.concatenate([black_white2, black_white], axis=1)
            white_black2 = np.concatenate([white_black2, white_black], axis=1)
    else:
        for i in range(1, num_of_row // 2):
            black_white2 = np.concatenate([black_white2, black_white], axis=1)
            white_black2 = np.concatenate([white_black2, white_black], axis=1)
        black_white2 = np.concatenate([black_white2, black], axis=1)
        white_black2 = np.concatenate([white_black2, white], axis=1)

    jj = 0
    black_white3 = black_white2
    for i in range(0, num_of_col):
        jj += 1
        # 纵向连接
        if jj % 2 == 1:
            black_white3 = np.concatenate((black_white3, white_black2))  # =np.vstack((img1, img2))
        else:
            black_white3 = np.concatenate((black_white3, black_white2))  # =np.vstack((img1, img2))

    # 添加边缘
    black_white4 = cv.copyMakeBorder(black_white3, 30, 30, 30, 30, cv.BORDER_CONSTANT, value=[255, 255, 255])
    cv.imshow('', black_white4)
    cv.imwrite('./pattern.jpg', black_white4)
    cv.waitKey(0)
    cv.destroyAllWindows()


def get_K_and_D(checkerboard: Tuple[int, int], imgs_path, save_file=True):
    """
    获取矫正参数并保存
    :param save_file: 默认保存参数
    :param checkerboard: 棋盘行列元组
    :param imgs_path: 棋盘图片路径
    :return: DIM, K, D
    """
    CHECKERBOARD = checkerboard
    subpixel_criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.1)
    calibration_flags = cv.fisheye.CALIB_RECOMPUTE_EXTRINSIC + cv.fisheye.CALIB_CHECK_COND + cv.fisheye.CALIB_FIX_SKEW
    obj_p = np.zeros((1, CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32)
    obj_p[0, :, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
    _img_shape = None
    obj_points = []
    img_points = []
    images = glob.glob(imgs_path + '/*.jpg')
    gray = None
    for image_filename in images:
        img = cv.imread(image_filename)
        if _img_shape is None:
            _img_shape = img.shape[:2]
        else:
            assert _img_shape == img.shape[:2], "All images must share the same size."

        gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
        ret, corners = cv.findChessboardCorners(gray, CHECKERBOARD,
                                                cv.CALIB_CB_ADAPTIVE_THRESH + cv.CALIB_CB_FAST_CHECK +
                                                cv.CALIB_CB_NORMALIZE_IMAGE)
        if ret:
            obj_points.append(obj_p)
            cv.cornerSubPix(gray, corners, (3, 3), (-1, -1), subpixel_criteria)
            img_points.append(corners)
    N_OK = len(obj_points)
    K = np.zeros((3, 3))
    D = np.zeros((4, 1))
    rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
    tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
    rms, _, _, _, _ = cv.fisheye.calibrate(
        obj_points,
        img_points,
        gray.shape[::-1],
        K,
        D,
        rvecs,
        tvecs,
        calibration_flags,
        (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 1e-6)
    )
    DIM = _img_shape[::-1]
    print("Found " + str(N_OK) + " valid images for calibration")
    print("DIM=" + str(_img_shape[::-1]))
    print("K=np.array(" + str(K.tolist()) + ")")
    print("D=np.array(" + str(D.tolist()) + ")")
    if save_file:
        np.savez("../calibrate.npz", DIM=DIM, K=K, D=D)
    return DIM, K, D


def undistorted(img_or_path, K, D, DIM, scale=0.6, imshow=False):
    """

    :param img_or_path: 图片路径或cv读取的图像
    :param K:
    :param D:
    :param DIM:
    :param scale:
    :param imshow: 是否显示
    :return: 矫正后图像
    """
    if type(img_or_path) == str:
        img = cv.imread(img_or_path)
    else:
        img = img_or_path
    dim1 = img.shape[:2][::-1]  # dim1 is the dimension of input image to un-distort
    assert dim1[0] / dim1[1] == DIM[0] / DIM[
        1], "Image to undistorted needs to have same aspect ratio as the ones used in calibration"
    if dim1[0] != DIM[0]:
        img = cv.resize(img, DIM, interpolation=cv.INTER_AREA)
    Knew = K.copy()
    if scale:  # change fov
        Knew[(0, 1), (0, 1)] = scale * Knew[(0, 1), (0, 1)]
    map1, map2 = cv.fisheye.initUndistortRectifyMap(K, D, np.eye(3), Knew, DIM, cv.CV_16SC2)
    undistorted_img = cv.remap(img, map1, map2, interpolation=cv.INTER_LINEAR, borderMode=cv.BORDER_CONSTANT)
    if imshow:
        cv.imshow("undistorted", undistorted_img)
    return undistorted_img


def calibrate_single():
    """
    文件读取矫正参数
    :return:
    """
    data = np.load('./calibrate.npz')
    DIM = data['DIM']
    K = data['K']
    D = data['D']
    return DIM, K, D

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值