mirror of
https://github.com/opencv/opencv.git
synced 2024-12-05 09:49:12 +08:00
67a3d35b4e
Add multiview calibration [GSOC 2022] ### Pull Request Readiness Checklist - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake The usage tutorial is on Google Docs following this link: https://docs.google.com/document/d/1k6YpD0tpSVqnVnvU2nzE34K3cp_Po6mLWqXV06CUHwQ/edit?usp=sharing
60 lines
2.8 KiB
Python
60 lines
2.8 KiB
Python
# This file is part of OpenCV project.
|
|
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
|
# of this distribution and at http://opencv.org/license.html.
|
|
|
|
import numpy as np
|
|
|
|
class Board:
|
|
def __init__(self, w, h, square_len, euler_limit, t_limit, t_origin=None):
|
|
assert w >= 0 and h >= 0 and square_len >= 0
|
|
assert len(euler_limit) == len(t_limit) == 3
|
|
self.w = w
|
|
self.h = h
|
|
self.square_len = square_len
|
|
|
|
self.t_limit = t_limit
|
|
self.euler_limit = np.array(euler_limit, dtype=np.float32)
|
|
colors = [[1,0,0], [0,1,0], [0,0,0], [0,0,1]]
|
|
self.colors_board = np.zeros((w*h, 3))
|
|
self.t_origin = np.array(t_origin, dtype=np.float32)[:,None] if t_origin is not None else None
|
|
for i in range(h):
|
|
for j in range(w):
|
|
if j <= w // 2 and i <= h // 2: color = colors[0]
|
|
elif j <= w // 2 and i > h // 2: color = colors[1]
|
|
elif j > w // 2 and i <= h // 2: color = colors[2]
|
|
else: color = colors[3]
|
|
self.colors_board[i*w+j] = color
|
|
for i in range(3):
|
|
assert len(euler_limit[i]) == len(t_limit[i]) == 2
|
|
self.euler_limit[i] *= (np.pi / 180)
|
|
|
|
def isProjectionValid(self, pts_proj):
|
|
"""
|
|
projection is valid, if x coordinate of left top corner point is smaller than x of bottom right point, ie do not allow 90 deg rotation of 2D board
|
|
also, if x coordinate of left bottom corner is smaller than x coordinate on top right corner, ie do not allow flip
|
|
pts_proj : 2 x N
|
|
"""
|
|
assert pts_proj.ndim == 2 and pts_proj.shape[0] == 2
|
|
# pdb.set_trace()
|
|
return pts_proj[0,0] < pts_proj[0,-1] and pts_proj[0,(self.h-1)*self.w] < pts_proj[0,self.w-1]
|
|
|
|
class CircleBoard(Board):
|
|
def __init__(self, w, h, square_len, euler_limit, t_limit, t_origin=None):
|
|
super().__init__(w, h, square_len, euler_limit, t_limit, t_origin)
|
|
self.pattern = []
|
|
for row in range(h):
|
|
for col in range(w):
|
|
if row % 2 == 1:
|
|
self.pattern.append([(col+.5)*square_len, square_len*(row//2+.5), 0])
|
|
else:
|
|
self.pattern.append([col*square_len, (row//2)*square_len, 0])
|
|
self.pattern = np.array(self.pattern, dtype=np.float32).T
|
|
|
|
class CheckerBoard(Board):
|
|
def __init__(self, w, h, square_len, euler_limit, t_limit, t_origin=None):
|
|
super().__init__(w, h, square_len, euler_limit, t_limit, t_origin)
|
|
self.pattern = np.zeros((w * h, 3), np.float32)
|
|
# https://stackoverflow.com/questions/37310210/camera-calibration-with-opencv-how-to-adjust-chessboard-square-size
|
|
self.pattern[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2) * square_len # only for (x,y,z=0)
|
|
self.pattern = self.pattern.T
|