Skip to content

Commit c5adbc4

Browse files
committed
Add line fitting with RANSAC
1 parent 9df5d66 commit c5adbc4

4 files changed

Lines changed: 181 additions & 0 deletions

File tree

msvs/3dv_tutorial.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "triangulation", "triangulat
2323
EndProject
2424
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bundle_adjustment", "bundle_adjustment\bundle_adjustment.vcxproj", "{968A197A-66E1-499E-B3DE-E7760D74081B}"
2525
EndProject
26+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ransac_line", "ransac_line\ransac_line.vcxproj", "{53D993B4-1B33-4C18-B279-B77B17517278}"
27+
EndProject
2628
Global
2729
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2830
Debug|Win32 = Debug|Win32
@@ -69,6 +71,10 @@ Global
6971
{968A197A-66E1-499E-B3DE-E7760D74081B}.Debug|Win32.Build.0 = Debug|Win32
7072
{968A197A-66E1-499E-B3DE-E7760D74081B}.Release|Win32.ActiveCfg = Release|Win32
7173
{968A197A-66E1-499E-B3DE-E7760D74081B}.Release|Win32.Build.0 = Release|Win32
74+
{53D993B4-1B33-4C18-B279-B77B17517278}.Debug|Win32.ActiveCfg = Debug|Win32
75+
{53D993B4-1B33-4C18-B279-B77B17517278}.Debug|Win32.Build.0 = Debug|Win32
76+
{53D993B4-1B33-4C18-B279-B77B17517278}.Release|Win32.ActiveCfg = Release|Win32
77+
{53D993B4-1B33-4C18-B279-B77B17517278}.Release|Win32.Build.0 = Release|Win32
7278
EndGlobalSection
7379
GlobalSection(SolutionProperties) = preSolution
7480
HideSolutionNode = FALSE
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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>{53D993B4-1B33-4C18-B279-B77B17517278}</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</AdditionalIncludeDirectories>
59+
</ClCompile>
60+
<Link>
61+
<SubSystem>Console</SubSystem>
62+
<GenerateDebugInformation>true</GenerateDebugInformation>
63+
<AdditionalLibraryDirectories>..\..\EXTERNAL\OpenCV\lib</AdditionalLibraryDirectories>
64+
</Link>
65+
</ItemDefinitionGroup>
66+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
67+
<ClCompile>
68+
<WarningLevel>Level3</WarningLevel>
69+
<PrecompiledHeader>
70+
</PrecompiledHeader>
71+
<Optimization>MaxSpeed</Optimization>
72+
<FunctionLevelLinking>true</FunctionLevelLinking>
73+
<IntrinsicFunctions>true</IntrinsicFunctions>
74+
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
75+
<SDLCheck>true</SDLCheck>
76+
<AdditionalIncludeDirectories>..\..\EXTERNAL\OpenCV\include</AdditionalIncludeDirectories>
77+
</ClCompile>
78+
<Link>
79+
<SubSystem>Console</SubSystem>
80+
<GenerateDebugInformation>true</GenerateDebugInformation>
81+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
82+
<OptimizeReferences>true</OptimizeReferences>
83+
<AdditionalLibraryDirectories>..\..\EXTERNAL\OpenCV\lib</AdditionalLibraryDirectories>
84+
</Link>
85+
</ItemDefinitionGroup>
86+
<ItemGroup>
87+
<ClCompile Include="..\..\src\ransac_line.cpp" />
88+
</ItemGroup>
89+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
90+
<ImportGroup Label="ExtensionTargets">
91+
</ImportGroup>
92+
</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/ransac_line.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "opencv_all.hpp"
2+
3+
#define CONVERT_LINE(line) (cv::Vec3d(line(0), -line(1), -line(0) * line(2) + line(1) * line(3)))
4+
5+
int main(void)
6+
{
7+
int ransac_trial = 50;
8+
double ransac_thresh = 3.0;
9+
int ransac_n_sample = 2;
10+
int sim_n_data = 1000;
11+
double sim_inlier_ratio = 0.5, sim_inlier_noise = 1.0;
12+
cv::Vec3d truth(1.0 / sqrt(2.0), 1.0 / sqrt(2.0), -240.0); // The line model: a*x + b*y + c = 0
13+
14+
// Generate data
15+
std::vector<cv::Point2d> data;
16+
cv::RNG rng;
17+
for (int i = 0; i < sim_n_data; i++)
18+
{
19+
if (rng.uniform(0.0, 1.0) < sim_inlier_ratio)
20+
{
21+
double x = rng.uniform(0.0, 480.0);
22+
double y = (truth(0) * x + truth(2)) / -truth(1);
23+
x += rng.gaussian(sim_inlier_noise);
24+
y += rng.gaussian(sim_inlier_noise);
25+
data.push_back(cv::Point2d(x, y)); // Inlier
26+
}
27+
else data.push_back(cv::Point2d(rng.uniform(0.0, 640.0), rng.uniform(0.0, 480.0))); // Outlier
28+
}
29+
30+
// Estimate a line using RANSAC
31+
int best_score = -1;
32+
cv::Vec3d best_line;
33+
for (int i = 0; i < ransac_trial; i++)
34+
{
35+
// Step 1: Hypothesis generation
36+
std::vector<cv::Point2d> sample;
37+
for (int j = 1; j < ransac_n_sample; j++)
38+
{
39+
int index = rng.uniform(0, data.size());
40+
sample.push_back(data[index]);
41+
}
42+
cv::Vec4d vvxy;
43+
cv::fitLine(sample, vvxy, CV_DIST_L2, 0, 0.01, 0.01);
44+
cv::Vec3d line = CONVERT_LINE(vvxy);
45+
46+
// Step 2: Hypothesis evaluation
47+
int score = 0;
48+
for (size_t j = 0; j < data.size(); j++)
49+
{
50+
double error = fabs(line(0) * data[j].x + line(1) * data[j].y + line(2));
51+
if (error < ransac_thresh) score++;
52+
}
53+
54+
if (score > best_score)
55+
{
56+
best_score = score;
57+
best_line = line;
58+
}
59+
}
60+
61+
// Estimate a line using least-squares method (for reference)
62+
cv::Vec4d vvxy;
63+
cv::fitLine(data, vvxy, CV_DIST_L2, 0, 0.01, 0.01);
64+
cv::Vec3d lsm_line = CONVERT_LINE(vvxy);
65+
66+
// Display estimates
67+
printf("* The Truth: %.3f, %.3f, %.3f\n", truth(0), truth(1), truth(2));
68+
printf("* Estimate (RANSAC): %.3f, %.3f, %.3f (Score: %d)\n", best_line(0), best_line(1), best_line(2), best_score);
69+
printf("* Estimate (LSM): %.3f, %.3f, %.3f\n", lsm_line(0), lsm_line(1), lsm_line(2));
70+
71+
return 0;
72+
}

0 commit comments

Comments
 (0)