cam_geom
for the Rust language📷 📐 Geometric models of cameras for photogrammetry
The crate implements geometric models of cameras which may be useful for photogrammetry.
The crate provides a couple camera models, the pinhole perspective
camera and the
orthographic
camera. Adding
another camera model entails implementing the
IntrinsicParameters
trait. See the
opencv_ros_camera
crate
for one example.
Also provided is the function
best_intersection_of_rays()
which
determines the best 3D point corresponding to the intersection of multiple
rays. Thus, this crate is also useful for multiple view geometry.
Characteristics:
serde
.
Enable with the serde-serialize
cargo feature.nalgebra
crate.IntrinsicParameters
trait. While the
camera models implemented in this crate are linear, there is no
requirement that implementations are linear. For example, the
opencv_ros_camera
crate
exhibits distortion.ExtrinsicParameters
based on the
nalgebra::Isometry3
type to handle the camera pose.std
) and no heap allocations. In other words, this can run on a
bare-metal microcontroller with no OS.To run the basic unit tests:
cargo test
To run all unit tests:
cargo test --features serde-serialize
no_std
Since the thumbv7em-none-eabihf
target does not have std
available, we
can build for it to check that our crate does not inadvertently pull in
std. The unit tests require std, so cannot be run on a no_std
platform.
The following will fail if a std dependency is present:
```
cargo build --no-default-features --target thumbv7em-none-eabihf ```
```rust use cam_geom::*; use nalgebra::{Matrix2x3, Unit, Vector3};
// Create two points in the world coordinate frame. let world_coords = Points::new(Matrix2x3::new( 1.0, 0.0, 0.0, // point 1 0.0, 1.0, 0.0, // point 2 ));
// perepective parameters - focal length of 100, no skew, pixel center at (640,480) let intrinsics = IntrinsicParametersPerspective::from(PerspectiveParams { fx: 100.0, fy: 100.0, skew: 0.0, cx: 640.0, cy: 480.0, });
// Set extrinsic parameters - camera at (10,0,0), looing at (0,0,0), up (0,0,1) let camcenter = Vector3::new(10.0, 0.0, 0.0); let lookat = Vector3::new(0.0, 0.0, 0.0); let up = Unit::newnormalize(Vector3::new(0.0, 0.0, 1.0)); let pose = ExtrinsicParameters::fromview(&camcenter, &lookat, &up);
// Create a Camera
with both intrinsic and extrinsic parameters.
let camera = Camera::new(intrinsics, pose);
// Project the original 3D coordinates to 2D pixel coordinates. let pixelcoords = camera.worldtopixel(&worldcoords);
// Print the results. for i in 0..worldcoords.data.nrows() { let wc = worldcoords.data.row(i); let pix = pixel_coords.data.row(i); println!("{} -> {}", wc, pix); } ```
This will print:
``` ┌ ┐ │ 1 0 0 │ └ ┘
-> ┌ ┐ │ 640 480 │ └ ┘
┌ ┐ │ 0 1 0 │ └ ┘
-> ┌ ┐ │ 650 480 │ └ ┘ ```
```rust use cam_geom::*; use nalgebra::RowVector3;
// Create the first ray.
let ray1 = Ray::
// Create the second ray.
let ray2 = Ray::
// Compute the best intersection. let result = bestintersectionof_rays(&[ray1, ray2]).unwrap();
// Print the result. println!("result: {}", result.data); ```
This will print:
result:
┌ ┐
│ 1 1 0 │
└ ┘
README.md
The README.md
file can be regenerated with:
text
cargo readme > README.md
Anyone who interacts with this software in any space, including but not limited to this GitHub repository, must follow our code of conduct.
Licensed under either of these: