Mimir/research/visual-spatial-map/mirrors/opencv-multi-camera-calibration.html
2026-05-21 18:50:11 +01:00

150 lines
11 KiB
HTML

<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Multi-camera Calibration</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
TeX: {
Macros: {
matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
hdotsfor: ["\\dots", 1],
mathbbm: ["\\mathbb{#1}", 1],
bordermatrix: ["\\matrix{#1}", 1]
}
}
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body><a href="https://docs.opencv.org/cdn-cgi/content?id=zYxjvxYdVNKlxLrMBTJL3G2dwGEDBkx8ORovAM7..M4-1779105529.0450983-1.0.1.1-xgi3WyNX2pz9kL_YHlOrPwN9m7IJLZYFahLuKJID6kI" aria-hidden="true" rel="nofollow noopener" style="display: none !important; visibility: hidden !important"></a>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<script>
(function() {
var cx = '002541620211387084530:kaexgxg7oxu';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = 'https://cse.google.com/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
<gcse:search></gcse:search>
<script type="text/javascript" src="/version.js"></script>
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
<td style="padding-left: 0.5em;">
<div id="projectname">OpenCV
&#160;<span id="projectnumber">3.4.20-dev</span>
</div>
<div id="projectbrief">Open Source Computer Vision</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('../../',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li> </ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Multi-camera Calibration </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>This tutorial will show how to use the multiple camera calibration toolbox. This toolbox is based on the usage of "random" pattern calibration object, so the tutorial is mainly two parts: an introduction to "random" pattern and multiple camera calibration.</p>
<h2>Random Pattern Calibration Object </h2>
<p>The random pattern is an image that is randomly generated. It is "random" so that it has many feature points. After generating it, one print it out and use it as a calibration object. The following two images are random pattern and a photo taken for it.</p>
<div class="image">
<img src="../../random_pattern.jpg" alt="random_pattern.jpg"/>
<div class="caption">
image</div></div>
<div class="image">
<img src="../../pattern_img.jpg" alt="pattern_img.jpg"/>
<div class="caption">
image</div></div>
<p> To generate a random pattern, use the class <code><a class="el" href="../../d7/d43/classcv_1_1randpattern_1_1RandomPatternGenerator.html">cv::randpattern::RandomPatternGenerator</a></code> in <code>ccalib</code> module. Run it as </p><div class="fragment"><div class="line">cv::randpattern::RandomPatternGenerator generator(width, height);</div><div class="line">generator.generatePattern();</div><div class="line">pattern = generator.getPattern();</div></div><!-- fragment --><p> Here <code>width</code> and <code>height</code> are width and height of pattern image. After getting the pattern, print it out and take some photos of it.</p>
<p>Now we can use these images to calibrate camera. First, <code>objectPoints</code> and <code>imagePoints</code> need to be detected. Use class <code><a class="el" href="../../df/d8d/classcv_1_1randpattern_1_1RandomPatternCornerFinder.html" title="Class for finding features points and corresponding 3D in world coordinate of a &quot;random&quot; pattern...">cv::randpattern::RandomPatternCornerFinder</a></code> to detect them. A sample code can be </p><div class="fragment"><div class="line">cv::randpattern::RandomPatternCornerFinder finder(patternWidth, patternHeight, nMiniMatches);</div><div class="line">finder.loadPattern(pattern);</div><div class="line">finder.computeObjectImagePoints(vecImg);</div><div class="line">vector&lt;Mat&gt; objectPoints = finder.getObjectPoints();</div><div class="line">vector&lt;Mat&gt; imagePoints = finder.getImagePoints();</div></div><!-- fragment --><p> Here variable <code>patternWidth</code> and <code>patternHeight</code> are physical pattern width and height with some user defined unit. <code>vecImg</code> is a vector of images that stores calibration images.</p>
<p>Second, use calibration functions like <code><a class="el" href="../../d9/d0c/group__calib3d.html#ga3207604e4b1a1758aa66acb6ed5aa65d" title="Finds the camera intrinsic and extrinsic parameters from several views of a calibration pattern...">cv::calibrateCamera</a></code> or <code><a class="el" href="../../d3/ddc/group__ccalib.html#gaf285e757a4091bfbc2bb742ada3ccba7" title="Perform omnidirectional camera calibration, the default depth of outputs is CV_64F. ">cv::omnidir::calibrate</a></code> to calibrate camera.</p>
<h2>Multiple Cameras Calibration </h2>
<p>Now we move to multiple camera calibration, so far this toolbox must use random pattern object.</p>
<p>To calibrate multiple cameras, we first need to take some photos of random pattern. Of cause, to calibrate the extrinsic parameters, one pattern need to be viewed by multiple cameras (at least two) at the same time. Another thing is that to help the program know which camera and which pattern the photo is taken, the image file should be named as "cameraIdx-timestamp.*". Photos with same timestamp means that they are the same object taken by several cameras. In addition, cameraIdx should start from 0. Some examples of files names are "0-129.png", "0-187.png", "1-187", "2-129".</p>
<p>Then, we can run multiple cameras calibration as </p><div class="fragment"><div class="line">cv::multicalib::MultiCameraCalibration multiCalib(cameraType, nCamera, inputFilename,patternWidth, patternHeight, showFeatureExtraction, nMiniMatches);</div><div class="line">multiCalib.run();</div><div class="line">multiCalib.writeParameters(outputFilename);</div></div><!-- fragment --><p> Here <code>cameraType</code> indicates the camera type, <code>multicalib::MultiCameraCalibration::PINHOLE</code> and <code>multicalib::MultiCameraCalibration::OMNIDIRECTIONAL</code> are supported. For omnidirectional camera, you can refer to <code><a class="el" href="../../db/dd2/namespacecv_1_1omnidir.html">cv::omnidir</a></code> module for detail. <code>nCamera</code> is the number of camers. <code>inputFilename</code> is the name of a file generated by <code>imagelist_creator</code> from <code>opencv/sample</code>. It stores names of random pattern and calibration images, the first file name is the name of random pattern. <code>patternWidth</code> and <code>patternHeight</code> are physical width and height of pattern. <code>showFeatureExtraction</code> is a flags to indicate whether show feature extraction process. <code>nMiniMatches</code> is a minimal points that should be detected in each frame, otherwise this frame will be abandoned. <code>outputFilename</code> is a xml file name to store parameters. </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Tue Jun 17 2025 23:15:47 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v833ccba57c9e4d2798f2e76cebdd09a11778172276447" integrity="sha512-57MDmcccJXYtNnH+ZiBwzC4jb2rvgVCEokYN+L/nLlmO8rfYT/gIpW2A569iJ/3b+0UEasghjuZH/ma3wIs/EQ==" data-cf-beacon='{"version":"2024.11.0","token":"55698296dd8c4381b9a17117972ffe0c","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>