相机内参和畸变系数标定 opencv-python


import os
import cv2
import argparse
import numpy as np

class CheckBoard:
    def __init__(self, points_per_col, points_per_row, square_size) -> None:
        self.points_per_col = points_per_col
        self.points_per_row = points_per_row
        self.square_size = square_size

        self.patten_size = (self.points_per_row, self.points_per_col)

        self.corners_world = []
        for row in range(self.points_per_col):
            for col in range(self.points_per_row):
                self.corners_world.append([float(col * self.square_size), float(row * self.square_size), 0.0])
        self.corners_pixel_all = []

    def add_corners_pixel(self, img):
        self.img_size = (img.shape[1], img.shape[0])

        corners_pixel = []
        found, corners_pixel = cv2.findChessboardCorners(img, self.patten_size, None)

        if found:
            img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
            cv2.cornerSubPix(img_gray, corners_pixel, (5, 5), (-1, -1), criteria)
            self.corners_pixel_all.append(corners_pixel)
            return True
        else:
            return False

    def caliCam(self):
        if len(self.corners_pixel_all) < 3:
            print("Not enough images")
            return None

        obj_points = []
        img_points = []
        for i in range(len(self.corners_pixel_all)):
            obj_points.append(self.corners_world)
            img_points.append(self.corners_pixel_all[i])
 
        ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(np.array(obj_points, dtype=np.float32), img_points, self.img_size, None, None)
        return ret, mtx, dist, rvecs, tvecs


if __name__ == "__main__":
    np.set_printoptions(suppress=True, precision=5, linewidth=500)

    parser = argparse.ArgumentParser(description='Camera Calibration')
    parser.add_argument('path', type=str, help='images forder', required=True)
    parser.add_argument('--rows', type=int, help="rows of checkboard", default=8) # 8x11, 21mm
    parser.add_argument('--cols', type=int, help="cols of checkboard", default=11)
    parser.add_argument('--square_size', type=int, help="size (mm) of checkboard", default=21)
    parser.add_argument('--verbose', action='store_true', help='show image')
    args = parser.parse_args()

    img_forder = args.path
    if not os.path.exists(img_forder):
        print(f"path {img_forder} not exist")
        exit(0)

    rows = args.rows
    cols = args.cols
    square_size = args.square_size
    verbose = args.verbose

    img_files = os.listdir(img_forder)
    imgs = []
    for img_file in img_files:
        img = cv2.imread(os.path.join(img_forder, img_file))
        if img is not None:
            imgs.append(img)

    if verbose:
        cv2.namedWindow("img")

    # 交叉点的行数,列数,每个交叉点的边长
    cb = CheckBoard(rows, cols, square_size)
    for i, img in enumerate(imgs):
        res = cb.add_corners_pixel(img)
        if res:
            if verbose:
                cv2.drawChessboardCorners(img, cb.patten_size, cb.corners_pixel_all[-1], True)
                cv2.imshow("img", img)
                key = cv2.waitKey(0)
                if key == ord('q') or key == 27:
                    break
        else:
            print("{} : failed".format(img_files[i]))

    cv2.destroyAllWindows()
    ret, mtx, dist, rvecs, tvecs = cb.caliCam()
    print("ret:\n", ret)
    print("mtx:\n", mtx)
    print("dist: (k1,k2,p1,p2,k3)\n")
    print("dist:\n", np.array2string(dist[0], separator=', '))

如图,交叉点的行数为8,列数为11,黑色矩形的边长为21mm。
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值