-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds two-view unrectified triangulation capability
Adds two-view triangulation capability. Triangulation is based on direct linear transform (an algebraic method). One can triangulate by giving a pair of projection (camera) matrices. Alternatively, one can supply the fundamental matrix which will result in a projective reconstruction. If calibration matrices are known, then one can triangulate using the Essential Matrix. This will result in a Euclidean reconstruction up to an unknown scale factor. I've implemented Kanatani's optimal correction so that a set of noisy corresponding points satisfy the epipolar constraint. However, the triangulation method currently does not use this correction.
- Loading branch information
Showing
11 changed files
with
222 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
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 is a 4 x N matrix, where N is the number of points expressed in homogeneous | ||
# coordinates. | ||
X = X[:,1:10:end] | ||
close(file) | ||
|
||
# Fix random seed. | ||
srand(1234) | ||
plotlyjs() | ||
|
||
# Transform the point cloud so that it will be oriented upright and | ||
# in front of two cameras which we will define next. | ||
T1 = eye(4) | ||
T1[:,4] = -mean(X,2) | ||
T2 = [1 0 0 0; | ||
0 1 0 0; | ||
0 0 1 -2500; | ||
0 0 0 1] | ||
R = eye(4) | ||
R[1:3,1:3] = rotx(deg2rad(90)) | ||
X = T2*R*T1*X; | ||
|
||
# Convert the 4 x N matrix into a list of 3D points expressed in homogeneous coordinates. | ||
π³ = [Point3DH(X[1,i],X[2,i],X[3,i],1.0) for i = 1:size(X,2)] | ||
|
||
# Intrinsic and extrinsic parameters of camera one. | ||
πβ = eye(3) | ||
πβ = eye(3) | ||
πβ = [0.0, 0.0, 0.0] | ||
πβ = [0.0, 0.0, 0.0] | ||
πβ = [πβ πβ] | ||
|
||
# Intrinsic and extrinsic parameters of camera two. | ||
πβ = eye(3) | ||
πβ = eye(3) | ||
πβ = [450.0, 0.0, 0.0] | ||
πβ = [0.0, 0.0, 0.0] | ||
πβ = [πβ πβ] | ||
|
||
# Camera projection matrices. | ||
πβ = construct(ProjectionMatrix(),πβ,πβ,πβ) | ||
πβ = construct(ProjectionMatrix(),πβ,πβ,πβ) | ||
|
||
# Set of corresponding points. | ||
β³ = project(Pinhole(),πβ,π³) | ||
β³ΚΉ = project(Pinhole(),πβ,π³) | ||
|
||
# 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(), 1, p1) | ||
draw!(Camera3D(), πβ, πβ, πβ, 1, p1) | ||
draw!(Camera3D(), πβ, πβ, πβ, 1, 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, yflip = true) | ||
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, yflip = true) | ||
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) | ||
|
||
# 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(π΄))) | ||
|
||
# The point cloud can be reconsructed only up to an unknown scale factor. | ||
p5 = Plots.plot(Y[1,:],Y[2,:],Y[3,:],seriestype = :scatter, ms=1,grid = false, box = :none, legend = false) | ||
draw!(WorldCoordinateSystem3D(), 0.002, p5) | ||
draw!(Camera3D(), πβ, πβ[1:3,1:3], πβ[:,4], 0.002, p5) | ||
draw!(Camera3D(), πβ, πβ[1:3,1:3], πβ[:,4], 0.002, p5) | ||
|
||
display(p4) | ||
#display(p5) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using MultipleViewGeometry, MultipleViewGeometry.ModuleRotation, Base.Test | ||
|
||
# Intrinsic and extrinsic parameters for the first camera. | ||
πβ = zeros(3,3) | ||
πβ[1,1] = 10 | ||
πβ[2,2] = 10 | ||
πβ[3,3] = 1 | ||
πβ = rotxyz(deg2rad(10), deg2rad(15), deg2rad(45)) | ||
πβ = [-250.0, 0.0, 2500.0] | ||
|
||
# Intrinsic and extrinsic parameters for the second camera. | ||
πβ = zeros(3,3) | ||
πβ[1,1] = 5 | ||
πβ[2,2] = 5 | ||
πβ[3,3] = 1 | ||
πβ = rotxyz(deg2rad(10), deg2rad(15), deg2rad(45)) | ||
πβ = [250.0, 0.0, 2500.0] | ||
|
||
π = construct(FundamentalMatrix(),πβ,πβ,πβ,πβ,πβ,πβ) | ||
π = construct(EssentialMatrix(),π , πβ, πβ) | ||
|
||
# Result 9.17 of R. Hartley and A. Zisserman, βTwo-View Geometry,β Multiple View Geometry in Computer Vision | ||
# A 3 by 3 matrix is an essential matrix if and only if two of its singular values | ||
# are equal, and the third is zero. | ||
U, S , V = svd(π) | ||
|
||
@test isapprox.(S[1], S[2]; atol = 1e-14) | ||
@test isapprox.(S[3], 0.0; atol = 1e-10) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters