Skip to content

Commit 3e7ffbf

Browse files
authored
Merge pull request #17 from JuliaRobotics/23Q1/enh/cleanup
refactor, consolidate types
2 parents 9000a0b + 6c3b94f commit 3e7ffbf

File tree

11 files changed

+101
-85
lines changed

11 files changed

+101
-85
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Remove method redefinition warnings by dropping additional types and keeping just construction helpers. Only types are `CameraCalibration[Mutable]`.
66
- Consolidate type `CameraIntrinsic`
7+
78
## v0.1
89

910
- Created consolidated `CameraCalibration` type to replace various previous camera models (all doing about the same thing),

src/CameraModels.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ using Manifolds
55
using DocStringExtensions
66
using StaticArrays
77
import Rotations as Rot_
8-
8+
import Base: getindex, getproperty
99

1010

1111
# exports

src/Deprecated.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@
55
## ================================================================================================
66
## consolidated types below
77

8+
@deprecate CameraExtrinsic(R::AbstractMatrix=[1 0 0; 0 1 0; 0 0 1.], t::AbstractVector=[0,0,0.]) ArrayPartition(SVector(t...),SMatrix(R))
89

10+
# Camera extrinsic must be world in camera frame (cRw)
11+
# Base.@kwdef struct CameraExtrinsic{T <: Real}
12+
# R::SMatrix{3,3,T,9} = one(Rot_.RotMatrix{3, Float64}).mat
13+
# t::SVector{3,T} = SVector(0,0,0.)
14+
# end
15+
16+
17+
@deprecate PixelCoordinate(row,col) PixelIndex(row,col)
918

