OpenCV 立体鱼眼校准

问题描述

我使用 Insta 360 Evo。但是,我将其用作立体相机并想对其进行校准。为此,我想使用 OpenCV 鱼眼。单独校准相机有效,但不适用于 StereoCalibrate 功能。在那里我总是收到以下错误消息:

cv2.error: OpenCV(4.5.1) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-wvn_it83\opencv\modules\calib3d\src\fisheye.cpp:1051: 错误:(-215:断言失败)abs_max

当我查看 Fisheye.cpp 时,错误只会在我有错误的校准数据时出现,但是我已经多次替换了数据,但它不起作用。 是不是 OpenCV 不能在 180 度的 FOV 下工作? 如果可以,是否还有其他方法可以校准立体相机?

这是我的代码

FisheyeCalibration.py -> 用于一台鱼眼相机

import cv2
assert cv2.__version__[0] >= '3','The fisheye module requires opencv version >= 3.0.0'

from VideoReader import VideoReader

import os
import numpy as np


class calibrateFisheye(object):
    def __init__(self,videoIn,parameterOut,CHECKERBOARD=(5,7)):
        self.video = VideoReader(videoIn)
        self.parameterOut = parameterOut
        self.CHECKERBOARD = CHECKERBOARD

        #self.subpix_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,30,0.1)
        self.calibration_flags = cv2.fisheye.CALIB_RECOmpuTE_EXTRINSIC + cv2.fisheye.CALIB_CHECK_COND + cv2.fisheye.CALIB_FIX_SKEW

        #objp = np.zeros((1,CHECKERBOARD[0] * CHECKERBOARD[1],3),np.float32)
        #objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0],0:CHECKERBOARD[1]].T.reshape(-1,2)

        self.subpix_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,0.1)
        objp = np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1],1,np.float64)
        objp[:,2)
        self.objp = objp

        self.objpoints = []  # 3d point in real world space
        self.imgpoints = []  # 2d points in image plane.

        self.computePoints()
        self.calibrate()
        self.saveNp()


    def _skip(self,count):
        for i in range(count):
            retVideo,_ = self.video.read()
            if not retVideo:
                return

    def computePoints(self):
        retVideo,f = self.video.read()

        while retVideo:
            print("Process-ID: {}\t\tCalibration finished to {:.2f} %".format(os.getpid(),self.video.progress()))
            gray = self.video.getGrayFrame()
            # Find the chess board corners
            ret,corners = cv2.findChessboardCorners(gray,self.CHECKERBOARD,cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_norMALIZE_IMAGE)
            if ret == True:
                self.objpoints.append(self.objp)
                cv2.cornerSubPix(gray,corners,(3,(-1,-1),self.subpix_criteria)
                self.imgpoints.append(corners)

            self._skip(0)
            retVideo,f = self.video.read()
            # = False

    def calibrate(self):
        self.objpoints = np.array(self.objpoints)
        self.imgpoints = np.array(self.imgpoints)

        N_OK = len(self.objpoints)
        self.K = np.zeros((3,3))
        self.D = np.zeros((4,1))
        self.rvecs = [np.zeros((1,dtype=np.float64) for i in range(N_OK)]
        self.tvecs = [np.zeros((1,dtype=np.float64) for i in range(N_OK)]
        self.rms,_,_ = \
            cv2.fisheye.calibrate(
                self.objpoints,self.imgpoints,(self.video.width,self.video.height),self.K,self.D,self.rvecs,self.tvecs,self.calibration_flags,(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,1e-6)
            )

    def saveNp(self):
        np.save(self.parameterOut + "k",self.K)
        np.save(self.parameterOut + "d",self.D)
        np.save(self.parameterOut + "rvecs",self.rvecs)
        np.save(self.parameterOut + "tvecs",self.tvecs)
        np.save(self.parameterOut + "rms",self.rms)

StereoFisheyeCaibration.py -> 用于 StereoCalibration

from VideoReader import VideoReader

import cv2
assert cv2.__version__[0] >= '3','The fisheye module requires opencv version >= 3.0.0'

import numpy as np

class calibrationFisheyeStereo(object):
    def __init__(self,paramerterIn,7),skip=0):
        print(skip)
        self.skip = skip
        self.CHECKERBOARD = CHECKERBOARD
        self.leftVideo = VideoReader(videoIn[0])
        self.rightVideo = VideoReader(videoIn[1])

        self.parameterLeft = paramerterIn[0]
        self.parameterRight = paramerterIn[1]
        self.parameterOut = parameterOut

        self.subpix_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,2)
        self.objp = objp

        self.objpoints = []  # 3d point in real world space
        self.imgpointsLeft = []  # 2d points in image plane.
        self.imgpointsRight = []  # 2d points in image plane.

        self.computePoints()
        self.calibrate()
        self.saveNp()

    def _skip(self,count):
        for i in range(count):
            retVideoL,_ = self.leftVideo.read()
            retVideoR,_ = self.rightVideo.read()
            if not retVideoR or not retVideoL:
                return

    def computePoints(self):
        retVideoL,f1 = self.leftVideo.read()
        retVideoR,f2 = self.rightVideo.read()

        i = 0

        while retVideoL and retVideoR:
            print("Calibration finished to {:.2f} %".format(self.leftVideo.progress()))
            grayL = self.leftVideo.getGrayFrame()
            grayR = self.rightVideo.getGrayFrame()

            retL,cornersL = cv2.findChessboardCorners(grayL,cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_norMALIZE_IMAGE)
            retR,cornersR = cv2.findChessboardCorners(grayR,cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_norMALIZE_IMAGE)

            if ((retL == True) and (retR == True)):
                i += 1
                print(i)
                #img = cv2.drawChessboardCorners(grayL,cornersL,retL)
                #img = cv2.resize(img,(self.leftVideo.width//2,self.leftVideo.height//2),interpolation=cv2.INTER_AREA)
                #if cv2.waitKey(1) & 0xFF == ord('q'):
                    #exit()
                #cv2.imshow("windowTxt",img)
                self.objpoints.append(self.objp)

                cv2.cornerSubPix(grayL,self.subpix_criteria)
                self.imgpointsLeft.append(cornersL)

                cv2.cornerSubPix(grayR,cornersR,self.subpix_criteria)
                self.imgpointsRight.append(cornersR)

            self._skip(self.skip)
            retVideoL,_ = self.rightVideo.read()
        print(i)

    def calibrate(self):
        self.D_left = np.load(self.parameterLeft + "d.npy")
        self.K_left = np.load(self.parameterLeft + "k.npy")

        self.D_right = np.load(self.parameterRight + "d.npy")
        self.K_right = np.load(self.parameterRight + "k.npy")

        self.R = np.zeros((1,dtype=np.float64)
        self.T = np.zeros((1,dtype=np.float64)

        TERMINATION_CRITERIA = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,0.1)
        FLAG = cv2.fisheye.CALIB_FIX_INTRINSIC

        N_OK = len(self.imgpointsLeft)

        self.objpoints = np.array(self.objpoints,dtype=np.float64)
        #self.imgpointsLeft = np.asarray(self.imgpointsLeft,dtype=np.float64)
        #self.imgpointsRight = np.asarray(self.imgpointsRight,dtype=np.float64)

        self.imgpointsLeft = np.array(self.imgpointsLeft,dtype=np.float64)
        self.imgpointsRight = np.array(self.imgpointsRight,dtype=np.float64)

        """self.objpoints = np.reshape(self.objpoints,(N_OK,self.CHECKERBOARD[0] * self.CHECKERBOARD[1],3))
        self.imgpointsLeft = np.reshape(self.imgpointsLeft,2))
        self.imgpointsRight = np.reshape(self.imgpointsRight,2))"""

        self.rms,self.K_left,self.D_left,self.K_right,self.D_right,self.R,self.T = \
            cv2.fisheye.stereoCalibrate(
                self.objpoints,self.imgpointsLeft,self.imgpointsRight,(self.leftVideo.width,self.leftVideo.height),self.T,FLAG,TERMINATION_CRITERIA)

    def saveNp(self):
        np.save(self.parameterOut + "K_left",self.K_left)
        np.save(self.parameterOut + "K_right",self.K_right)

        np.save(self.parameterOut + "D_left",self.D_left)
        np.save(self.parameterOut + "D_right",self.D_right)

        np.save(self.parameterOut + "R",self.R)
        np.save(self.parameterOut + "T",self.T)
        np.save(self.parameterOut + "rms",self.rms)

VideoReader.py -> 我的助手类

import cv2

class VideoReader(object):
    def __init__(self,path):
        self.video = cv2.VideoCapture(path)
        self.fps = self.video.get(cv2.CAP_PROP_FPS)
        self.total_frames = self.video.get(cv2.CAP_PROP_FRAME_COUNT)
        self.current_frames = self.video.get(cv2.CAP_PROP_POS_FRAMES)

        self.frame = None
        self.ret = False
        self.windowNames = {}
        self.width = None
        self.height = None

    def __del__(self):
        self.video.release()
        for name in self.windowNames:
            cv2.destroyWindow(name)

    def read(self):
        self.ret,self.frame = self.video.read()
        self.current_frames = self.video.get(cv2.CAP_PROP_POS_FRAMES)
        if self.ret:
            self.height,self.width,_ = self.frame.shape
        return self.ret,self.frame

    def progress(self):
        percentage = self.current_frames / self.total_frames * 100
        return percentage

    def duration(self):
        duration = self.fps * self.total_frames
        return duration

    def display(self,windowTxt):
        if self.ret:
            self.windowNames[windowTxt]=0
            if cv2.waitKey(1) & 0xFF == ord('q'):
                exit()
            cv2.imshow(windowTxt,self.frame)

    def getGrayFrame(self):
        return cv2.cvtColor(self.frame,cv2.COLOR_BGR2GRAY)

    def __version__(self):
        return cv2.__version__

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)