Skip to content

Commit d0d2fb9

Browse files
Andy FerrisChris Foster
authored andcommitted
Simplified cameramap()
1 parent 302774c commit d0d2fb9

File tree

2 files changed

+29
-52
lines changed

2 files changed

+29
-52
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,7 @@ image, you might use the following code:
190190
cam_transform = PerspectiveMap() inv(AffineMap(cam_rotation, cam_position))
191191
screen_points = map(cam_transform, points)
192192
```
193+
194+
There is also a `cameramap()` convenience function that can create a composed
195+
transformation that includes the intrinsic scaling (e.g. focal length and pixel
196+
size) and offset (defining which pixel is labeled `(0,0)`) of an imaging system.

src/perspective.jl

Lines changed: 25 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -30,66 +30,39 @@ end
3030
return pop(v) * inv(v[end])
3131
end
3232

33-
Base.@pure Base.isapprox(::PerspectiveMap, ::PerspectiveMap; kwargs...) = true
33+
Base.isapprox(::PerspectiveMap, ::PerspectiveMap; kwargs...) = true
3434

3535
"""
36-
cameramap(property = value, ...)
36+
cameramap()
37+
cameramap(scale)
38+
cameramap(scale, offset)
3739
3840
Create a transformation that takes points in real space (e.g. 3D) and projects
3941
them through a perspective transformation onto the focal plane of an ideal
4042
(pinhole) camera with the given properties.
4143
42-
All properties are optional. Valid properties include:
44+
The `scale` sets the scale of the screen. For a standard digital camera, this
45+
would be `scale = focal_length / pixel_size`. Non-square pixels are supported
46+
by providing a pair of scales in a tuple, `scale = (scale_x, scale_y)`. Positive
47+
scales represent a camera looking in the +z axis with a virtual screen in front
48+
of the camera (the x,y coordinates are not inverted compared to 3D space). Note
49+
that points behind the camera (with negative z component) will be projected
50+
(and inverted) onto the image coordinates and it is up to the user to cull
51+
such points as necessary.
4352
44-
* `focal_length` (in physical units)
45-
* `pixel_size` (in physical units) or `pixel_size_x` and `pixel_size_y`
46-
* `offset_x` and `offset_y` (in pixels)
47-
* `origin` (a vector) and `orientation` (a rotation matrix)
48-
49-
By default, the camera looks towards the postive-`z` axis from `(0,0,0)` and
50-
the sign of the `x` and `y` components is preserved for objects in front of the
51-
camera (objects behind the camera are also projected and therefor inverted - it
52-
is up to the user to cull these as necessary).
53-
54-
If `origin` and `orientation` are specified, the camera is translated to `origin`
55-
and rotated by `orientation` before the perspective map is applied.
53+
The `offset = (offset_x, offset_y)` is used to define the origin in the imaging
54+
plane. For instance, you may wish to have the point (0,0) represent the top-left
55+
corner of your imaging sensor. This measurement is in the units after applying
56+
`scale` (e.g. pixels).
5657
5758
(see also `PerspectiveMap`)
5859
"""
59-
function cameramap(;focal_length = nothing,
60-
pixel_size = nothing,
61-
pixel_size_x = nothing,
62-
pixel_size_y = nothing,
63-
offset_x = nothing,
64-
offset_y = nothing,
65-
origin = nothing,
66-
orientation = nothing)
67-
68-
trans = PerspectiveMap()
69-
70-
if pixel_size === nothing # (this form of if-else-end is handled well by the compiler... the author is looking forward to v0.6 where !(::Bool) is pure...)
71-
else
72-
pixel_size_x = pixel_size
73-
pixel_size_y = pixel_size
74-
end
75-
76-
# Apply camera rotations, if necessary
77-
if origin === nothing && orientation === nothing
78-
else
79-
trans = trans inv(AffineMap(orientation, origin))
80-
end
81-
82-
# Apply camera scaling, if necessary
83-
if isa(focal_length, Void) && isa(pixel_size_x, Void) && isa(pixel_size_y, Void)
84-
else
85-
trans = LinearMap(UniformScaling(focal_length/pixel_size)) trans
86-
end
87-
88-
# Apply pixel offset, if necessary
89-
if isa(offset_x, Void) && isa(offset_y, Void)
90-
else
91-
trans = Translation(SVector(-offset_x, -offset_y)) trans
92-
end
93-
94-
return trans
95-
end
60+
cameramap() = PerspectiveMap()
61+
cameramap(scale::Number) =
62+
LinearMap(UniformScaling(focal_length/pixel_size)) PerspectiveMap()
63+
cameramap(scale::Tuple{Number, Number}) =
64+
LinearMap(SMatrix{2,2}(scale[1],0,0,scale[2])) PerspectiveMap()
65+
cameramap(scale::Number, offset::Tuple{Number,Number}) =
66+
AffineMap(UniformScaling(focal_length/pixel_size), SVector(-offset[1], -offset[2])) PerspectiveMap()
67+
cameramap(scale::Tuple{Number, Number}, offset::Tuple{Number,Number})) =
68+
AffineMap(SMatrix{2,2}(scale[1],0,0,scale[2]), SVector(-offset[1], -offset[2]))) PerspectiveMap()

0 commit comments

Comments
 (0)