Skip to content

Commit 91816c9

Browse files
committed
Add bundle adjustment
1 parent dff2704 commit 91816c9

7 files changed

Lines changed: 223 additions & 12 deletions

File tree

msvs/3dv_tutorial.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image_stitching", "image_st
2121
EndProject
2222
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "triangulation", "triangulation\triangulation.vcxproj", "{F3C46820-CF91-48EF-94E1-5ADB573D8D8B}"
2323
EndProject
24+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bundle_adjustment", "bundle_adjustment\bundle_adjustment.vcxproj", "{968A197A-66E1-499E-B3DE-E7760D74081B}"
25+
EndProject
2426
Global
2527
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2628
Debug|Win32 = Debug|Win32
@@ -63,6 +65,10 @@ Global
6365
{F3C46820-CF91-48EF-94E1-5ADB573D8D8B}.Debug|Win32.Build.0 = Debug|Win32
6466
{F3C46820-CF91-48EF-94E1-5ADB573D8D8B}.Release|Win32.ActiveCfg = Release|Win32
6567
{F3C46820-CF91-48EF-94E1-5ADB573D8D8B}.Release|Win32.Build.0 = Release|Win32
68+
{968A197A-66E1-499E-B3DE-E7760D74081B}.Debug|Win32.ActiveCfg = Debug|Win32
69+
{968A197A-66E1-499E-B3DE-E7760D74081B}.Debug|Win32.Build.0 = Debug|Win32
70+
{968A197A-66E1-499E-B3DE-E7760D74081B}.Release|Win32.ActiveCfg = Release|Win32
71+
{968A197A-66E1-499E-B3DE-E7760D74081B}.Release|Win32.Build.0 = Release|Win32
6672
EndGlobalSection
6773
GlobalSection(SolutionProperties) = preSolution
6874
HideSolutionNode = FALSE
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup Label="ProjectConfigurations">
4+
<ProjectConfiguration Include="Debug|Win32">
5+
<Configuration>Debug</Configuration>
6+
<Platform>Win32</Platform>
7+
</ProjectConfiguration>
8+
<ProjectConfiguration Include="Release|Win32">
9+
<Configuration>Release</Configuration>
10+
<Platform>Win32</Platform>
11+
</ProjectConfiguration>
12+
</ItemGroup>
13+
<PropertyGroup Label="Globals">
14+
<ProjectGuid>{968A197A-66E1-499E-B3DE-E7760D74081B}</ProjectGuid>
15+
<Keyword>Win32Proj</Keyword>
16+
<RootNamespace>3dv_tutorial</RootNamespace>
17+
</PropertyGroup>
18+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
19+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
20+
<ConfigurationType>Application</ConfigurationType>
21+
<UseDebugLibraries>true</UseDebugLibraries>
22+
<PlatformToolset>v120</PlatformToolset>
23+
<CharacterSet>Unicode</CharacterSet>
24+
</PropertyGroup>
25+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
26+
<ConfigurationType>Application</ConfigurationType>
27+
<UseDebugLibraries>false</UseDebugLibraries>
28+
<PlatformToolset>v120</PlatformToolset>
29+
<WholeProgramOptimization>true</WholeProgramOptimization>
30+
<CharacterSet>Unicode</CharacterSet>
31+
</PropertyGroup>
32+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
33+
<ImportGroup Label="ExtensionSettings">
34+
</ImportGroup>
35+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
36+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
37+
</ImportGroup>
38+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
39+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
40+
</ImportGroup>
41+
<PropertyGroup Label="UserMacros" />
42+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
43+
<LinkIncremental>true</LinkIncremental>
44+
<OutDir>..\..\bin</OutDir>
45+
</PropertyGroup>
46+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
47+
<LinkIncremental>false</LinkIncremental>
48+
<OutDir>..\..\bin</OutDir>
49+
</PropertyGroup>
50+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
51+
<ClCompile>
52+
<PrecompiledHeader>
53+
</PrecompiledHeader>
54+
<WarningLevel>Level3</WarningLevel>
55+
<Optimization>Disabled</Optimization>
56+
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
57+
<SDLCheck>true</SDLCheck>
58+
<AdditionalIncludeDirectories>..\..\EXTERNAL\OpenCV\include;..\..\EXTERNAL\cvsba\src</AdditionalIncludeDirectories>
59+
</ClCompile>
60+
<Link>
61+
<SubSystem>Console</SubSystem>
62+
<GenerateDebugInformation>true</GenerateDebugInformation>
63+
<AdditionalLibraryDirectories>..\..\EXTERNAL\OpenCV\lib;..\..\EXTERNAL\CLAPACK\lib</AdditionalLibraryDirectories>
64+
<AdditionalDependencies>blasd.lib;lapackd.lib;libf2cd.lib;%(AdditionalDependencies)</AdditionalDependencies>
65+
</Link>
66+
</ItemDefinitionGroup>
67+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
68+
<ClCompile>
69+
<WarningLevel>Level3</WarningLevel>
70+
<PrecompiledHeader>
71+
</PrecompiledHeader>
72+
<Optimization>MaxSpeed</Optimization>
73+
<FunctionLevelLinking>true</FunctionLevelLinking>
74+
<IntrinsicFunctions>true</IntrinsicFunctions>
75+
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
76+
<SDLCheck>true</SDLCheck>
77+
<AdditionalIncludeDirectories>..\..\EXTERNAL\OpenCV\include;..\..\EXTERNAL\cvsba\src</AdditionalIncludeDirectories>
78+
</ClCompile>
79+
<Link>
80+
<SubSystem>Console</SubSystem>
81+
<GenerateDebugInformation>true</GenerateDebugInformation>
82+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
83+
<OptimizeReferences>true</OptimizeReferences>
84+
<AdditionalLibraryDirectories>..\..\EXTERNAL\OpenCV\lib;..\..\EXTERNAL\CLAPACK\lib</AdditionalLibraryDirectories>
85+
<AdditionalDependencies>blas.lib;lapack.lib;libf2c.lib;%(AdditionalDependencies)</AdditionalDependencies>
86+
</Link>
87+
</ItemDefinitionGroup>
88+
<ItemGroup>
89+
<ClCompile Include="..\..\EXTERNAL\cvsba\src\cvsba.cpp" />
90+
<ClCompile Include="..\..\EXTERNAL\cvsba\src\sba_chkjac.c" />
91+
<ClCompile Include="..\..\EXTERNAL\cvsba\src\sba_crsm.c" />
92+
<ClCompile Include="..\..\EXTERNAL\cvsba\src\sba_lapack.c" />
93+
<ClCompile Include="..\..\EXTERNAL\cvsba\src\sba_levmar.c" />
94+
<ClCompile Include="..\..\EXTERNAL\cvsba\src\sba_levmar_wrap.c" />
95+
<ClCompile Include="..\..\src\bundle_adjustment.cpp" />
96+
</ItemGroup>
97+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
98+
<ImportGroup Label="ExtensionTargets">
99+
</ImportGroup>
100+
</Project>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
4+
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
5+
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
6+
</PropertyGroup>
7+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
8+
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
9+
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
10+
</PropertyGroup>
11+
</Project>

