Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
302 views
in Technique[技术] by (71.8m points)

python - OpenCV Stereo Fisheye calibration

I work with an Insta 360 Evo. However, I use this as a stereo camera and would like to calibrate it. For this I would like to use the OpenCV Fisheye. Calibrating the cameras individually works, but not the StereoCalibrate function. There I always get the following error message:

cv2.error: OpenCV(4.5.1) C:UsersappveyorAppDataLocalTemp1pip-req-build-wvn_it83opencvmodulescalib3dsrcfisheye.cpp:1051: error: (-215:Assertion failed) abs_max < threshold in function 'cv::fisheye::stereoCalibrate'

When I look in the Fisheye.cpp the error only comes when I have bad calibration data, however I have replaced the data several times and it does not work. Can it be that the OpenCV cannot work with FOV 180 degree? If this is possible, is there another way to calibrate the StereoCamera?

Here is my code:

FisheyeCalibration.py -> for one Fisheye Camera

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, 30, 0.1)
        objp = np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1], 1, 3), np.float64)
        objp[:, 0, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 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: {}Calibration 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, 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, 1, 3), dtype=np.float64) for i in range(N_OK)]
        self.tvecs = [np.zeros((1, 1, 3), 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, 30, 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 -> for the 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, videoIn, paramerterIn, parameterOut, CHECKERBOARD=(5,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, 30, 0.1)
        objp = np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1], 1, 3), np.float64)
        objp[:, 0, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 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, self.CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
            retR, cornersR = cv2.findChessboardCorners(grayR, self.CHECKERBOARD, 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, self.CHECKERBOARD, 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, cornersL, (3, 3), (-1, -1), self.subpix_criteria)
                self.imgpointsLeft.append(cornersL)

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

            self._skip(self.skip)
            retVideoL, _ = self.leftVideo.read()
            retVideoR, _ = 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, 1, 3), dtype=np.float64)
        self.T = np.zeros((1, 1, 3), dtype=np.float64)

        TERMINATION_CRITERIA = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 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, 1, self.CHECKERBOARD[0] * self.CHECKERBOARD[1], 3))
        self.imgpointsLeft = np.reshape(self.imgpointsLeft, (N_OK, 1, self.CHECKERBOARD[0] * self.CHECKERBOARD[1], 2))
        self.imgpointsRight = np.reshape(self.imgpointsRight, (N_OK, 1, self.CHECKERBOARD[0] * self.CHECKERBOARD[1], 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.K_left, self.D_left,
                self.K_right, self.D_right,
                (self.leftVideo.width, self.leftVideo.height), self.R, 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 -> My Helper Class

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__
question from:https://stackoverflow.com/questions/65852617/opencv-stereo-fisheye-calibration

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...