Skip to content

Commit

Permalink
WIP Triangulate
Browse files Browse the repository at this point in the history
  • Loading branch information
zygmuntszpak committed Jul 10, 2018
1 parent d3d6e92 commit c470e8a
Show file tree
Hide file tree
Showing 25 changed files with 647 additions and 23 deletions.
Binary file added data/teapot.mat
Binary file not shown.
4 changes: 3 additions & 1 deletion demo/example_fundamental_matrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ inlier_pts1 = read(file,"inlierPts1")
inlier_pts2 = read(file,"inlierPts2")
close(file)

# Conver the images to Grayscale.
# Conver the images to Grayscale.
img1g = Gray.(img1)
img2g = Gray.(img2)

Expand Down Expand Up @@ -63,3 +63,5 @@ Plots.plot!([eΚΉ[1]],[eΚΉ[2]], grid = false, box = :none, legend = false,
# Display both views simultaneously.
p3 = Plots.plot(p1,p2,layout=(1,2), legend = false)
display(p3)

𝐅₀*e
111 changes: 111 additions & 0 deletions demo/example_unrectified_triangulate.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using MultipleViewGeometry, Base.Test
using MultipleViewGeometry.ModuleCostFunction
using MultipleViewGeometry.ModuleTypes
using MultipleViewGeometry.ModuleConstraints
using MultipleViewGeometry.ModuleConstruct
using MultipleViewGeometry.ModuleDraw
using MultipleViewGeometry.ModuleTriangulation
using BenchmarkTools, Compat
using StaticArrays
using MAT, Plots

# Load MATLAB matrices that represent a pair of images and that contain
# a set of manually matched corresponding points.
file = matopen("./data/teapot.mat")
X = read(file,"pts3D")
X = X[:,1:10:end]
close(file)

# Fix random seed.
srand(1234)
plotlyjs()

#𝒳 = [Point3DH(x,y,z,1.0) for x=-1:0.5:10 for y=-1:0.5:10 for z=2:-0.1:1]

𝒳 = [Point3DH(X[1,i],X[2,i],X[3,i],1.0) for i = 1:size(X,2)]

#X = reinterpret(Float64,map(SVector{4,Float64},𝒳),(4,length(𝒳)))
#Z = reinterpret(SVector{4,Float64},(3000,4))
# reinterpret(SVector{4,Float64}, X, (size(X,2),))#
# reinterpret(SVector{4,Float64}, Z, (size(Z,2),))#
# reinterpret(SVector{4,Float64}, X, (3000,1))

# Intrinsic and extrinsic parameters of camera one.
πŠβ‚ = eye(3)
𝐑₁ = eye(3)
𝐭₁ = [-250.0, 0.0, 2500.0]
πœβ‚ = [0.0, 0.0, 0.0]
𝐄₁ = [𝐑₁ 𝐭₁]

# Intrinsic and extrinsic parameters of camera two.
πŠβ‚‚ = eye(3)
𝐑₂ = eye(3)
𝐭₂ = [250.0, 0.0, 2500.0]
πœβ‚‚ = [0.0, 0.0, 0.0]
𝐄₂ = [𝐑₂ 𝐭₂]

# Camera projection matrices.
𝐏₁ = construct(ProjectionMatrix(),πŠβ‚,𝐑₁,𝐭₁)
𝐏₂ = construct(ProjectionMatrix(),πŠβ‚‚,𝐑₂,𝐭₂)

# Set of corresponding points.
β„³ = project(Pinhole(),𝐏₁,𝒳)
β„³ΚΉ = project(Pinhole(),𝐏₂,𝒳)

# Convert the array of Point3DH into a 4 x N matrix to simplify
# the plotting of the data points.
#X = reinterpret(Float64,map(SVector{4,Float64},𝒳),(4,length(𝒳)))

# Visualise the data points
p1 = Plots.plot(X[1,:],X[2,:],X[3,:],seriestype = :scatter, ms=1,grid = false, box = :none, legend = false)
draw!(WorldCoordinateSystem3D(), 450, p1)
draw!(Camera3D(), πŠβ‚, 𝐑₁, 𝐭₁, 250, p1)
draw!(Camera3D(), πŠβ‚‚, 𝐑₂, 𝐭₂, 250, p1)


# Plot the projections of the point cloud in the image pair.
p2 = Plots.plot();
for n = 1:length(β„³)
m = β„³[n]
Plots.plot!([m[1]],[m[2]], grid = false, box = :none, legend = false,
seriestype = :scatter, ms = 2, markercolor=:Black,
aspect_ratio = :equal)
end

p3 = Plots.plot();
for n = 1:length(β„³ΚΉ)
mΚΉ = β„³ΚΉ[n]
Plots.plot!([mΚΉ[1]],[mΚΉ[2]], grid = false, box = :none, legend = false,
seriestype = :scatter, ms = 2, markercolor=:Black,
aspect_ratio = :equal)
end

# Visualise the 3D point cloud, as well as the projected images.
l = @layout [ a; [b c] ]
p4 = Plots.plot(p1,p2, p3, layout = l)


# 𝒴 = triangulate(DirectLinearTransform(),𝐏₁,𝐏₂,(β„³,β„³ΚΉ))
#
# Y = reinterpret(Float64,map(SVector{4,Float64},𝒴),(4,length(𝒴)))
# # Visualise the data points
# p5 = Plots.plot(Y[1,:],Y[2,:],Y[3,:],seriestype = :scatter, ms=1,grid = false, box = :none, legend = false)
# draw!(WorldCoordinateSystem3D(), 450, p1)
# draw!(Camera3D(), πŠβ‚, 𝐑₁, 𝐭₁, 250, p1)
# draw!(Camera3D(), πŠβ‚‚, 𝐑₂, 𝐭₂, 250, p1)

# Estimate of the fundamental matrix and the true fundamental matrix.
𝐅 = estimate(FundamentalMatrix(), DirectLinearTransform(), (β„³, β„³ΚΉ))
𝐄 = construct(EssentialMatrix(), 𝐅, πŠβ‚, πŠβ‚‚)

𝐏₁, 𝐏₂ = construct(ProjectionMatrix(), 𝐄, (β„³, β„³ΚΉ))

𝒴 = triangulate(DirectLinearTransform(),𝐏₁,𝐏₂,(β„³,β„³ΚΉ))
Y = reinterpret(Float64,map(SVector{4,Float64},𝒴),(4,length(𝒴)))
# Visualise the data points
p5 = Plots.plot(Y[1,:],Y[2,:],Y[3,:],seriestype = :scatter, ms=1,grid = false, box = :none, legend = false)
draw!(WorldCoordinateSystem3D(), 450/1000, p1)
# draw!(Camera3D(), πŠβ‚, 𝐏₁[1:3,1:3], 𝐏₁[:,4], 250/1000, p1)
# draw!(Camera3D(), πŠβ‚‚, 𝐏₂[1:3,1:3], 𝐏₂[:,4], 250/1000, p1)
# draw!(Camera3D(), πŠβ‚, 𝐑₁, 𝐭₁, 250, p1)
# draw!(Camera3D(), πŠβ‚‚, 𝐑₂, 𝐭₂, 250, p1)
24 changes: 22 additions & 2 deletions src/MultipleViewGeometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using StaticArrays

# Types exported from `types.jl`
export HomogeneousPoint, ProjectiveEntity, FundamentalMatrix, ProjectionMatrix
export EssentialMatrix
export CameraModel, Pinhole, CanonicalLens
export EstimationAlgorithm, DirectLinearTransform, Taubin, FundamentalNumericalScheme
export CostFunction, ApproximateMaximumLikelihood, AML
Expand All @@ -16,6 +17,7 @@ export CoordinateSystemTransformation, CanonicalToHartley, HartleyToCanonical
export CovarianceMatrices
export Point2DH, Point3DH
export HessianApproximation, CanonicalApproximation, CovarianceEstimationScheme
export NoiseModel, GaussianNoise

# Aliases exported from math_aliases.jl
export βŠ—, βˆ‘, √
Expand All @@ -35,6 +37,9 @@ export moments
# Functions exported from `estimate_twoview.jl`
export estimate

# Functions exported from `construct_essentialmatrix.jl`
export construct

# Functions exported from `construct_fundamentalmatrix.jl`
export construct

Expand All @@ -51,7 +56,17 @@ export rotx, roty, rotz, rotxyz, rodrigues2matrix
export cost, X, covariance_matrix, covariance_matrix_debug

# Functions exported from `draw.jl`
export draw!, EpipolarLineGraphic
export draw!, EpipolarLineGraphic, LineSegment3D, PlaneSegment3D, Camera3D
export WorldCoordinateSystem3D

# Functions exported from `constraints.jl`
export satisfy, EpipolarConstraint, Constraint

# Functions exported from `triangulation.jl`
export triangulate

# Functions exported from `noise.jl`
export perturb

include("math_aliases/ModuleMathAliases.jl")
include("types/ModuleTypes.jl")
Expand All @@ -66,7 +81,9 @@ include("cost_function/ModuleCostFunction.jl")
include("estimate/ModuleEstimation.jl")
include("construct/ModuleConstruct.jl")
include("draw/ModuleDraw.jl")

include("constraints/ModuleConstraints.jl")
include("triangulation/ModuleTriangulation.jl")
include("noise/ModuleNoise.jl")

using .ModuleMathAliases
using .ModuleTypes
Expand All @@ -81,6 +98,9 @@ using .ModuleMoments
using .ModuleCostFunction
using .ModuleConstruct
using .ModuleDraw
using .ModuleConstraints
using .ModuleTriangulation
using .ModuleNoise


# package code goes here
Expand Down
4 changes: 0 additions & 4 deletions src/carriers/carriers.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Carrier vector for fundamental matrix estimation.
@inline function βˆ‚β‚“u(entity::FundamentalMatrix, π’Ÿ)
m, mΚΉ = collect(π’Ÿ)
# 𝐦 = 𝑛(collect(Float64,m.coords))
# 𝐦ʹ = 𝑛(collect(Float64,mΚΉ.coords))
𝐦 = 𝑛(m)
𝐦ʹ = 𝑛(mΚΉ)
βˆ‚β‚“u(entity, 𝐦 , 𝐦ʹ)
Expand All @@ -17,8 +15,6 @@ end

@inline function uβ‚“(entity::FundamentalMatrix, π’Ÿ)
m, mΚΉ = collect(π’Ÿ)
# 𝐦 = 𝑛(collect(Float64,m.coords))
# 𝐦ʹ = 𝑛(collect(Float64,mΚΉ.coords))
𝐦 = 𝑛(m)
𝐦ʹ = 𝑛(mΚΉ)
uβ‚“(entity, 𝐦 , 𝐦ʹ)
Expand Down
7 changes: 7 additions & 0 deletions src/constraints/ModuleConstraints.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ModuleConstraints
using MultipleViewGeometry.ModuleTypes, MultipleViewGeometry.ModuleMathAliases, MultipleViewGeometry.ModuleOperators
using StaticArrays
export satisfy, EpipolarConstraint, Constraint

include("constraints.jl")
end
47 changes: 47 additions & 0 deletions src/constraints/constraints.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
abstract type Constraint end

type EpipolarConstraint <: Constraint
end

# Triangulation from Two Views Revisited: Hartley-Sturm vs. Optimal Correction
function satisfy(entity::FundamentalMatrix, constraint::EpipolarConstraint, 𝐅::AbstractArray, π’Ÿ::Tuple{AbstractArray, Vararg{AbstractArray}})
β„³, β„³ΚΉ = π’Ÿ
π’ͺ = similar(β„³)
π’ͺΚΉ = similar(β„³ΚΉ)

N = length(β„³)
𝐏₂ = SMatrix{3,3,Float64,3^2}([1 0 0; 0 1 0; 0 0 0])

I = 10
for n = 1:N
𝐦 = β„³[n]
𝐦ʹ = β„³ΚΉ[n]
𝐦ₕ = init_correction_view_1(𝐅, 𝐦, 𝐦ʹ, 𝐏₂)
𝐦ₕʹ= init_correction_view_2(𝐅, 𝐦, 𝐦ʹ, 𝐏₂)
for i = 1:I
π¦β‚œ = 𝐦 - 𝐦ₕ
π¦β‚œΚΉ = 𝐦ʹ - 𝐦ₕʹ
𝐦ₕ = update_correction_view_1(𝐅, 𝐦, 𝐦ₕ, π¦β‚œ, 𝐦ʹ, 𝐦ₕʹ, π¦β‚œΚΉ, 𝐏₂)
𝐦ₕʹ = update_correction_view_2(𝐅, 𝐦, 𝐦ₕ, π¦β‚œ, 𝐦ʹ, 𝐦ₕʹ, π¦β‚œΚΉ, 𝐏₂)
end
π’ͺ[n] = 𝐦ₕ
π’ͺΚΉ[n] = 𝐦ₕʹ
end
π’ͺ ,π’ͺΚΉ
end

function init_correction_view_1(𝐅::AbstractArray, 𝐦::AbstractVector, 𝐦ʹ::AbstractVector, 𝐏₂::AbstractArray)
𝐦 - dot(𝐦,𝐅*𝐦ʹ)*𝐏₂*𝐅*𝐦ʹ / ( dot(𝐅*𝐦ʹ,𝐏₂*𝐅*𝐦ʹ) + dot(𝐅'*𝐦, 𝐏₂*𝐅'*𝐦) )
end

function init_correction_view_2(𝐅::AbstractArray, 𝐦::AbstractVector, 𝐦ʹ::AbstractVector, 𝐏₂::AbstractArray)
𝐦ʹ - dot(𝐦,𝐅*𝐦ʹ)*𝐏₂*𝐅'*𝐦 / ( dot(𝐅*𝐦ʹ,𝐏₂*𝐅*𝐦ʹ) + dot(𝐅'*𝐦, 𝐏₂*𝐅'*𝐦) )
end

function update_correction_view_1(𝐅::AbstractArray, 𝐦::AbstractVector, 𝐦ₕ::AbstractVector, π¦β‚œ::AbstractVector, 𝐦ʹ::AbstractVector, 𝐦ₕʹ::AbstractVector, π¦β‚œΚΉ::AbstractVector, 𝐏₂::AbstractArray)
𝐦 - ( ( dot(𝐦ₕ,𝐅*𝐦ₕʹ) + dot(𝐅*𝐦ₕʹ, π¦β‚œ) + dot(𝐅'*𝐦ₕ, π¦β‚œΚΉ) ) * 𝐏₂*𝐅*𝐦ₕʹ) / (dot(𝐅*𝐦ₕʹ, 𝐏₂*𝐅*𝐦ₕʹ) + dot(𝐅'*𝐦ₕ, 𝐏₂*𝐅'*𝐦ₕ) )
end

function update_correction_view_2(𝐅::AbstractArray, 𝐦::AbstractVector, 𝐦ₕ::AbstractVector, π¦β‚œ::AbstractVector, 𝐦ʹ::AbstractVector, 𝐦ₕʹ::AbstractVector, π¦β‚œΚΉ::AbstractVector, 𝐏₂::AbstractArray)
𝐦ʹ - ( ( dot(𝐦ₕ,𝐅*𝐦ₕʹ) + dot(𝐅*𝐦ₕʹ, π¦β‚œ) + dot(𝐅'*𝐦ₕ, π¦β‚œΚΉ) ) * 𝐏₂*𝐅'*𝐦ₕ) / (dot(𝐅*𝐦ₕʹ, 𝐏₂*𝐅*𝐦ₕʹ) + dot(𝐅'*𝐦ₕ, 𝐏₂*𝐅'*𝐦ₕ) )
end
2 changes: 2 additions & 0 deletions src/construct/ModuleConstruct.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
module ModuleConstruct
using MultipleViewGeometry
using MultipleViewGeometry.ModuleTypes, MultipleViewGeometry.ModuleMathAliases, MultipleViewGeometry.ModuleOperators
using MultipleViewGeometry.ModuleProjection
using StaticArrays
export construct

include("construct_projectionmatrix.jl")
include("construct_fundamentalmatrix.jl")
include("construct_essentialmatrix.jl")
end
11 changes: 11 additions & 0 deletions src/construct/construct_essentialmatrix.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function construct( e::EssentialMatrix, 𝐅::AbstractArray, πŠβ‚::AbstractArray, πŠβ‚‚::AbstractArray)
if (size(πŠβ‚) != (3,3)) || (size(πŠβ‚‚) != (3,3))
throw(ArgumentError("Expect 3 x 3 calibration matrices."))
end
if (size(𝐅) != (3,3))
throw(ArgumentError("Expect 3 x 3 fundamental matrix."))
end
# Equation 9.12 Chapter 9 from Hartley & Zisserman
𝐄 = πŠβ‚‚'*𝐅*πŠβ‚
MMatrix{3,3,Float64,3*3}(𝐄)
end
51 changes: 51 additions & 0 deletions src/construct/construct_projectionmatrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,54 @@ function construct( e::ProjectionMatrix, 𝐅::AbstractArray)
SMatrix{3,4,Float64,3*4}(𝐏₁), SMatrix{3,4,Float64,3*4}(𝐏₂)

end

function construct( e::ProjectionMatrix, 𝐄::AbstractArray, π’Ÿ::Tuple{AbstractArray, Vararg{AbstractArray}})
𝐖 = SMatrix{3,3,Float64,3*3}([0 -1 0; 1 0 0; 0 0 1])
𝐙 = SMatrix{3,3,Float64,3*3}([0 1 0; -1 0 0; 0 0 0])
𝐔,𝐒,𝐕 = svd(𝐄)
𝐭 = 𝐔[:,3]
𝐏₁ = SMatrix{3,4,Float64,3*4}(eye(3,4))
𝐏₂₁ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖*𝐕' 𝐭])
𝐏₂₂ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖'*𝐕' 𝐭])
𝐏₂₃ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖*𝐕' -𝐭])
𝐏₂₄ = SMatrix{3,4,Float64,3*4}([𝐔*𝐖'*𝐕' -𝐭])

𝒳₁ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₁, π’Ÿ)
𝒳₂ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₂, π’Ÿ)
𝒳₃ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₃, π’Ÿ)
𝒳₄ = triangulate(DirectLinearTransform(), 𝐏₁, 𝐏₂₄, π’Ÿ)

# Determine which projection matrix in the second view triangulated
# the majority of points in front of the cameras.
ℳ₁ = map(𝒳₁) do 𝐗
𝐦 = 𝐏₂₁ * 𝐗
𝐦[3] > 0
end

β„³β‚‚ = map(𝒳₂) do 𝐗
𝐦 = 𝐏₂₂ * 𝐗
𝐦[3] > 0
end

ℳ₃ = map(𝒳₃) do 𝐗
𝐦 = 𝐏₂₃ * 𝐗
𝐦[3] > 0
end

β„³β‚„ = map(𝒳₄) do 𝐗
𝐦 = 𝐏₂₄ * 𝐗
𝐦[3] > 0
end

total, index = findmax((sum(ℳ₁), sum(β„³β‚‚), sum(ℳ₃), sum(β„³β‚„)))

if index == 1
return 𝐏₁, 𝐏₂₁
elseif index == 2
return 𝐏₁, 𝐏₂₂
elseif index == 3
return 𝐏₁, 𝐏₂₃
else
return 𝐏₁, 𝐏₂₄
end
end
18 changes: 9 additions & 9 deletions src/cost_function/cost_functions.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@


function cost(c::CostFunction, entity::FundamentalMatrix, 𝛉::AbstractArray, π’ž::Tuple{AbstractArray, Vararg{AbstractArray}}, π’Ÿ::Tuple{AbstractArray, Vararg{AbstractArray}})
β„³, β„³ΚΉ = collect(π’Ÿ)
Λ₁, Ξ›β‚‚ = collect(π’ž)
β„³, β„³ΚΉ = π’Ÿ
Λ₁, Ξ›β‚‚ = π’ž
Jβ‚β‚˜β‚— = 0.0
N = length(π’Ÿ[1])
πš²β‚™ = @MMatrix zeros(4,4)
Expand Down Expand Up @@ -130,7 +130,7 @@ function covariance_matrix(c::CostFunction, s::CanonicalApproximation, entity::F
𝚲 = _covariance_matrix(AML(),FundamentalMatrix(), 𝛉₁, (Λ₁,Λ₁ʹ), (π’ͺ , π’ͺΚΉ))

𝛉₁ = 𝛉₁ / norm(𝛉₁)

# Derivative of the determinant of 𝚯 = reshape(𝛉₁,(3,3)).
φ₁ = 𝛉₁[5]*𝛉₁[9] - 𝛉₁[8]*𝛉₁[6]
Ο†β‚‚ = -(𝛉₁[4]*𝛉₁[5] - 𝛉₁[7]*𝛉₁[6])
Expand Down Expand Up @@ -158,8 +158,8 @@ end

function _covariance_matrix(c::CostFunction, entity::FundamentalMatrix, 𝛉::AbstractArray, π’ž::Tuple{AbstractArray, Vararg{AbstractArray}}, π’Ÿ::Tuple{AbstractArray, Vararg{AbstractArray}})
𝛉 = 𝛉 / norm(𝛉)
β„³, β„³ΚΉ = collect(π’Ÿ)
Λ₁, Ξ›β‚‚ = collect(π’ž)
β„³, β„³ΚΉ = π’Ÿ
Λ₁, Ξ›β‚‚ = π’ž
N = length(π’Ÿ[1])
πš²β‚™ = @MMatrix zeros(4,4)
πžβ‚ = @SMatrix [1.0; 0.0; 0.0]
Expand Down Expand Up @@ -233,8 +233,8 @@ function _X(c::CostFunction, entity::ProjectiveEntity, 𝛉::AbstractArray,π’ž:
𝐍 = fill(0.0,(l,l))
𝐌 = fill(0.0,(l,l))
N = length(π’Ÿ[1])
β„³, β„³ΚΉ = collect(π’Ÿ)
Λ₁, Ξ›β‚‚ = collect(π’ž)
β„³, β„³ΚΉ = π’Ÿ
Λ₁, Ξ›β‚‚ = π’ž
πš²β‚™ = @MMatrix zeros(4,4)
πžβ‚ = @SMatrix [1.0; 0.0; 0.0]
πžβ‚‚ = @SMatrix [0.0; 1.0; 0.0]
Expand Down Expand Up @@ -291,8 +291,8 @@ function T(c::CostFunction, entity::ProjectiveEntity, 𝛉::AbstractArray, π’ž:
𝐌 = fill(0.0,(l,l))
𝐓 = fill(0.0,(l,l))
N = length(π’Ÿ[1])
β„³, β„³ΚΉ = collect(π’Ÿ)
Λ₁, Ξ›β‚‚ = collect(π’ž)
β„³, β„³ΚΉ = π’Ÿ
Λ₁, Ξ›β‚‚ = π’ž
πš²β‚™ = @MMatrix zeros(4,4)
πžβ‚ = @SMatrix [1.0; 0.0; 0.0]
πžβ‚‚ = @SMatrix [0.0; 1.0; 0.0]
Expand Down
Loading

0 comments on commit c470e8a

Please sign in to comment.