Using ray-traversal for 3D particle matching in the context of particle tracking velocimetry in fluid mechanics
Mickael Bourgoin Sander Huisman
physics.flu-dyn




mickael.bourgoin@ens-lyon.fr
Univ Lyon, École normale supérieure de Lyon, Univ Claude Bernard Lyon 1, C.N.R.S., Laboratoire de Physique, F-69342 Lyon, France
  
s.g.huisman@gmail.com
Physics of Fluids Group, Max Planck UT Center for Complex Fluid Dynamics, Faculty of Science and Technology, MESA+ Institute, and J.M. Burgers Centre for Fluid Dynamics, University of Twente, P.O. Box 217, 7500 AE Enschede, The Netherlands
Univ Lyon, École normale supérieure de Lyon, Univ Claude Bernard Lyon 1, C.N.R.S., Laboratoire de Physique, F-69342 Lyon, France



 
An innovative method based on the traversal of rays, originating from detected particles, through a three-dimensional grid of voxels is presented. The methodology has as main advantage that the outcome of the method is independent of the order of the input; the order of the cameras and the order of the rays presented as input to the algorithm does not influence the outcome. The algorithm finds matches in decreasing value of match quality, ensuring that globally best matches are matched before worse matches. The time complexity of the algorithm is found to scale efficiently with the number of cameras and particles. A variety of show-cases are given to exemplify the algorithm for different geometries and different number of cameras. The method is designed for the tracking of tracer or inertial particles in fluid mechanics, for which the particle size generally ranges from 𝒪()–𝒪(). The method, however, does not impose a size limit on the particles.


Using ray-traversal for 3D particle matching
in the context of particle tracking velocimetry in fluid mechanics
    Sander G. Huisman
    December 30, 2023
===============================================================================================================





§ INTRODUCTION

The process of calculating the 3D position based on the views of multiple cameras is traditionally called stereomatching, and is based on the biological process of stereopsis. Though most animals have binocular vision, experiments in fluid dynamics have been using more than two cameras to improve depth perception and to provide extra robustness and accuracy by data-redundancy, in particular in the context of Lagrangian particle tracking techniques <cit.> (with particles generally having a size in the range of –). The angles between the cameras should, however, be optimized. A small angle between two cameras causes large errors in the estimation of the depth. It is fairly common to put cameras at relative angles of 90 degrees, such that one of the coordinates is redundant, which makes matching easier. It is, though, not strictly necessary; it can be any angle. When more than two cameras are used, in order to minimize the error in all directions, it is generally a good strategy to globally maximise the relative angles between all the cameras. 

In the past years, important advancements have been done in the field of 3D multi-view reconstruction, impulsed by progresses in computer vision science <cit.>. In particular, situations where cameras record projective images (with a linear correspondence between real world views and acquired images) have reached a high level of mathematical understanding and algorithm developments which allow to perform 3D-matching from multi-camera recordings, with a minimum requirement of a priori knowledge of the camera arrangement and optical properties (so called internal and external calibration parameters)
<cit.>. In this regard the 3D reconstruction from multiple projective views is generally considered as a solved problem <cit.>. The case of non-projective views has, however, advanced less. This is a common situation in fluid mechanics research applications, where images can be taken through multiple interfaces, with different shapes (non-necessarily planar), separating different media (with different optical properties, as air-water interfaces) et cetera, what eventually lead to strong refraction effects and non-linear distorsions. For this reason, 3D-view reconstruction in high-resolution fluid mechanics measurements (for instance in Particle Tracking Velocimetry (PTV)) still generally relies on accurate camera calibration methods capable to handle such non-linearities <cit.> and to retrieve accurate correspondences for each camera between each pixel and the corresponding ray of light that produces an image on the pixel. A 3D-matching algorithm then proceeds by seeking correct correspondences of rays between multiple cameras.

