openCV方法标定OAK鱼眼相机-单目

说明,本文章参照来源:

        一文讲透鱼眼相机畸变矫正,及目标检测项目应用 值得收藏_verilog鱼眼矫正-CSDN博客

一.标定准备

1.手动拍摄50-80张标定图片。要求标定图片中的棋盘格尽量不要靠近边缘区域,否则成像质量差,容易标定失败。

2.标定棋盘格选择(内角点:9*6,A4大小)

3.工程结构:

4.openCV与python版本:

        opencv == 3.4.2.16

        python==3.7

二.代码

相机参数与畸变系数根据个人需要提取

'''
    func:鱼眼相机单目标定
    by openCV方法
    注:数据集要求拍摄数量一般在50~80之间,保证棋盘的宽高可以占整个画面1/4以上,并放入inputs文件夹中
        提取特征点与计算参数一块执行
#     棋盘标定法;棋盘标定法的缺点,是靠近圆周(外围区域)的区域,会被拉伸的很严重,视觉效果变差。
#              所以一般会进行切除,导致矫正后的图片只保留了原图的中间区域。
'''
import glob
import numpy as np
import cv2
from tqdm import tqdm

class FishEyeSignal:
    camName = 'camd'

    # 设置超参数
    CHECKERBOARD = (9, 6)  # W=12  h = 9 内角点大小
    # 设置寻找亚像素角点的参数,表示迭代停止条件 迭代30次或位置变换小于0.001停止
    criteria = (cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS, 30, 0.001)
    # subpix搜索半径
    radius = (11, 11)
    h,w = 0,0
    objpoint = []  # 3d点
    imgpoint = []  # 2d点

    def get_feature(self):
        # 获取特征点并可视化
        objp = np.zeros((1, self.CHECKERBOARD[0] * self.CHECKERBOARD[1], 3), np.float32)
        objp[0,:,:2] = np.mgrid[0:self.CHECKERBOARD[0], 0:self.CHECKERBOARD[1]].T.reshape(-1,2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y
        path_all = glob.glob(r'D:\Project\Python\test01\OpenCVMulti\sources\{}\inputs/*.jpg'.format(self.camName))
        for path in tqdm(path_all):
            image = cv2.imread(path)
            gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            self.h, self.w = gray.shape[:2]
            ret, corners = cv2.findChessboardCorners(gray, self.CHECKERBOARD, None)
            if ret:
                self.objpoint.append(objp)
                corners = cv2.cornerSubPix(image=gray, corners=corners, winSize=self.radius, zeroZone=(-1, -1),
                                           criteria=self.criteria)
                self.imgpoint.append(corners)
                # 可视化棋盘点
                path_out = path.replace('inputs', 'shows')
                # 对应世界坐标系 点顺序先X轴后Y轴,右手法则定Z轴
                cv2.drawChessboardCorners(image=image, patternSize=self.CHECKERBOARD, corners=corners, patternWasFound=True)
                # 提取特征点后的图片会被保存,可手动将提取错误的剔除
                cv2.imwrite(path_out, image)
        print('获取特征点完成')

    def cacu_parameter(self):
        # 计算相机内参和畸变系数
        flags = 0
        flags |= cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC
        flags |= cv2.fisheye.CALIB_CHECK_COND
        flags |= cv2.fisheye.CALIB_FIX_SKEW

        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6)
        ret, K, D, rvecs, tvecs = cv2.fisheye.calibrate(self.objpoint, self.imgpoint, (self.w, self.h), K=None, D=None, flags=flags, criteria=criteria)
        # print('K:',K)
        # print('D:',D)

        if ret > 5:
            print('拟合误差大,棋盘点检测不准确')
        map_combine, _ = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, (self.w, self.h), cv2.CV_16SC2)
        mapy = map_combine[:, :, 1].astype(np.float32)
        mapx = map_combine[:, :, 0].astype(np.float32)
        xpath = r'sources/npy/mapx_{}.npy'.format(self.camName)
        ypath = r'sources/npy/mapy_{}.npy'.format(self.camName)
        np.save(xpath, mapx)
        np.save(ypath, mapy)
        print('计算参数成功')
        return K,D,(self.w,self.h)

    def calibration(self):
        # 加载remap matrix 矫正输入图片
        xpath =  r'sources/npy/mapx_{}.npy'.format(self.camName)
        ypath =  r'sources/npy/mapy_{}.npy'.format(self.camName)
        mapx = np.load(xpath)
        mapy = np.load(ypath)
        image = cv2.imread(r'D:\Project\Python\test01\OpenCVMulti\sources\rgb\inputs\1721369260.9120214rgb.jpg')
        image_remap = cv2.remap(image, mapx, mapy, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
        cv2.imshow('ori',image)
        cv2.imshow('校准后',image_remap)
        cv2.waitKey(0)
        cv2.destroyAllWindows()


if __name__ == '__main__':
    a = FishEyeSignal()
    a.camName = 'rgb'
    # # # 获取特征点
    # a.get_feature()
    # # # # 计算参数
    # K,D,DMI = a.cacu_parameter()
    # # # 输入图片进行矫正验证
    a.calibration()

 三.标定结果

原图

校准后

结论:

        可以看出棋盘标定法标定鱼眼镜头在边缘处拉伸较为明显

四.标定过程中遇到的问题

 1. ret, K, D, rvecs, tvecs = cv2.fisheye.calibrate(self.objpoint, self.imgpoint, (self.w, self.h), K=None, D=None, flags=flags, criteria=criteria)
cv2.error: OpenCV(4.10.0) D:\a\opencv-python\opencv-python\opencv\modules\calib3d\src\fisheye.cpp:1502: error: (-3:Internal error) CALIB_CHECK_COND - Ill-conditioned matrix for input array 0 in function 'cv::internal::CalibrateExtrinsics'

报错:如上,

解决方法:更换openCV版本为3.4.2 2

 2.error: (-215:Assertion failed) fabs(norm_u1) > 0 in function 'cv::internal::

 解决方法:

        重新采集数据集,保证数据集图像质量清晰,棋盘格不靠经边缘点,棋盘格占据图像视野不要太小。

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值