opencv/apps/python-calibration-generator/board.py
Maksym Ivashechkin 67a3d35b4e
Merge pull request #22363 from ivashmak:multiview-calib
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
2023-03-23 15:42:41 +03:00

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