mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
86b9885c90fc6d546d62bd220a813d8943d82b29
Fix empty intrinsics handling and minor calibration improvements #27651 Closes: #27650 Minor changes: * Filter out `""` in `files_with_intrinsics`. * Match the list length with the number of cameras. * Fix unpacking from `cv.calibrateMultiviewExtended`. * Adjust visualisation to ensure correct shapes. * Save `cam_ids` as a list in YAML. * Removed typos. <details> <summary>Pytest</summary> ```py import json import numpy as np import importlib.util import sys import pytest spec = importlib.util.spec_from_file_location("mv", "multiview_calibration.py") mv = importlib.util.module_from_spec(spec) sys.modules["mv"] = mv spec.loader.exec_module(mv) def test_insideImageMask_boundaries(): # w = 10, h = 10, valid x,y: [0..9] pts = np.array([[0, 5, 9, -1, 10], [0, 5, 9, 5, 5]], dtype=np.int32) m = mv.insideImageMask(pts, 10, 10) assert m.tolist() == [True, True, True, False, False] def test_intrinsics_empty_ignored_and_forwarded(tmp_path, monkeypatch): cam1 = tmp_path / "cam1.txt" cam2 = tmp_path / "cam2.txt" cam1.write_text("\n") cam2.write_text("\n") opened = [] class FakeNode: def __init__(self, name): self.name = name def mat(self): if self.name in ("camera_matrix", "cameraMatrix"): return np.eye(3, dtype=np.float32) if self.name in ("dist_coeffs", "distortion_coefficients"): return np.zeros((1, 5), dtype=np.float32) return None class FakeFS: def __init__(self, filename, flags=None): opened.append(filename) def getNode(self, key): return FakeNode(key) monkeypatch.setattr(mv.cv, "FileStorage", FakeFS) captured = {} def fake_calibrateFromPoints(pattern_points, image_points, image_sizes, models, image_names, find_intrinsics_in_python, Ks=None, distortions=None): captured["Ks"] = Ks captured["dist"] = distortions return dict( Rs=[np.zeros((3, 1)) for _ in models], Ts=[np.zeros((3, 1)) for _ in models], Ks=Ks, distortions=distortions, rvecs0=[np.zeros((3, 1))], tvecs0=[np.zeros((3, 1))], errors_per_frame=np.ones((len(models), 1), dtype=np.float32), output_pairs=[], image_points=image_points, models=models, image_sizes=image_sizes, pattern_points=pattern_points, detection_mask=np.ones((len(models), 1), np.uint8), image_names=image_names, ) monkeypatch.setattr(mv, "calibrateFromPoints", fake_calibrateFromPoints) out = mv.calibrateFromImages( files_with_images=[str(cam1), str(cam2)], grid_size=[3, 2], pattern_type="checkerboard", models=[0, 0], dist_m=0.1, winsize=(5, 5), points_json_file="", debug_corners=False, RESIZE_IMAGE=False, # <- match real signature name here find_intrinsics_in_python=False, is_parallel_detection=False, cam_ids=["1", "2"], files_with_intrinsics=["", str(tmp_path / "intr.yml")], board_dict_path=None, ) assert "" not in opened assert captured["Ks"] is not None and len(captured["Ks"]) == 2 assert captured["dist"] is not None and len(captured["dist"]) == 2 def test_visualize_converts_rvec_to_R_and_t_to_col(monkeypatch): called = {} def fake_plotCamerasPosition(Rs, Ts, image_sizes, pairs, pattern, frame_idx, cam_ids, detection_mask): called["R_shapes"] = [R.shape for R in Rs] called["T_shapes"] = [T.shape for T in Ts] def fake_plotProjection(points_2d, pattern_points, rvec0, tvec0, rvec1, tvec1, K, dist_coeff, model, *rest): called["tvec1_shape"] = tvec1.shape called["K_shape"] = K.shape monkeypatch.setattr(mv.plt, "savefig", lambda *a, **k: None) monkeypatch.setattr(mv.plt, "close", lambda *a, **k: None) monkeypatch.setattr(mv, "plotCamerasPosition", fake_plotCamerasPosition) monkeypatch.setattr(mv, "plotProjection", fake_plotProjection) detection_mask = np.ones((1, 1), np.uint8) Rs = [np.zeros((3, 1), dtype=np.float32)] # rvec Ts = [np.array([[0., 0., 0.]], dtype=np.float32)] # row 1x3 Ks = [np.eye(3, dtype=np.float32)] distortions = [np.zeros((1, 5), dtype=np.float32)] models = [0] image_points = [[np.array([[10., 10.]], dtype=np.float32)]] errors_per_frame = np.array([[1.0]], dtype=np.float32) rvecs0 = [np.zeros((3, 1), dtype=np.float32)] tvecs0 = [np.zeros((3, 1), dtype=np.float32)] pattern_points = np.array([[0., 0., 0.]], dtype=np.float32) image_sizes = [(100, 100)] output_pairs = [] image_names = None cam_ids = ["0"] mv.visualizeResults( detection_mask, Rs, Ts, Ks, distortions, models, image_points, errors_per_frame, rvecs0, tvecs0, pattern_points, image_sizes, output_pairs, image_names, cam_ids ) assert called["R_shapes"] == [(3, 3)] assert called["T_shapes"] == [(3, 1)] assert called["tvec1_shape"] == (3, 1) assert called["K_shape"] == (3, 3) ``` </details> ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [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 - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
OpenCV: Open Source Computer Vision Library
Resources
- Homepage: https://opencv.org
- Courses: https://opencv.org/courses
- Docs: https://docs.opencv.org/5.x/
- Q&A forum: https://forum.opencv.org
- previous forum (read only): http://answers.opencv.org
- Issue tracking: https://github.com/opencv/opencv/issues
- Additional OpenCV functionality: https://github.com/opencv/opencv_contrib
- Donate to OpenCV: https://opencv.org/support/
Contributing
Please read the contribution guidelines before starting work on a pull request.
Summary of the guidelines:
- One pull request per issue;
- Choose the right base branch;
- Include tests and documentation;
- Clean up "oops" commits before submitting;
- Follow the coding style guide.
Additional Resources
- Submit your OpenCV-based project for inclusion in Community Friday on opencv.org
- Subscribe to the OpenCV YouTube Channel featuring OpenCV Live, an hour-long streaming show
- Follow OpenCV on LinkedIn for daily posts showing the state-of-the-art in computer vision & AI
- Apply to be an OpenCV Volunteer to help organize events and online campaigns as well as amplify them
- Follow OpenCV on Mastodon in the Fediverse
- Follow OpenCV on Twitter
- OpenCV.ai: Computer Vision and AI development services from the OpenCV team.
Description
Languages
C++
87.6%
C
3.2%
Python
2.9%
CMake
2%
Java
1.5%
Other
2.6%