src/bundle_adjustment.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#include "opencv_all.hpp"
2+
#include "cvsba.h"
3+
4+
int main(void)
5+
{
6+
double camera_focal = 1000;
7+
cv::Point2d camera_center(320, 240);
8+
int n_views = 5;
9+
10+
// Load multiple views of 'box.xyz'
11+
// c.f. You need to run 'image_generation.cpp' to generate point observation.
12+
// You can apply Gaussian noise by change value of 'camera_noise' if necessay.
13+
std::vector<std::vector<cv::Point2d> > xs;
14+
for (int i = 0; i < n_views; i++)
15+
{
16+
FILE* fin = fopen(cv::format("image_generation%d.xyz", i).c_str(), "rt");
17+
if (fin == NULL) return -1;
18+
std::vector<cv::Point2d> pts;
19+
while (!feof(fin))
20+
{
21+
double x, y, w;
22+
if (fscanf(fin, "%lf %lf %lf", &x, &y, &w) == 3)
23+
pts.push_back(cv::Point2d(x, y));
24+
}
25+
fclose(fin);
26+
xs.push_back(pts);
27+
if (xs.front().size() != xs.back().size()) return -1;
28+
}
29+
std::vector<int> visible_all(xs.front().size(), 1);
30+
std::vector<std::vector<int> > visibility(n_views, visible_all);
31+
32+
// Prepare each camera projection matrix
33+
std::vector<cv::Mat> Ks, dist_coeffs, Rs, ts;
34+
cv::Mat K = (cv::Mat_<double>(3, 3) << camera_focal, 0, camera_center.x, 0, camera_focal, camera_center.y, 0, 0, 1);
35+
Ks.resize(n_views, K); // K for all cameras
36+
dist_coeffs.resize(n_views, cv::Mat::zeros(5, 1, CV_64F)); // dist_coeff for all cameras
37+
Rs.push_back(cv::Mat::eye(3, 3, CV_64F)); // R for the first camera (index: 0)
38+
ts.push_back(cv::Mat::zeros(3, 1, CV_64F)); // t for the first camera (index: 0)
39+
40+
// Esitmate relative pose of the inital two views
41+
cv::Mat F = cv::findFundamentalMat(xs[0], xs[1], cv::FM_8POINT);
42+
cv::Mat E = K.t() * F * K;
43+
cv::Mat R, t;
44+
cv::recoverPose(E, xs[0], xs[1], K, R, t);
45+
Rs.push_back(R); // R for the second camera
46+
ts.push_back(t); // t for the second camera
47+
48+
// Reconstruct the initial 3D points of 'box.xyz' (triangulation)
49+
cv::Mat P0 = K * cv::Mat::eye(3, 4, CV_64F);
50+
cv::Mat Rt, X;
51+
cv::hconcat(R, t, Rt);
52+
cv::Mat P1 = K * Rt;
53+
cv::triangulatePoints(P0, P1, xs[0], xs[1], X);
54+
std::vector<cv::Point3d> Xs;
55+
X.row(0) = X.row(0) / X.row(3);
56+
X.row(1) = X.row(1) / X.row(3);
57+
X.row(2) = X.row(2) / X.row(3);
58+
X.row(3) = 1;
59+
for (int c = 0; c < X.cols; c++)
60+
Xs.push_back(cv::Point3d(X.at<double>(0, c), X.at<double>(1, c), X.at<double>(2, c)));
61+
62+
// Estimate the initial relative pose of other views (PnP)
63+
for (int i = 2; i < n_views; i++)
64+
{
65+
cv::Mat rvec;
66+
cv::solvePnP(Xs, xs[i], Ks[i], dist_coeffs[i], rvec, t);
67+
cv::Rodrigues(rvec, R);
68+
Rs.push_back(R); // R for the third and other cameras
69+
ts.push_back(t); // t for the third and other cameras
70+
}
71+
72+
// Optimize camera pose and 3D points (bundle adjustment)
73+
try
74+
{
75+
cvsba::Sba sba;
76+
cvsba::Sba::Params param;
77+
param.type = cvsba::Sba::MOTIONSTRUCTURE;
78+
param.fixedIntrinsics = 5;
79+
param.fixedDistortion = 5;
80+
param.verbose = true;
81+
sba.setParams(param);
82+
double error = sba.run(Xs, xs, visibility, Ks, Rs, ts, dist_coeffs);
83+
}
84+
catch (cv::Exception) { }
85+
86+
// Store the 3D points
87+
FILE* fout = fopen("bundle_adjustment.xyz", "wt");
88+
if (fout == NULL) return -1;
89+
for (size_t i = 0; i < Xs.size(); i++)
90+
fprintf(fout, "%f %f %f\n", Xs[i].x, Xs[i].y, Xs[i].z);
91+
fclose(fout);
92+
return 0;
93+
}