This manuscript is on the matching algorithm of light rays from a set of several cameras used for 3D particle tracking methods. In this context, the 3D position of a particle is retrieved from the intersection of rays of light coming from each of the cameras. These rays can be obtained e.g. from Tsai's pinhole model<cit.> based on the optics of the camera and the objectives or more elaborate models<cit.>. Like ray-tracing in computer graphics, we will consider the rays to origin from each camera, towards the detected particle—in the opposite direction of light being scattered by a particle that is captured by a camera. 
For a given particle and a given camera, this ray r has an origin p (let's say at the position of the particle image on the camera sensor) and a direction v. The complexity of the problem arises when many particles are to be tracked simultaneously with several cameras. In this situation, a bundle of rays (one ray for each particle) emerges from each camera. In order to determine the actual 3D position of all the particles, one needs to find the set of rays that cross (or nearly cross) with each other. To get a feeling of the difficulty of the problem, we show an example set of rays from experiments having slightly over 1600 rays in total, emerging from 4 cameras at different view angles, see Fig. <ref>.
The problem of 3D matching can then be stated as follows: given c cameras, each with m_i rays, find sets of rays r_i.j that minimize the distance from a point to  rays coming from different cameras. Here the i index is the index of the camera and j the index of the ray for that camera. 



For a valid match, the rays from each set of rays should be from distinct cameras. A simple naïve approach would be to consider all possible sets and pick out the best matches, i.e. a brute force computation. However this would lead to m^c combinations to be tested. For a typical case of 400 particles, tracked with 4 cameras, this would lead to a large number of candidate matches (400^4 = 2.56 × 10^10). This is computationally prohibitive as too much time would be spent to go through all combinations looking for crossing or nearly crossing lines. Various strategies can be thought of that will eliminate the majority of these candidate matches. Classical alternative strategies are generally based on epipolar geometry with projections of rays between pairs of cameras <cit.>, in order to reduce the dimension of space in which crossings are to be found. The most efficient schemes can reduce the computational need from 𝒪(m^c) to 𝒪(cmlogm). However, such strategies usually operate by successive stereo-matching searches of correspondences between pairs of cameras. When more than two camera are used, this requires then either to consider one of the cameras as a reference for the pairs (with time complexity 𝒪(cmlogm)), what may lead to ambiguities (as due to imperfection of the optical models, the matches found may depend on the choice of the reference camera) or to consider all possible pairs of cameras (with time complexity 𝒪(c^2mlogm)) and apply sophisticated combinatory algorithms to perform the required consistency checks between all the pairwise stereo-matches to avoid ambiguities. Multi-focal geometry offers an alternative robust and efficient framework to achieve this, by building a set of linear tensors directly connecting the views from multiple cameras <cit.>. However this linear approach is strongly tight to the projective model generally used to describe the cameras behavior and can hardly be extend to more general situations where non-linear corrections (accounting for instance for optical distortions) are necessary.

Here we propose a new strategy, based on ray traversal across 3D voxels, which efficiently allows to perform the stereo-matching with an arbitrary number of cameras, by combining all the cameras simultaneously, without requiring pair-wise operations and consistency post-checks and independently of the calibration model used to construct the rays, which can be as simple as a pinhole camera model <cit.> or any more sophisticated non-linear calibration <cit.> giving the pixel-to-ray correspondence. Note that we will focus here on applications of the newly proposed matching method to PTV in fluid mechanics; we will not discuss the calibration and tracking (i.e. the following of matched particles over time) parts of this technique, as they can be achieved independently. Beyond PTV, the present method could also be used for the 3D reconstruction of an object by matching image keypoints from multiple images from different angles. 



§ METHOD

In this article we will focus on the traversal of rays through a 3D array of voxels (in analogy to pixels, volume elements) with constant spacing in each direction, but it can be generalized to voxels with varying widths, and even further to an octree where a (cubic) space is recursively subdivided into 8 sub-cubes in order to locally refine the 3D volume. For simplicity and didactic purposes, we will consider a rather simple scenario where there are only 3 cameras with a total of 7 rays, and where the situation can be visualized in 2D such that it is comprehensible, see fig. <ref>.





The first step of the algorithm is to traverse the rays through the voxels, this can be done very fast and is linear with the number of voxels in each direction, see e.g. Ref. <cit.>. During this process we will maintain a list of all the voxels traversed, denoted by the two indices x and y (and z in real experiments), along with the ray who traversed it, see step 1 of Table <ref>. Furthermore, we also add all the neighbours of the visited voxels (here we use a ℓ_1 norm of 1 giving 6 neighbours: left, right, above, below, front, back). Such that these rays allow for some `play' during the matching. For our near-2D toy-problem shown in Fig. <ref>, we have 319 voxels that are visited. Our first element in the list is x=4, y=11, and Ray=1.2 meaning that ray 2 from camera 1 has visited the voxel with horizontal index 4, and vertical index 11. 

The second step is to gather, for each voxel, what rays have traversed through that voxel, see step 2 of Table <ref>. One can see that a lot of voxels will have only a single ray that traversed them, but there are some, for example the second entry of the list, that is visited by four rays. This combining operation (akin to `group by' in SQL) can be done in 𝒪(nlogn) time where n is the number of elements in the list; first the list is sorted by cell indices x and y in 𝒪(nlogn) time, and then one can walk through the sorted list `cutting' the list in `grouped' sublists in 𝒪(n) time. 

The third step is to remove entries from the list which are visited by only a single camera; for 3D matching we need information from at least 2 cameras in order to get a 3D coordinate. This step can be done in 𝒪(n) time. With our toy-problem we have now 46 elements in the list. Note that we can also discard the voxel indices as they are not needed any more, they were only needed in order for step 2 to combine the rays, or physically, to `compute' which rays are close to each other. The list of step 2 shows the cell indices only for explanation purposes but it could have been removed already during step 2. Note that the selection criterium can be generalized in the case one uses many cameras, one could e.g. require that at least 3 rays from different cameras are needed for a match, this would further prune the list. 

The fourth step is to remove any duplicates from the list of step 3. This can be done efficiently by first sorting the list of lists of rays in some canonical order (e.g. small lists before long lists, and lists with equal length are ordered first by each first ray, then by the second ray, and so on, equivalent to a phone book where names have different lengths and the names are sorted first by the first character, then the second character and so on.), this sorting operation can be done in 𝒪(nlogn) time. Now we can again walk through the sorted list and only keep an element if the one before was not the same, this can be done in linear time 𝒪(n). Note that during step 2 we sorted the rays for each entry, this makes this sorting and deleting duplicates much easier. We are left with 10 entries in our list.

In the fifth step we extract all possible candidate from each of the set of rays. In general this means that the rays are grouped by camera, and then the Cartesian product is applied to get all the tuples of possible candidates. To exemplify, say that we have an entry: , , , ,  this would give 2 possibilities for camera 1, 1 possibility for camera 2, and 2 possibilities for camera 3 or a total of 4 combinations of candidates ({,,}, {,,}, {,,}, and {,,}). For our toy-problem we can see that the first entry of step 4 is expanded in to 2 possible candidate matches (the first two entries of step 5). 



In the sixth and penultimate step we calculate the point for which the average of the square distances is minimum for each candidate set of rays. This can be efficiently solved using a set of linear equations (3 of them to be precise, one for each coordinate) that can be solved using standard matrix algebra, see Fig. <ref> for an illustration for the case of 4 rays. For this point we calculate the root mean square value of the distances from this point to the rays (matching error); a smaller value means the rays cross more closely; a better and more probable match. Finally these candidates are sorted, first by number of rays in descending order (matches with more rays are more reliable than matches with less rays), and then by matching error in ascending order (smaller error is better). See the list in step 6 of Table <ref>.

The last step would be to walk through the list of candidates, starting from the top, and picking each of them for which the rays are not matched before. A naïve approach would be to remove all future entries which has one of the rays of the accepted candidate, however this would lead to 𝒪(n^2) time scaling which is unfavourable. We can do this more efficiently by keeping a hash map (hash table) which records the number of times a ray is used. This allows for fast insertion, looking up, and modification of the number of times a ray is used. This leads to an algorithm that scales with time as 𝒪(n) on average, and with a worst-case of 𝒪(nlogn). Note that the current implementation of the algorithm already allows for multiple matches per ray if needed; for a high particle density system particles can occlude the field of view such that particles appear to overlap in an image which then results in the creation of a single ray. Our code allows for matching each ray multiple time if needed. This, of course, should be used cautiously as it has the potential to result in so-called ghost particles. Different strategies can be implemented, prioritizing the number of cameras, the error, or the number of cases it is used. Also different strategies can be implemented such as the strategy proposed by Tan et al. <cit.> which includes the use of a so-called preference vector P. Additionally one could include the associated particle size in finding the best match in the selection procedure. The algorithm is flexible and can be optimized for different goals (best matches, most cameras used, least ghost et cetera).

As one can see, most of the steps have 𝒪(nlogn) time complexity or better, where n is the number of traversed voxels. We can safely assume that the number of traversed voxels scales linearly with the number of rays (and independent of the number of cameras). We do, however, have to consider the size of the voxel. The voxels should be equal or larger than the maximum distance we allow as `error' for our matching. If we allow for a maximum distance of (say) 1, we need to make sure that all the voxels within a neighbourhood of 1 from the ray are also traversed, this is done by also traversing the neighbours, see the light-shaded voxels in Fig. <ref>. It ensures us that matches with errors twice this 1 will not occur, as two (or more) rays that are more than twice the distance away from each other will not traverse the same cells. It is therefore not a good idea to introduce a smaller voxel size than this distance in combination with a larger neigborhood of say 2 in ℓ_1 distance in order to fulfil the requirement of maximum distance. This would just lead to more duplicate entries in the lists of steps 2 through 4.  For speed and memory reasons we do have to make a compromise in the choice of our voxel spacing. A very fine spacing will give much better pruning in possible candidates (the list of step 5) but memory usage and time consumption will be high in the first steps as more cells are traversed; the n in the aforementioned time complexity measures will increase inversely with the voxel size. However, if we make the voxel very large, say, in the extreme case, 1 voxel that fills the entire volume, then all the rays will traverse this single voxel, so the list of step 1, 2, 3, and 4 will be of length ∑_i m_i, however the length of step 5 will be ∏_i m_i, and will scale as m^c, where m is the number of particles and c the number of cameras; this is our naïve approach of trying out all combination of rays. And optimum is to be found with a voxel size (and maximum distance) for which the entries in steps 1 through 4 are manageable, while the number of candidates in step 5 is also kept manageable.



§ TIMING

In order to find the optimum number of divisions, we will consider an artificial experiment with 256 randomly placed particles in a cubic volume with sides of length 1. We will add 4 virtual cameras, and position them around the volume in a tetrahedral configuration. For now, we will consider a perfect arrangement of pinhole cameras such that the virtual rays are perfectly going through the virtual particles. For simplicity we will keep the voxels cubic, and vary the voxel size in all three direction simultaneously and time the duration of the execution, see Fig. <ref>. During step 3 we have only kept voxels which are visited by at least 3 cameras.



It can now clearly be observed that we find a certain number of divisions of the volume (that determines the voxel size) for which the duration of the algorithm is minimum, in our configuration it is 68 divisions. Such a minimum could be found automatically for a real measurement by e.g. a golden-section search, before processing the entire recording. We can repeat this procedure for different number of particles, see Fig. <ref>. One can see that the same balance can be found for all datasets of different number of particles. As expected, the optimal number of divisions (d) increases with the number of particles (m). We find that d ∝ m^0.461±0.005 for a 95% confidence level. The number of cells traversed, for optimal timing (and therefore divisions), scales therefore as n ∝ m^1.461±0.005.



In Fig. <ref> the optimal computing time as a function of number of particles is shown. It is found that the time t scales as t ∝ m^1.429±0.006 for a 95% confidence level. Which is close to the m^1.461 scaling that was predicted above. The scaling of m^1.429 means that doubling the number of particles results in only 2.7× more processing power.




§ PERFORMANCE





 §.§ General considerations

Next, the performance of the matching algorithm will be tested by randomly disturbing the particles in 3D for each camera. This causes the rays not to perfectly intersect, in order to mimic optical imperfections, which are unavoidable in a real PTV experiments. We artificially perturb the synthetic particles up to a distance δ by generating a random vector inside a ball of radius δ (uniformly sampled in the volume of the ball). This is done for each camera for the case of 256 particles situated inside a cubic region, observed by 4 cameras in a tetrahedral configuration. We compute the average distance between every particle and its closest neighbour as seen by the camera which is denoted by ⟨ d_closest⟩. When δ/⟨ d_closest⟩≥ 0.5 the particles can be disturbed so much that they can (on average) start `touching'. In Fig. <ref> we show the matching statistics for 50 frames of 256 random particles, perturbed for a variety of disturbances δ. It can be seen that if the particles are mismatched 20% of the mean inter-particle distance more than 90% is still correctly matched. Note that this highly depends on the arrangement of the cameras, the shape of the measurement volume, and if the particles exhibit clustering. 

To prove that our method is independent of the number of divisions we perform a synthetic test for a variety of disturbances δ for 10 frames of 4 cameras with 256 particles, for a variety of voxel sizes. As said before, the choice of voxel size has to be chosen carefully in the sense that it should not be smaller than the expected disturbance of the particles in an experiment. In such a case we can not guarantee that the traversed voxels overlap for each of the rays. So for a certain disturbance we have a lower limit on the voxel size (or an upper limit on the number of divisions). Note that for the case of perfect rays, without a disturbance, the number of divisions does not matter, the result is always the same, though the time and memory use can vary greatly. The results of our synthetic test that confirms our statement is shown in Fig. <ref>. We see that all the curves overlap, such that the accuracy is independent of the number of the divisions. We note that each of the curves ends at a different δ such as to fulfill the requirement that the voxel size should not be smaller than the disturbance.





 §.§ Comparison

In this section we compare it to classic methods that rely on matching rays (or equivalently particles) based on pairs. Various different approaches and algorithms exist, but the general description is as follows: 1 a ray (particle) is selected in one of the cameras, 2 this ray is matched (either by projection on images or directly in 3D) to a ray or multiple rays on another camera, 3 this is continued for each of the cameras until there is a reasonable match. This can be done by adding additional rays to each match so going from a single ray to pairs, to triplets, to quadruplets etc., or by looking for pairs of cameras and then combining these results. 4 This match (and the corresponding rays (particles)) are excluded and the process is iterated until all rays are matched. This iterative nature of the algorithm has some downsides as the order of the rays which are chosen on the first cameras may influence the output, but also the order of the cameras can change the outcome. Several refinement strategies exist to (partially) negate this effect, but these can be computationally expensive. We compare our code to the above-described algorithm by selecting the `first' ray from camera 1, finding the best matching ray in camera 2, using this pair we select the best matching ray in camera 3 to form a triplet, and then to select the best ray in camera 4. These rays are then removed from the pool of rays, and the algorithm is repeated until no rays are left. We also implement an improvement on this algorithm, where, after this first run, only the best 10 (or 5) matches get selected, the remaining rays get shuffled, and then the algorithm is rerun to select another 10 (or 5) best matches, and this is repeated until no rays are left. Note that the performance of the algorithm depends on how the shuffling is done, and therefore the process is done for a 100 frames and the average performance is reported. We test both algorithms for 100 frames for the case of 4 cameras and 100 particles randomly positions in a spherical domain, see Fig. <ref>. It can be seen that the voxel-based matching algorithm gives best performance compared to the tested pair-based matching algorithms.



 §.§ High particle count

We also stress-test our method for the case of high number of particles like is done for related algorithms like shake-the-box <cit.>. Note that in that method the tracking is done together with the matching, and it `works' directly on the images, while our method does not use information from previous frames, knowledge of the optics, or the camera arrangement and works solely on the rays. All our test were performed on a standard laptop which limits us to 50000 particles in the current implementation of the algorithm due to a peak memory consumption of 29. For 50000 particles randomly placed in a cube observed by 4 cameras in a tetrehedral configuration, we used 758 divisions in each direction. The total number of voxels traversed is of the order of 850 million, while the number of candidates matches is of the order 16 million. This also shows the difficulty of this method for high number of particles as all the traversed voxels have to be in memory. We show the performance of the method in the bottom of Fig. <ref>. Note that for 50000 particles spread on a typical 1 megapixel image the average separation between particles is roughly 2.2px. Particles can be detected with sub-pixel accuracy, and the error can be smaller than 0.1px by utilizing the intensity of the neighbouring pixels to find an improved estimate of the centroid of the particle. Even for 0.4 pixel disturbances we find the performance to be above 90%.





§ MEMORY







We now focus on the memory usage. We set up a synthetic case of 256 particles seen by 4 cameras in a tetrahedral configuration. We vary the number of divisions over a wide range and monitor the time and memory used by the program, more specifically it is set-up to monitor the so-called maximum resident set size, see Fig. <ref>. We observe that both the memory consumption and time consumption show an optimum. However, these are slightly shifted, which is expected as storing the traversed voxels and the candidates has a different memory ratio then the time-ratios for the time taken for traversing through the voxels and going through the candidate matches—the algorithms used have different memory and time dependencies. For the user it is best to select the number of divisions in the gray area, optimizing for memory (around 52 divisions) or for speed (around 68 divisions). These numbers will of course depend on the exact implementation and the programming language(C++11), the compiler(GNU++11), the operating system(macOS Catalina), the hardware, the number of particles (256) and their arrangement, and the number of cameras(4) and their arrangement, where the values in parentheses are the parameters used for this publication.








§ EXAMPLES


The above matching algorithm has already been successfully applied to a variety of geometries with different number of cameras. We note that the tracking of the particles was done separately with standard particle tracking algorithms <cit.>. We will go over several of the use-cases:

The code, as described above, has been used in the Twente Water Tunnel facility <cit.>, which is a vertically oriented water tunnel that is 8 tall, which has an active grid to create near homogeneous isotropic stationary turbulence. It was used to track millimetric bubbles in 3D using 4 high-speed cameras, see Ref. <cit.> and Fig. <ref>a for an overview of the measurement section and the camera arrangement. An example trajectory, colored by its horizontal speed, of one of the bubbles is shown in Fig. <ref>b. 

The code was also slightly modified to work in the Taylor-Couette geometry. For this case the rays stop traversing once it hits the inner cylinder or leaves the setup again, and candidate matches are only allowed if they are located between the cylinders. Tracking particles in a Taylor–Couette geometry warrants full optical access from the side, we have therefore chosen to perform these experiments in the Boiling Twente Taylor–Couette facility <cit.> as the outer cylinder is constructed from transparent PMMA. To track particles around the inner cylinder a large number of cameras are needed, we have therefore used 8 high-speed cameras all around the inner cylinder. We have selected 30 large trajectories for the case of counter-rotating cylinders f_i=-0.4f_o and Re=8×10^4 with finite-size neutrally-buoyant particles of 3 diameter to be visualized, see Fig. <ref>c. The color of the trajectories represent the velocity magnitude of the particles.

Another use-case is for the measurements of a turbulent jet. Here 3 high-speed cameras were used to track neutrally-buoyant tracer particles of 250 in size, see Fig. <ref>d. Lastly, the algorithm is also already used in Rayleigh-Bénard convection experiments to track tracer particles and in the Lagrangian Exploration Module <cit.> at the École normale supérieure in Lyon to track neutrally-buoyant particles for which publications are in progress.




§ CONCLUSION

In conclusion, we have explained a new fully scalable (with regard to the number of cameras used) algorithm for finding matches of rays, the results of which can be used for Particle Tracking Velocimetry (PTV) or 3D reconstruction. The main advantage over other algorithms is that the order of cameras and the order of the rays (detected particles in 2D) do not influence the outcome. Another advantage is that it will first find the globally best match, rather than a greedy algorithm (locally optimal choice). Moreover, the algorithms shows good time scaling as the number of cameras and particles increase. We have shown several use-cases with different geometries and with different number of high-speed cameras, however this algorithm is not limited to those geometries, as it could also be used to track particles (bubbles, droplets) in geometries such as pipes, von Kármán flow, oscillating grid turbulence setups, or the V-ONSET <cit.>.




This work was financially supported by the Zwaartekracht programme Multiscale Catalytic Energy Conversion (MCEC), which is part of The Netherlands Organisation for Scientific Research (NWO) and by the Project IDEXLYON of the University of Lyon in the framework of the French program  “Programme Investissements d'Avenir” (ANR-16-IDEX-0005). We thank Thomas Basset, David Dumont, Luuk Blaauw, Varghese Mathai, Chao Sun, Bianca Viggiano, and Romain Volk for feedback on, discussion of, and testing of the method and providing their experimental data for the example visualisations.




§ DATA AVAILABILITY STATEMENT

The data that support the findings of this study are available from the corresponding author upon reasonable request.



10

maas
H. G. Maas, A. Gruen and D. Papantoniou, Experiments in Fluids 15,  133
  (1993).

virant
M. Virant and T. Dracos, Measurement science and technology 8,  1539
  (1997).

ott
S. Ott and J. Mann, Journal of Fluid Mechanics 422,  207  (2000).

bourgoin2006
M. Bourgoin, N. T. Ouellette, H. Xu, J. Berg and E. Bodenschatz, Science 311,  835  (2006).

hartley2003
R. Hartley and A. Zisserman, Multiple view geometry in computer vision
  (Cambridge university press, 2003).

zhang1995
Z. Zhang, R. Deriche, O. D. Faugeras and Q. Luong, Artificial Intelligence 78,  87  (1995).

hartley1995
R. I. Hartley,  in Proceedings of IEEE International Conference on
  Computer Vision, IEEE (PUBLISHER, 1995), pp. 882–887.

criminisi2001
A. Criminisi, Accurate Visual Metrology from Single and Multiple
  Uncalibrated Images., Distinguished Dissertation Series
  (Springer-Verlag London Ltd., 2001).

basanta2013
J. Basanta, O. Kazuo and N. Kazuo, International Journal of Innovative
  Computing, Information and Control 9,  5  (2013).

machicoane
N. Machicoane, A. Aliseda, R. Volk and M. Bourgoin, Review of Scientific
  Instruments 90,  035112  (2019).

tsai
R. Tsai, IEEE Journal on Robotics and Automation 3,  323  (1987).

mathai2018
V. Mathai, S. G. Huisman, C. Sun, D. Lohse and M. Bourgoin, Phys. Rev. Lett.
  121,  054501  (2018).

bib:risoeReport
J. Mann, S. Ott and J. S. Andersen, Technical Report No. Riso-R-1036 (EN),
  Risoe National Laboratory, Roskilde, Denmark (unpublished).

amanatides
J. Amanatides, A. Woo et al.,  in Eurographics (-, 1987), No. 3,
  pp. 3–10.

tan2020
S. Tan, A. Salibindla, A. U. M. Masuk and R. Ni, Experiments in Fluids 61,  47  (2020).

schanz2016shake
D. Schanz, S. Gesemann and A. Schröder, Experiments in fluids 57,  70
   (2016).

malik1993particle
N. Malik, T. Dracos and D. Papantoniou, Experiments in fluids 15,  279
  (1993).

ouellette2006quantitative
N. T. Ouellette, H. Xu and E. Bodenschatz, Experiments in Fluids 40,  301
   (2006).

poorte2002experiments
R. Poorte and A. Biesheuvel, J. Fluid Mech. 461,  127  (2002).

huisman2015a
S. G. Huisman, R. C. A. van der Veen, G.-W. H. Bruggert, D. Lohse and C. Sun,
  Review of Scientific Instruments 86,    (2015).

LEM
R. Zimmermann, H. Xu, Y. Gasteuil, M. Bourgoin, R. Volk, J.-F. Pinton and E.
  Bodenschatz, Review of Scientific Instruments 81,  055112  (2010).

vonset
A. U. M. Masuk, A. Salibindla, S. Tan and R. Ni, Review of Scientific
  Instruments 90,  085105  (2019).