1019
# CameraCalibration(
1120
# height::Int= 480,
@@ -79,7 +88,7 @@ CameraModel = (@warn("CameraModels.CameraModel is deprecated, use CameraModels.A
7988

8089

8190
export CameraModelandParameters
82-
const CameraModelandParameters = (@warn("CameraModels.CameraModelandParameters is deprecated, use CamereModels.CameraCalibration instead.");CameraCalibration)
91+
# const CameraModelandParameters = (@warn("CameraModels.CameraModelandParameters is deprecated, use CamereModels.CameraCalibration instead.");CameraCalibration)
8392

8493
function CameraModelandParameters(
8594
width::Int,
@@ -189,7 +198,7 @@ export Pinhole
189198

190199

191200
## From yakir12/CameraModels.jl
192-
const Pinhole = (@warn("CameraModels.Pinhole is deprecated, use CamereModels.CameraCalibration instead."); CameraCalibration)
201+
# const Pinhole = (@warn("CameraModels.Pinhole is deprecated, use CamereModels.CameraCalibration instead."); CameraCalibration)
193202
function Pinhole(columns::Int,rows::Int,prinicipalpoint,focallength::Vector2 )
194203
@warn "CameraModels.Pinhole is deprecated, use CamereModels.CameraCalibration instead."
195204
f_w,f_h = focallength[1], focallength[2]
@@ -225,7 +234,7 @@ export CameraIntrinsic
225234

226235

227236
function Base.getproperty(
228-
x::Union{<:Pinhole, CameraModelandParameters},
237+
x::CameraCalibration, # Union{<:Pinhole, CameraModelandParameters},
229238
f::Symbol,
230239
)
231240
if f == :skew

src/ExportAPI.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ export CameraCalibrationT, CameraCalibration, CameraCalibrationMutable
77

88
export CameraSkewDistortion
99

10-
export RadialDistortion
11-
12-
export Ray, PixelCoordinate
10+
export Ray, PixelIndex
1311
export pixel2ray, point2pixel, canreproject, sensorsize #, origin, direction,
1412

1513
export lookdirection, updirection #, columns, rows

src/entities/CameraCalibration.jl

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,9 @@ CameraCalibrationT = Union{<:CameraCalibration, <:CameraCalibrationMutable}
8080
## ===========================================================================
8181

8282

83-
# Camera extrinsic must be world in camera frame (cRw)
84-
Base.@kwdef struct CameraExtrinsic{T <: Real}
85-
R::SMatrix{3,3,T,9} = one(Rot_.RotMatrix{3, Float64}).mat
86-
t::SVector{3,T} = SVector(0,0,0.)
87-
end
88-
8983
Base.@kwdef struct CameraModelFull
9084
ci::CameraCalibration = CameraCalibration()
91-
ce::CameraExtrinsic = CameraExtrinsic()
85+
ce::ArrayPartition = CameraExtrinsic()
9286
end
9387

9488

src/entities/GeneralTypes.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11

22

3-
const PixelCoordinate = SVector{2, Float64}
4-
const Vector2 = SVector{2, Float64}
3+
struct PixelIndex{T <: Real}
4+
row::T
5+
col::T
6+
end
7+
8+
function Base.getindex(p::PixelIndex,i::Int)
9+
if i === 1
10+
p.row
11+
elseif i === 2
12+
p.col
13+
else
14+
DomainError("Camera only has rows and columns, cannot index to $i")
15+
end
16+
end
517

18+
const Vector2 = SVector{2, Float64}
619
const Point3 = SVector{3, Float64}
720
const Vector3 = SVector{3, Float64}
821

src/services/CameraCalibration.jl

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,67 +22,3 @@ function CameraCalibrationMutable(img::AbstractMatrix{T}) where T
2222
CameraCalibrationMutable(;width, height, K)
2323
end
2424

25-
26-
27-
"""
28-
$SIGNATURES
29-
30-
Slightly general Radial Distortion type, currently limited to StaticArrays.jl on CPU, but can later be extended to utilize GPUs -- see notes.
31-
32-
Notes
33-
- Make sure `dest` image is large enough to encapsulate the resulting image after un-distortion
34-
35-
Example
36-
```julia
37-
using Images, FileIO, CameraModels
38-
39-
# load the image
40-
img = load("myimg.jpg")
41-
42-
# genereate a radial distortion object
43-
radialdistortion = RadialDistortion()
44-
```
45-
46-
Reference:
47-
From Wikipedia: https://en.wikipedia.org/wiki/Distortion_(optics)
48-
( xd , yd ) = distorted image point as projected on image plane using specified lens,
49-
( xu , yu ) = undistorted image point as projected by an ideal pinhole camera,
50-
( xc , yc ) = distortion center,
51-
r = sqrt( (xd - xc)^2 + (yd - yc)^2 )
52-
53-
```math
54-
xu = xc + (xd + xc) / (1 + K1*(r^2) + K2*(r^4) + ...)
55-
yu = yc + (yd + yc) / (1 + K1*(r^2) + K2*(r^4) + ...)
56-
```
57-
58-
DevNotes (Contributions welcome):
59-
- TODO manage image clamping if `dest` is too small and data should be cropped out.
60-
- TODO buffer radii matrix for better reuse on repeat image size sequences
61-
- TODO dispatch with either CUDA.jl or AMDGPU.jl <:AbstractArray objects.
62-
- TODO use Tullio.jl with multithreading and GPU
63-
- TODO check if LoopVectorization.jl tools like `@avx` help performance
64-
"""
65-
function radialDistortion!(
66-
cc::CameraCalibration{<:Real,N},
67-
dest::AbstractMatrix,
68-
src::AbstractMatrix
69-
) where N
70-
# loop over entire image
71-
for h_d in size(src,1), w_d in size(src,2)
72-
# temporary coordinates
73-
@inbounds h_ = h_d - cc.center[1]
74-
@inbounds w_ = w_d - cc.center[2]
75-
# calculate the radius from distortion center
76-
_radius2 = h_^2 + w_^2
77-
# calculate the denominator
78-
_denomin = 1
79-
@inbounds @fastmath for k in 1:N
80-
_denomin += cc.kc[k]*(_radius2^k)
81-
end
82-
# calculate the new 'undistorted' coordinates and set equal to incoming image
83-
@inbounds @fastmath h_u = cc.center[1] + h_/_denomin
84-
@inbounds @fastmath w_u = cc.center[2] + h_/_denomin
85-
dest[h_u,w_u] = src[h_d,w_d]
86-
end
87-
nothing
88-
end

src/services/CameraServices.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ Also see: [`project`](@ref)
9696
"""
9797
function backproject(
9898
model::CameraCalibrationT,
99-
px_coord::Union{<:AbstractVector{<:Real}, <:PixelCoordinate}
99+
px_coord::Union{<:AbstractVector{<:Real}, <:PixelIndex}
100100
)
101101
#
102102
x = (px_coord[1] - c_w(model)) / f_w(model)
@@ -124,7 +124,7 @@ end
124124
function project!(
125125
ret::AbstractVector{<:Real},
126126
ci::CameraCalibration, #CameraIntrinsic,
127-
ce::CameraExtrinsic,
127+
ce::ArrayPartition,
128128
pt::Vector{Float64}
129129
)
130130
res = ci.K*(ce.R*pt + ce.t)
@@ -152,7 +152,7 @@ function cameraResidual!(
152152
res::AbstractVector{<:Real},
153153
z::AbstractVector{<:Real},
154154
ci::CameraCalibration, #CameraIntrinsic,
155-
ce::CameraExtrinsic,
155+
ce::ArrayPartition,
156156
pt::AbstractVector{<:Real}
157157
)
158158
# in place memory operations

src/services/Utils.jl

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,69 @@ function CameraSkewDistortion(width,height,fc,cc,skew,kc)
1616
CameraModelandParameters(width,height,fc,cc,skew,kc,KK,Ki)
1717
end
1818

19+
"""
20+
$SIGNATURES
21+
22+
Slightly general Radial Distortion type, currently limited to StaticArrays.jl on CPU, but can later be extended to utilize GPUs -- see notes.
23+
24+
Notes
25+
- Make sure `dest` image is large enough to encapsulate the resulting image after un-distortion
26+
27+
Example
28+
```julia
29+
using Images, FileIO, CameraModels
30+
31+
# load the image
32+
img = load("myimg.jpg")
33+
34+
# TODO, store radialDistortion in CameraCalibration
35+
```
36+
37+
Reference:
38+
From Wikipedia: https://en.wikipedia.org/wiki/Distortion_(optics)
39+
( xd , yd ) = distorted image point as projected on image plane using specified lens,
40+
( xu , yu ) = undistorted image point as projected by an ideal pinhole camera,
41+
( xc , yc ) = distortion center,
42+
r = sqrt( (xd - xc)^2 + (yd - yc)^2 )
43+
44+
```math
45+
xu = xc + (xd + xc) / (1 + K1*(r^2) + K2*(r^4) + ...)
46+
yu = yc + (yd + yc) / (1 + K1*(r^2) + K2*(r^4) + ...)
47+
```
48+
49+
DevNotes (Contributions welcome):
50+
- TODO manage image clamping if `dest` is too small and data should be cropped out.
51+
- TODO buffer radii matrix for better reuse on repeat image size sequences
52+
- TODO dispatch with either CUDA.jl or AMDGPU.jl <:AbstractArray objects.
53+
- TODO use Tullio.jl with multithreading and GPU
54+
- TODO check if LoopVectorization.jl tools like `@avx` help performance
55+
"""
56+
function radialDistortion!(
57+
cc::CameraCalibration{<:Real,N},
58+
dest::AbstractMatrix,
59+
src::AbstractMatrix
60+
) where N
61+
# loop over entire image
62+
for h_d in size(src,1), w_d in size(src,2)
63+
# temporary coordinates
64+
@inbounds h_ = h_d - cc.center[1]
65+
@inbounds w_ = w_d - cc.center[2]
66+
# calculate the radius from distortion center
67+
_radius2 = h_^2 + w_^2
68+
# calculate the denominator
69+
_denomin = 1
70+
@inbounds @fastmath for k in 1:N
71+
_denomin += cc.kc[k]*(_radius2^k)
72+
end
73+
# calculate the new 'undistorted' coordinates and set equal to incoming image
74+
@inbounds @fastmath h_u = cc.center[1] + h_/_denomin
75+
@inbounds @fastmath w_u = cc.center[2] + h_/_denomin
76+
dest[h_u,w_u] = src[h_d,w_d]
77+
end
78+
nothing
79+
end
80+
81+
1982

2083

2184
function intersectLineToPlane3D(

test/CameraTestBench.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ function run_test_bench(model::C, pixel_accuracy::Float64 = 1e-5, ray_accuracy::
3131
# Some models might not implement point2pixel.
3232
if canreproject(model)
3333
reprojection = point2pixel(model, point)
34-
@test some_pixel_location reprojection atol = pixel_accuracy
34+
@test some_pixel_location[1] reprojection[1] atol = pixel_accuracy
35+
@test some_pixel_location[2] reprojection[2] atol = pixel_accuracy
3536
else
3637
@info "point2pixel not implemented for $(C)."
3738
end

0 commit comments

Comments
 (0)