src/image_generation.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ int main(void)
1212
cv::Size camera_res(640, 480);
1313
cv::Point3d camera_pos[] = { cv::Point3d(0, 0, 0), cv::Point3d(-2, -2, 0), cv::Point3d(2, 2, 0), cv::Point3d(-2, 2, 0), cv::Point3d(2, -2, 0) };
1414
cv::Point3d camera_ori[] = { cv::Point3d(0, 0, 0), cv::Point3d(-CV_PI / 12, CV_PI / 12, 0), cv::Point3d(CV_PI / 12, -CV_PI / 12, 0), cv::Point3d(CV_PI / 12, CV_PI / 12, 0), cv::Point3d(-CV_PI / 12, -CV_PI / 12, 0) };
15-
double camera_noise = 0;
15+
double camera_noise = 1;
1616

1717
// Load a point cloud in the homogeneous coordinate
1818
FILE* fin = fopen("data/box.xyz", "rt");
@@ -63,10 +63,11 @@ int main(void)
6363
}
6464
cv::imshow(cv::format("3DV_Tutorial: Image Generation %d", i), image);
6565

66-
std::ofstream fout(cv::format("image_generation%d.csv", i));
67-
if (!fout.is_open()) break;
68-
fout << cv::format(x.t(), cv::Formatter::FMT_CSV);
69-
fout.close();
66+
FILE* fout = fopen(cv::format("image_generation%d.xyz", i).c_str(), "wt");
67+
if (fout == NULL) return -1;
68+
for (int c = 0; c < x.cols; c++)
69+
fprintf(fout, "%f %f 1\n", x.at<double>(0, c), x.at<double>(1, c));
70+
fclose(fout);
7071
}
7172

7273
std::cout << "Press any key to terminate tihs program!" << std::endl;

src/mono_visual_odometry.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ int main(void)
77
cv::Point2d camera_center(607.1928, 185.2157);
88

99
// Open a file to write camera trajectory
10-
FILE* camera_traj = fopen("camera_trajectory.csv", "wt");
10+
FILE* camera_traj = fopen("mono_visual_odometry.xyz", "wt");
1111
if (camera_traj == NULL) return -1;
1212

1313
// Open an video and get the initial image
@@ -71,7 +71,7 @@ int main(void)
7171
else cv::line(image, point_prev[i], point[i], cv::Scalar(0, 255, 0));
7272
}
7373
cv::imshow("3DV Tutorial: Monocular Visual Odometry", image);
74-
fprintf(camera_traj, "%.6f, %.6f, %.6f\n", camera_pose.at<double>(0, 3), camera_pose.at<double>(1, 3), camera_pose.at<double>(2, 3));
74+
fprintf(camera_traj, "%.6f %.6f %.6f\n", camera_pose.at<double>(0, 3), camera_pose.at<double>(1, 3), camera_pose.at<double>(2, 3));
7575
if (cv::waitKey(1) == 27) break; // 'ESC' key: Exit
7676
}
7777

src/triangulation.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ int main(void)
66
cv::Point2d camera_center(320, 240);
77

88
// Load two views of 'box.xyz'
9-
// c.f. You need to run 'image_generation.cpp' to generate two files for point observation.
9+
// c.f. You need to run 'image_generation.cpp' to generate point observation.
1010
// You can apply Gaussian noise by change value of 'camera_noise' if necessay.
1111
std::vector<cv::Point2d> points0, points1;
12-
FILE* fin0 = fopen("image_generation0.csv", "rt");
13-
FILE* fin1 = fopen("image_generation1.csv", "rt");
12+
FILE* fin0 = fopen("image_generation0.xyz", "rt");
13+
FILE* fin1 = fopen("image_generation1.xyz", "rt");
1414
if (fin0 == NULL || fin1 == NULL) return -1;
1515
while (!feof(fin0) || !feof(fin1))
1616
{
1717
double x, y, w;
18-
if (!feof(fin0) && fscanf(fin0, "%lf, %lf, %lf", &x, &y, &w) == 3)
18+
if (!feof(fin0) && fscanf(fin0, "%lf %lf %lf", &x, &y, &w) == 3)
1919
points0.push_back(cv::Point2d(x, y));
20-
if (!feof(fin1) && fscanf(fin1, "%lf, %lf, %lf", &x, &y, &w) == 3)
20+
if (!feof(fin1) && fscanf(fin1, "%lf %lf %lf", &x, &y, &w) == 3)
2121
points1.push_back(cv::Point2d(x, y));
2222
}
2323
fclose(fin0);

0 commit comments

Comments
 (0)