diff --git a/ICP/ICP.vcxproj b/ICP/ICP.vcxproj
new file mode 100644
index 0000000..3e1c709
--- /dev/null
+++ b/ICP/ICP.vcxproj
@@ -0,0 +1,129 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release DLL
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}
+ ICP
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ProjectName)
+ $(SolutionDir)bin\
+
+
+ $(SolutionDir)bin\
+
+
+ $(SolutionDir)bin\
+
+
+
+ Level3
+ Disabled
+ true
+ $(SolutionDir)\include\ICP;$(SolutionDir)\include
+ _CRT_SECURE_NO_WARNINGS;ICP_DLL_EXPORTS;_MBCS;%(PreprocessorDefinitions)
+
+
+ true
+ $(SolutionDir)\lib;%(AdditionalLibraryDirectories)
+ opencv_core248d.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ $(SolutionDir)\include\ICP;$(SolutionDir)\include
+ _CRT_SECURE_NO_WARNINGS;ICP_DLL_EXPORTS;_MBCS;%(PreprocessorDefinitions)
+ StreamingSIMDExtensions2
+ true
+
+
+ true
+ true
+ true
+ $(SolutionDir)\lib;
+ opencv_core248.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ $(SolutionDir)\include\ICP;$(SolutionDir)\include
+ _CRT_SECURE_NO_WARNINGS;ICP_DLL_EXPORTS;_WINDLL;%(PreprocessorDefinitions)
+ true
+
+
+ true
+ true
+ true
+ $(SolutionDir)\lib;
+ opencv_core248.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ICP/ICP.vcxproj.filters b/ICP/ICP.vcxproj.filters
new file mode 100644
index 0000000..1fd40fd
--- /dev/null
+++ b/ICP/ICP.vcxproj.filters
@@ -0,0 +1,33 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/ICP/Release DLL/ICP.tlog/CL.read.1.tlog b/ICP/Release DLL/ICP.tlog/CL.read.1.tlog
new file mode 100644
index 0000000..deddf39
Binary files /dev/null and b/ICP/Release DLL/ICP.tlog/CL.read.1.tlog differ
diff --git a/ICP/Release DLL/ICP.tlog/CL.write.1.tlog b/ICP/Release DLL/ICP.tlog/CL.write.1.tlog
new file mode 100644
index 0000000..0e74de1
Binary files /dev/null and b/ICP/Release DLL/ICP.tlog/CL.write.1.tlog differ
diff --git a/ICP/Release DLL/ICP.tlog/ICP.lastbuildstate b/ICP/Release DLL/ICP.tlog/ICP.lastbuildstate
new file mode 100644
index 0000000..62cfa56
--- /dev/null
+++ b/ICP/Release DLL/ICP.tlog/ICP.lastbuildstate
@@ -0,0 +1,2 @@
+#TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit
+Release DLL|Win32|D:\Praca\LiveScan3D\LiveScanServer\|
diff --git a/ICP/Release DLL/ICP.tlog/ICP.write.1u.tlog b/ICP/Release DLL/ICP.tlog/ICP.write.1u.tlog
new file mode 100644
index 0000000..669f4c9
Binary files /dev/null and b/ICP/Release DLL/ICP.tlog/ICP.write.1u.tlog differ
diff --git a/ICP/Release DLL/ICP.tlog/cl.command.1.tlog b/ICP/Release DLL/ICP.tlog/cl.command.1.tlog
new file mode 100644
index 0000000..d01d6ee
Binary files /dev/null and b/ICP/Release DLL/ICP.tlog/cl.command.1.tlog differ
diff --git a/ICP/Release DLL/ICP.tlog/link.command.1.tlog b/ICP/Release DLL/ICP.tlog/link.command.1.tlog
new file mode 100644
index 0000000..1783900
Binary files /dev/null and b/ICP/Release DLL/ICP.tlog/link.command.1.tlog differ
diff --git a/ICP/Release DLL/ICP.tlog/link.read.1.tlog b/ICP/Release DLL/ICP.tlog/link.read.1.tlog
new file mode 100644
index 0000000..32222d6
Binary files /dev/null and b/ICP/Release DLL/ICP.tlog/link.read.1.tlog differ
diff --git a/ICP/Release DLL/ICP.tlog/link.write.1.tlog b/ICP/Release DLL/ICP.tlog/link.write.1.tlog
new file mode 100644
index 0000000..32917a6
Binary files /dev/null and b/ICP/Release DLL/ICP.tlog/link.write.1.tlog differ
diff --git a/LiveScan.sln b/LiveScan.sln
new file mode 100644
index 0000000..b700701
--- /dev/null
+++ b/LiveScan.sln
@@ -0,0 +1,74 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LiveScanClient", "LiveScanClient\KinectClient.vcxproj", "{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveScanServer", "LiveScanServer\LiveScanServer.csproj", "{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICP", "ICP\ICP.vcxproj", "{973EE923-B423-4BCD-AA08-B03DA40CB51F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|Win32 = Debug|Win32
+ Release ICP as exe|Any CPU = Release ICP as exe|Any CPU
+ Release ICP as exe|Mixed Platforms = Release ICP as exe|Mixed Platforms
+ Release ICP as exe|Win32 = Release ICP as exe|Win32
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Win32.Build.0 = Debug|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Any CPU.ActiveCfg = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Mixed Platforms.ActiveCfg = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Mixed Platforms.Build.0 = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Win32.ActiveCfg = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Win32.Build.0 = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Any CPU.ActiveCfg = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Win32.ActiveCfg = Release|Win32
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Win32.Build.0 = Release|Win32
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Any CPU.ActiveCfg = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Any CPU.Build.0 = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Mixed Platforms.Build.0 = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Win32.ActiveCfg = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Win32.ActiveCfg = Release|Any CPU
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Win32.Build.0 = Debug|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Any CPU.ActiveCfg = Release|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Mixed Platforms.ActiveCfg = Release|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Mixed Platforms.Build.0 = Release|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Win32.ActiveCfg = Release|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Win32.Build.0 = Release|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Any CPU.ActiveCfg = Release DLL|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Mixed Platforms.ActiveCfg = Release DLL|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Mixed Platforms.Build.0 = Release DLL|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Win32.ActiveCfg = Release DLL|Win32
+ {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Win32.Build.0 = Release DLL|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/LiveScanClient/KinectClient.vcxproj b/LiveScanClient/KinectClient.vcxproj
new file mode 100644
index 0000000..cfff532
--- /dev/null
+++ b/LiveScanClient/KinectClient.vcxproj
@@ -0,0 +1,121 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}
+ KinectClient
+ LiveScanClient
+
+
+
+ Application
+ true
+ v120
+ Unicode
+
+
+ Application
+ false
+ v120
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)bin\
+ $(ProjectName)D
+
+
+ $(SolutionDir)bin\
+ $(ProjectName)
+
+
+
+ Level3
+ Disabled
+ true
+ $(KINECTSDK20_DIR)\inc;$(SolutionDir)\include\LiveScanClient;$(SolutionDir)\include;$(ProjectDir)
+ _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions)
+
+
+ true
+ c:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86\;D:\opencv\build\x86\vc12\lib;$(KINECTSDK20_DIR)\lib\x86;$(SolutionDir)lib
+ opencv_highgui248d.lib;opencv_calib3d248d.lib;opencv_imgproc248d.lib;opencv_core248d.lib;kinect20.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ NotSet
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ $(KINECTSDK20_DIR)\inc;$(SolutionDir)\include\LiveScanClient;$(SolutionDir)\include;$(ProjectDir)
+ _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;_WINSOCK_DEPRACATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ StreamingSIMDExtensions2
+
+
+ true
+ true
+ true
+ opencv_highgui248.lib;opencv_calib3d248.lib;opencv_imgproc248.lib;opencv_core248.lib;kinect20.lib;%(AdditionalDependencies)
+ c:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86\;D:\opencv\build\x86\vc12\lib;$(KINECTSDK20_DIR)\lib\x86;$(SolutionDir)lib
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LiveScanClient/KinectClient.vcxproj.filters b/LiveScanClient/KinectClient.vcxproj.filters
new file mode 100644
index 0000000..679951e
--- /dev/null
+++ b/LiveScanClient/KinectClient.vcxproj.filters
@@ -0,0 +1,100 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/LiveScanClient/LiveScanClient.rc b/LiveScanClient/LiveScanClient.rc
new file mode 100644
index 0000000..5eac6e2
--- /dev/null
+++ b/LiveScanClient/LiveScanClient.rc
@@ -0,0 +1,112 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP ICON "app.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_APP DIALOGEX 0, 0, 643, 415
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT | WS_EX_APPWINDOW
+CAPTION "LiveScanClient"
+CLASS "LiveScanClientAppDlgWndClass"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_VIDEOVIEW,"Static",SS_BLACKFRAME,0,0,641,360
+ DEFPUSHBUTTON "Connect",IDC_BUTTON_CONNECT,282,388,90,12
+ EDITTEXT IDC_IP,387,387,118,13,ES_AUTOHSCROLL
+ LTEXT "",IDC_STATUS,0,402,642,11,SS_SUNKEN
+ DEFPUSHBUTTON "Show depth",IDC_BUTTON_SWITCH,282,373,90,12
+ LTEXT "Server IP address:",IDC_STATIC,389,374,82,10
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_APP, DIALOG
+ BEGIN
+ RIGHTMARGIN, 642
+ BOTTOMMARGIN, 413
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/LiveScanClient/app.ico b/LiveScanClient/app.ico
new file mode 100644
index 0000000..db8b818
Binary files /dev/null and b/LiveScanClient/app.ico differ
diff --git a/LiveScanClient/resource.h b/LiveScanClient/resource.h
new file mode 100644
index 0000000..263c36a
--- /dev/null
+++ b/LiveScanClient/resource.h
@@ -0,0 +1,24 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+//
+#define IDI_APP 100
+#define IDD_APP 100
+#define IDC_VIDEOVIEW 1000
+#define IDC_STATUS 1001
+#define IDC_BUTTON_CONNECT 1003
+#define IDC_IP 1006
+#define IDC_BUTTON_SWITCH 1013
+#define IDC_STATUS2 1014
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1015
+#define _APS_NEXT_SYMED_VALUE 102
+#endif
+#endif
diff --git a/LiveScanClient/stdafx.h b/LiveScanClient/stdafx.h
new file mode 100644
index 0000000..6a1fb05
--- /dev/null
+++ b/LiveScanClient/stdafx.h
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//------------------------------------------------------------------------------
+
+// include file for standard system and project includes
+
+#pragma once
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+// Windows Header Files
+#include
+
+#include
+
+// Direct2D Header Files
+#include
+
+#pragma comment (lib, "d2d1.lib")
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+// Safe release for interfaces
+template
+inline void SafeRelease(Interface *& pInterfaceToRelease)
+{
+ if (pInterfaceToRelease != NULL)
+ {
+ pInterfaceToRelease->Release();
+ pInterfaceToRelease = NULL;
+ }
+}
\ No newline at end of file
diff --git a/LiveScanServer/App.config b/LiveScanServer/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/LiveScanServer/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LiveScanServer/KinectServer.cs b/LiveScanServer/KinectServer.cs
new file mode 100644
index 0000000..0d1bf6d
--- /dev/null
+++ b/LiveScanServer/KinectServer.cs
@@ -0,0 +1,429 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Threading;
+
+using System.Net.Sockets;
+using System.Net;
+using System.ComponentModel;
+
+namespace KinectServer
+{
+ public delegate void SocketListChangedHandler(List list);
+ public class KinectServer
+ {
+ Socket oServerSocket;
+
+ bool bServerRunning = false;
+
+ KinectSettings oSettings;
+ object oClientSocketLock = new object();
+ object oFrameRequestLock = new object();
+
+ List lClientSockets = new List();
+
+ public event SocketListChangedHandler eSocketListChanged;
+
+ public int nClientCount
+ {
+ get
+ {
+ int nClients;
+ lock (oClientSocketLock)
+ {
+ nClients = lClientSockets.Count;
+ }
+ return nClients;
+ }
+ }
+
+ public List lCameraPoses
+ {
+ get
+ {
+ List cameraPoses = new List();
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ cameraPoses.Add(lClientSockets[i].oCameraPose);
+ }
+ }
+ return cameraPoses;
+ }
+ }
+
+ public List lWorldTransforms
+ {
+ get
+ {
+ List worldTransforms = new List();
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ worldTransforms.Add(lClientSockets[i].oWorldTransform);
+ }
+ }
+ return worldTransforms;
+ }
+
+ set
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ lClientSockets[i].oWorldTransform = value[i];
+ }
+ }
+ }
+ }
+
+ public bool bAllCalibrated
+ {
+ get
+ {
+ bool allCalibrated = true;
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ if (!lClientSockets[i].bCalibrated)
+ {
+ allCalibrated = false;
+ break;
+ }
+ }
+
+ }
+ return allCalibrated;
+ }
+ }
+
+ public KinectServer(KinectSettings settings)
+ {
+ this.oSettings = settings;
+ }
+
+ private void SocketListChanged()
+ {
+ if (eSocketListChanged != null)
+ {
+ eSocketListChanged(lClientSockets);
+ }
+ }
+
+ public void StartServer()
+ {
+ if (!bServerRunning)
+ {
+ oServerSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
+ oServerSocket.Blocking = false;
+
+ IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 48001);
+ oServerSocket.Bind(endPoint);
+ oServerSocket.Listen(10);
+
+ bServerRunning = true;
+ Thread listeningThread = new Thread(this.ListeningWorker);
+ listeningThread.Start();
+ Thread receivingThread = new Thread(this.ReceivingWorker);
+ receivingThread.Start();
+ }
+ }
+
+ public void StopServer()
+ {
+ if (bServerRunning)
+ {
+ bServerRunning = false;
+
+ oServerSocket.Close();
+ lock (oClientSocketLock)
+ lClientSockets.Clear();
+ }
+ }
+
+ public void CaptureSynchronizedFrame()
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ lClientSockets[i].CaptureFrame();
+ }
+
+ //Wait till frames captured
+ bool allGathered = false;
+ while (!allGathered)
+ {
+ allGathered = true;
+
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ if (!lClientSockets[i].bFrameCaptured)
+ {
+ allGathered = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public void Calibrate()
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ lClientSockets[i].Calibrate();
+ }
+ }
+ }
+
+ public void SendSettings()
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ lClientSockets[i].SendSettings(oSettings);
+ }
+ }
+ }
+
+ public void SendCalibrationData()
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ lClientSockets[i].SendCalibrationData();
+ }
+ }
+ }
+
+ public void GetStoredFrame(List> lFramesRGB, List> lFramesVerts)
+ {
+ lFramesRGB.Clear();
+ lFramesVerts.Clear();
+
+ lock (oFrameRequestLock)
+ {
+ //Request frames
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ lClientSockets[i].RequestStoredFrame();
+ }
+
+ //Wait till frames received
+ bool allGathered = false;
+ while (!allGathered)
+ {
+ allGathered = true;
+
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ if (!lClientSockets[i].bStoredFrameReceived)
+ {
+ allGathered = false;
+ break;
+ }
+ }
+ }
+ }
+
+ //Store received frames
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ lFramesRGB.Add(new List(lClientSockets[i].lFrameRGB));
+ lFramesVerts.Add(new List(lClientSockets[i].lFrameVerts));
+ }
+ }
+ }
+ }
+
+ public void GetLatestFrame(List> lFramesRGB, List> lFramesVerts)
+ {
+ lFramesRGB.Clear();
+ lFramesVerts.Clear();
+
+ lock (oFrameRequestLock)
+ {
+ //Request frames
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ lClientSockets[i].RequestLastFrame();
+ }
+
+ //Wait till frames received
+ bool allGathered = false;
+ while (!allGathered)
+ {
+ allGathered = true;
+
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ if (!lClientSockets[i].bLatestFrameReceived)
+ {
+ allGathered = false;
+ break;
+ }
+ }
+ }
+ }
+
+ //Store received frames
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ lFramesRGB.Add(new List(lClientSockets[i].lFrameRGB));
+ lFramesVerts.Add(new List(lClientSockets[i].lFrameVerts));
+ }
+ }
+ }
+ }
+
+ public void ClearStoredFrames()
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ lClientSockets[i].ClearStoredFrames();
+ }
+ }
+ }
+
+ private void ListeningWorker()
+ {
+ while (bServerRunning)
+ {
+ try
+ {
+ Socket newClient = oServerSocket.Accept();
+
+ //we do not want to add new clients while a frame is being requested
+ lock (oFrameRequestLock)
+ {
+ lock (oClientSocketLock)
+ {
+ lClientSockets.Add(new KinectSocket(newClient));
+ lClientSockets[lClientSockets.Count - 1].SendSettings(oSettings);
+ lClientSockets[lClientSockets.Count - 1].eChanged += new SocketChangedHandler(SocketListChanged);
+ if (eSocketListChanged != null)
+ {
+ eSocketListChanged(lClientSockets);
+ }
+ }
+ }
+ }
+ catch (SocketException)
+ {
+ }
+ System.Threading.Thread.Sleep(100);
+ }
+
+ if (eSocketListChanged != null)
+ {
+ eSocketListChanged(lClientSockets);
+ }
+ }
+
+ private void ReceivingWorker()
+ {
+ System.Timers.Timer checkConnectionTimer = new System.Timers.Timer();
+ checkConnectionTimer.Interval = 1000;
+
+ checkConnectionTimer.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ if (!lClientSockets[i].SocketConnected())
+ {
+ lClientSockets.RemoveAt(i);
+ if (eSocketListChanged != null)
+ {
+ eSocketListChanged(lClientSockets);
+ }
+ continue;
+ }
+ }
+ }
+ };
+
+ checkConnectionTimer.Start();
+
+ while (bServerRunning)
+ {
+ lock (oClientSocketLock)
+ {
+ for (int i = 0; i < lClientSockets.Count; i++)
+ {
+ byte[] buffer = lClientSockets[i].Receive(1);
+
+ while (buffer.Length != 0)
+ {
+ if (buffer[0] == 0)
+ {
+ lClientSockets[i].bFrameCaptured = true;
+ }
+ else if (buffer[0] == 1)
+ {
+ lClientSockets[i].ReceiveCalibrationData();
+ }
+ //stored frame
+ else if (buffer[0] == 2)
+ {
+ lClientSockets[i].ReceiveFrame();
+ lClientSockets[i].bStoredFrameReceived = true;
+ }
+ //last frame
+ else if (buffer[0] == 3)
+ {
+ lClientSockets[i].ReceiveFrame();
+ lClientSockets[i].bLatestFrameReceived = true;
+ }
+
+ buffer = lClientSockets[i].Receive(1);
+ }
+ }
+ }
+
+ Thread.Sleep(10);
+ }
+
+ checkConnectionTimer.Stop();
+ }
+ }
+}
diff --git a/LiveScanServer/KinectSettings.cs b/LiveScanServer/KinectSettings.cs
new file mode 100644
index 0000000..fe5a063
--- /dev/null
+++ b/LiveScanServer/KinectSettings.cs
@@ -0,0 +1,93 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace KinectServer
+{
+ [Serializable]
+ public class KinectSettings
+ {
+ public float[] aMinBounds = new float[3];
+ public float[] aMaxBounds = new float[3];
+
+ public bool bFilter = false;
+ public int nFilterNeighbors = 10;
+ public float fFilterThreshold = 0.1f;
+
+ public BindingList lMarkerPoses = new BindingList();
+
+ public int nNumICPIterations = 10;
+ public int nMaxNumRefineIters = 10;
+ public bool bMergeScansForSave = false;
+
+ public KinectSettings()
+ {
+ aMinBounds[0] = -5f;
+ aMinBounds[1] = -5f;
+ aMinBounds[2] = -5f;
+
+ aMaxBounds[0] = 5f;
+ aMaxBounds[1] = 5f;
+ aMaxBounds[2] = 5f;
+ }
+
+ public List ToByteList()
+ {
+ List lData = new List();
+
+ byte[] bTemp = new byte[sizeof(float) * 3];
+
+ Buffer.BlockCopy(aMinBounds, 0, bTemp, 0, sizeof(float) * 3);
+ lData.AddRange(bTemp);
+ Buffer.BlockCopy(aMaxBounds, 0, bTemp, 0, sizeof(float) * 3);
+ lData.AddRange(bTemp);
+
+ if (bFilter)
+ lData.Add(1);
+ else
+ lData.Add(0);
+
+ bTemp = BitConverter.GetBytes(nFilterNeighbors);
+ lData.AddRange(bTemp);
+
+ bTemp = BitConverter.GetBytes(fFilterThreshold);
+ lData.AddRange(bTemp);
+
+ bTemp = BitConverter.GetBytes(lMarkerPoses.Count);
+ lData.AddRange(bTemp);
+
+ for (int i = 0; i < lMarkerPoses.Count; i++)
+ {
+ bTemp = new byte[sizeof(float) * 9];
+ Buffer.BlockCopy(lMarkerPoses[i].pose.R, 0, bTemp, 0, sizeof(float) * 9);
+ lData.AddRange(bTemp);
+
+ bTemp = new byte[sizeof(float) * 3];
+ Buffer.BlockCopy(lMarkerPoses[i].pose.t, 0, bTemp, 0, sizeof(float) * 3);
+ lData.AddRange(bTemp);
+
+ bTemp = BitConverter.GetBytes(lMarkerPoses[i].id);
+ lData.AddRange(bTemp);
+ }
+
+ return lData;
+ }
+ }
+}
diff --git a/LiveScanServer/KinectSocket.cs b/LiveScanServer/KinectSocket.cs
new file mode 100644
index 0000000..a091fe6
--- /dev/null
+++ b/LiveScanServer/KinectSocket.cs
@@ -0,0 +1,246 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Net.Sockets;
+
+namespace KinectServer
+{
+ public delegate void SocketChangedHandler();
+
+ public class KinectSocket
+ {
+ Socket oSocket;
+ byte[] byteToSend = new byte[1];
+ public bool bFrameCaptured = false;
+ public bool bLatestFrameReceived = false;
+ public bool bStoredFrameReceived = false;
+ public bool bCalibrated = false;
+ //The pose of the sensor in the scene (used by the OpenGLWindow to show the sensor)
+ public AffineTransform oCameraPose = new AffineTransform();
+ //The transform that maps the vertices in the sensor coordinate system to the world corrdinate system.
+ public AffineTransform oWorldTransform = new AffineTransform();
+
+ public string sSocketState;
+
+ public List lFrameRGB = new List();
+ public List lFrameVerts = new List();
+
+ public event SocketChangedHandler eChanged;
+
+ public KinectSocket(Socket clientSocket)
+ {
+ oSocket = clientSocket;
+ sSocketState = oSocket.RemoteEndPoint.ToString() + " Calibrated = false";
+ }
+
+ public void CaptureFrame()
+ {
+ bFrameCaptured = false;
+ byteToSend[0] = 0;
+ SendByte();
+ }
+
+ public void Calibrate()
+ {
+ bCalibrated = false;
+ sSocketState = oSocket.RemoteEndPoint.ToString() + " Calibrated = false";
+
+ byteToSend[0] = 1;
+ SendByte();
+
+ UpdateSocketState();
+ }
+
+ public void SendSettings(KinectSettings settings)
+ {
+ List lData = settings.ToByteList();
+
+ byte[] bTemp = BitConverter.GetBytes(lData.Count);
+ lData.InsertRange(0, bTemp);
+ lData.Insert(0, 2);
+
+ if (SocketConnected())
+ oSocket.Send(lData.ToArray());
+ }
+
+ public void RequestStoredFrame()
+ {
+ byteToSend[0] = 3;
+ SendByte();
+ bStoredFrameReceived = false;
+ }
+
+ public void RequestLastFrame()
+ {
+ byteToSend[0] = 4;
+ SendByte();
+ bLatestFrameReceived = false;
+ }
+
+ public void SendCalibrationData()
+ {
+ int size = 1 + 2 * (9 + 3) * sizeof(float);
+ byte[] data = new byte[size];
+ int i = 0;
+
+ data[i] = 5;
+ i++;
+
+ Buffer.BlockCopy(oWorldTransform.R, 0, data, i, 9 * sizeof(float));
+ i += 9 * sizeof(float);
+ Buffer.BlockCopy(oWorldTransform.t, 0, data, i, 3 * sizeof(float));
+ i += 3 * sizeof(float);
+
+ Buffer.BlockCopy(oCameraPose.R, 0, data, i, 9 * sizeof(float));
+ i += 9 * sizeof(float);
+ Buffer.BlockCopy(oCameraPose.t, 0, data, i, 3 * sizeof(float));
+ i += 3 * sizeof(float);
+
+
+ if (SocketConnected())
+ oSocket.Send(data);
+ }
+
+ public void ClearStoredFrames()
+ {
+ byteToSend[0] = 6;
+ SendByte();
+ }
+
+ public void ReceiveCalibrationData()
+ {
+ bCalibrated = true;
+
+ byte[] buffer = Receive(sizeof(int) * 1);
+ //currently not used
+ int markerId = BitConverter.ToInt32(buffer, 0);
+
+ buffer = Receive(sizeof(float) * 9);
+ Buffer.BlockCopy(buffer, 0, oWorldTransform.R, 0, sizeof(float) * 9);
+
+ buffer = Receive(sizeof(float) * 3);
+ Buffer.BlockCopy(buffer, 0, oWorldTransform.t, 0, sizeof(float) * 3);
+
+ buffer = Receive(sizeof(float) * 9);
+ Buffer.BlockCopy(buffer, 0, oCameraPose.R, 0, sizeof(float) * 9);
+
+ buffer = Receive(sizeof(float) * 3);
+ Buffer.BlockCopy(buffer, 0, oCameraPose.t, 0, sizeof(float) * 3);
+
+ UpdateSocketState();
+ }
+
+ public void ReceiveFrame()
+ {
+ lFrameRGB.Clear();
+ lFrameVerts.Clear();
+
+ int nToRead;
+ byte[] buffer = new byte[1024];
+
+ while (oSocket.Available == 0)
+ {
+ if (!SocketConnected())
+ return;
+ }
+
+
+ oSocket.Receive(buffer, 4, SocketFlags.None);
+
+ //string result = System.Text.Encoding.UTF8.GetString(buffer);
+ //n_to_read = Int32.Parse(result);
+
+ nToRead = BitConverter.ToInt32(buffer, 0);
+
+ if (nToRead == 0)
+ return;
+
+ buffer = new byte[nToRead];
+ int nAlreadyRead = 0;
+
+ while (nAlreadyRead != nToRead)
+ {
+ while (oSocket.Available == 0)
+ {
+ if (!SocketConnected())
+ return;
+ }
+
+ nAlreadyRead += oSocket.Receive(buffer, nAlreadyRead, nToRead - nAlreadyRead, SocketFlags.None);
+ }
+
+ int point_size = 3 + 3 * 4;
+ int n_vertices = nToRead / point_size;
+
+ for (int i = 0; i < n_vertices; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ lFrameRGB.Add(buffer[i * point_size + j]);
+ lFrameVerts.Add(BitConverter.ToSingle(buffer, i * point_size + j * 4 + 3));
+ }
+ }
+ }
+
+ public byte[] Receive(int nBytes)
+ {
+ byte[] buffer;
+ if (oSocket.Available != 0)
+ {
+ buffer = new byte[Math.Min(nBytes, oSocket.Available)];
+ oSocket.Receive(buffer, nBytes, SocketFlags.None);
+ }
+ else
+ buffer = new byte[0];
+
+ return buffer;
+ }
+
+ public bool SocketConnected()
+ {
+ bool part1 = oSocket.Poll(1000, SelectMode.SelectRead);
+ bool part2 = (oSocket.Available == 0);
+
+ if (part1 && part2)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ private void SendByte()
+ {
+ oSocket.Send(byteToSend);
+ }
+
+ public void UpdateSocketState()
+ {
+ if (bCalibrated)
+ sSocketState = oSocket.RemoteEndPoint.ToString() + " Calibrated = true";
+ else
+ sSocketState = oSocket.RemoteEndPoint.ToString() + " Calibrated = false";
+
+ if (eChanged != null)
+ eChanged();
+ }
+ }
+}
diff --git a/LiveScanServer/LiveScanServer.csproj b/LiveScanServer/LiveScanServer.csproj
new file mode 100644
index 0000000..f3dcbba
--- /dev/null
+++ b/LiveScanServer/LiveScanServer.csproj
@@ -0,0 +1,105 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}
+ WinExe
+ Properties
+ KinectServer
+ LiveScanServer
+ v4.5
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ ..\bin\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ ..\bin\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ MainWindowForm.cs
+
+
+
+
+
+
+
+
+ Form
+
+
+ SettingsForm.cs
+
+
+
+ MainWindowForm.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+ SettingsForm.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LiveScanServer/MainWindowForm.Designer.cs b/LiveScanServer/MainWindowForm.Designer.cs
new file mode 100644
index 0000000..d8d7fbf
--- /dev/null
+++ b/LiveScanServer/MainWindowForm.Designer.cs
@@ -0,0 +1,225 @@
+namespace KinectServer
+{
+ partial class MainWindowForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.btStart = new System.Windows.Forms.Button();
+ this.btCalibrate = new System.Windows.Forms.Button();
+ this.btRecord = new System.Windows.Forms.Button();
+ this.lClientListBox = new System.Windows.Forms.ListBox();
+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
+ this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel();
+ this.recordingWorker = new System.ComponentModel.BackgroundWorker();
+ this.txtSeqName = new System.Windows.Forms.TextBox();
+ this.btRefineCalib = new System.Windows.Forms.Button();
+ this.OpenGLWorker = new System.ComponentModel.BackgroundWorker();
+ this.savingWorker = new System.ComponentModel.BackgroundWorker();
+ this.updateWorker = new System.ComponentModel.BackgroundWorker();
+ this.btShowLive = new System.Windows.Forms.Button();
+ this.btSettings = new System.Windows.Forms.Button();
+ this.refineWorker = new System.ComponentModel.BackgroundWorker();
+ this.lbSeqName = new System.Windows.Forms.Label();
+ this.statusStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // btStart
+ //
+ this.btStart.Location = new System.Drawing.Point(12, 12);
+ this.btStart.Name = "btStart";
+ this.btStart.Size = new System.Drawing.Size(95, 23);
+ this.btStart.TabIndex = 0;
+ this.btStart.Text = "Start server";
+ this.btStart.UseVisualStyleBackColor = true;
+ this.btStart.Click += new System.EventHandler(this.btStart_Click);
+ //
+ // btCalibrate
+ //
+ this.btCalibrate.Location = new System.Drawing.Point(12, 70);
+ this.btCalibrate.Name = "btCalibrate";
+ this.btCalibrate.Size = new System.Drawing.Size(95, 23);
+ this.btCalibrate.TabIndex = 2;
+ this.btCalibrate.Text = "Calibrate";
+ this.btCalibrate.UseVisualStyleBackColor = true;
+ this.btCalibrate.Click += new System.EventHandler(this.btCalibrate_Click);
+ //
+ // btRecord
+ //
+ this.btRecord.Location = new System.Drawing.Point(12, 126);
+ this.btRecord.Name = "btRecord";
+ this.btRecord.Size = new System.Drawing.Size(95, 23);
+ this.btRecord.TabIndex = 4;
+ this.btRecord.Text = "Start recording";
+ this.btRecord.UseVisualStyleBackColor = true;
+ this.btRecord.Click += new System.EventHandler(this.btRecord_Click);
+ //
+ // lClientListBox
+ //
+ this.lClientListBox.FormattingEnabled = true;
+ this.lClientListBox.Location = new System.Drawing.Point(113, 12);
+ this.lClientListBox.Name = "lClientListBox";
+ this.lClientListBox.Size = new System.Drawing.Size(219, 108);
+ this.lClientListBox.TabIndex = 5;
+ //
+ // statusStrip1
+ //
+ this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.statusLabel});
+ this.statusStrip1.Location = new System.Drawing.Point(0, 187);
+ this.statusStrip1.Name = "statusStrip1";
+ this.statusStrip1.Size = new System.Drawing.Size(344, 22);
+ this.statusStrip1.TabIndex = 6;
+ this.statusStrip1.Text = "statusStrip1";
+ //
+ // statusLabel
+ //
+ this.statusLabel.Name = "statusLabel";
+ this.statusLabel.Size = new System.Drawing.Size(0, 17);
+ //
+ // recordingWorker
+ //
+ this.recordingWorker.WorkerSupportsCancellation = true;
+ this.recordingWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.recordingWorker_DoWork);
+ this.recordingWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.recordingWorker_RunWorkerCompleted);
+ //
+ // txtSeqName
+ //
+ this.txtSeqName.Location = new System.Drawing.Point(113, 155);
+ this.txtSeqName.MaxLength = 40;
+ this.txtSeqName.Name = "txtSeqName";
+ this.txtSeqName.Size = new System.Drawing.Size(106, 20);
+ this.txtSeqName.TabIndex = 7;
+ this.txtSeqName.Text = "noname";
+ //
+ // btRefineCalib
+ //
+ this.btRefineCalib.Location = new System.Drawing.Point(12, 97);
+ this.btRefineCalib.Name = "btRefineCalib";
+ this.btRefineCalib.Size = new System.Drawing.Size(95, 23);
+ this.btRefineCalib.TabIndex = 11;
+ this.btRefineCalib.Text = "Refine calib";
+ this.btRefineCalib.UseVisualStyleBackColor = true;
+ this.btRefineCalib.Click += new System.EventHandler(this.btRefineCalib_Click);
+ //
+ // OpenGLWorker
+ //
+ this.OpenGLWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.OpenGLWorker_DoWork);
+ this.OpenGLWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.OpenGLWorker_RunWorkerCompleted);
+ //
+ // savingWorker
+ //
+ this.savingWorker.WorkerSupportsCancellation = true;
+ this.savingWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.savingWorker_DoWork);
+ this.savingWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.savingWorker_RunWorkerCompleted);
+ //
+ // updateWorker
+ //
+ this.updateWorker.WorkerSupportsCancellation = true;
+ this.updateWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.updateWorker_DoWork);
+ //
+ // btShowLive
+ //
+ this.btShowLive.Location = new System.Drawing.Point(12, 154);
+ this.btShowLive.Name = "btShowLive";
+ this.btShowLive.Size = new System.Drawing.Size(95, 23);
+ this.btShowLive.TabIndex = 12;
+ this.btShowLive.Text = "Show live";
+ this.btShowLive.UseVisualStyleBackColor = true;
+ this.btShowLive.Click += new System.EventHandler(this.btShowLive_Click);
+ //
+ // btSettings
+ //
+ this.btSettings.Location = new System.Drawing.Point(12, 41);
+ this.btSettings.Name = "btSettings";
+ this.btSettings.Size = new System.Drawing.Size(95, 23);
+ this.btSettings.TabIndex = 13;
+ this.btSettings.Text = "Settings";
+ this.btSettings.UseVisualStyleBackColor = true;
+ this.btSettings.Click += new System.EventHandler(this.btSettings_Click);
+ //
+ // refineWorker
+ //
+ this.refineWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.refineWorker_DoWork);
+ this.refineWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.refineWorker_RunWorkerCompleted);
+ //
+ // lbSeqName
+ //
+ this.lbSeqName.AutoSize = true;
+ this.lbSeqName.Location = new System.Drawing.Point(113, 136);
+ this.lbSeqName.Name = "lbSeqName";
+ this.lbSeqName.Size = new System.Drawing.Size(88, 13);
+ this.lbSeqName.TabIndex = 14;
+ this.lbSeqName.Text = "Sequence name:";
+ //
+ // MainWindowForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(344, 209);
+ this.Controls.Add(this.lbSeqName);
+ this.Controls.Add(this.btSettings);
+ this.Controls.Add(this.btShowLive);
+ this.Controls.Add(this.btRefineCalib);
+ this.Controls.Add(this.txtSeqName);
+ this.Controls.Add(this.statusStrip1);
+ this.Controls.Add(this.lClientListBox);
+ this.Controls.Add(this.btRecord);
+ this.Controls.Add(this.btCalibrate);
+ this.Controls.Add(this.btStart);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.MaximizeBox = false;
+ this.Name = "MainWindowForm";
+ this.Text = "LiveScanServer";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
+ this.statusStrip1.ResumeLayout(false);
+ this.statusStrip1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button btStart;
+ private System.Windows.Forms.Button btCalibrate;
+ private System.Windows.Forms.Button btRecord;
+ private System.Windows.Forms.ListBox lClientListBox;
+ private System.Windows.Forms.StatusStrip statusStrip1;
+ private System.ComponentModel.BackgroundWorker recordingWorker;
+ private System.Windows.Forms.TextBox txtSeqName;
+ private System.Windows.Forms.Button btRefineCalib;
+ private System.ComponentModel.BackgroundWorker OpenGLWorker;
+ private System.ComponentModel.BackgroundWorker savingWorker;
+ private System.ComponentModel.BackgroundWorker updateWorker;
+ private System.Windows.Forms.Button btShowLive;
+ private System.Windows.Forms.Button btSettings;
+ private System.ComponentModel.BackgroundWorker refineWorker;
+ private System.Windows.Forms.ToolStripStatusLabel statusLabel;
+ private System.Windows.Forms.Label lbSeqName;
+ }
+}
+
diff --git a/LiveScanServer/MainWindowForm.cs b/LiveScanServer/MainWindowForm.cs
new file mode 100644
index 0000000..de20044
--- /dev/null
+++ b/LiveScanServer/MainWindowForm.cs
@@ -0,0 +1,524 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Threading;
+using System.Windows.Forms;
+using System.Globalization;
+using System.Runtime.Serialization;
+
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Timers;
+
+
+namespace KinectServer
+{
+ public partial class MainWindowForm : Form
+ {
+ [DllImport("ICP.dll")]
+ static extern float ICP(IntPtr verts1, IntPtr verts2, int nVerts1, int nVerts2, float[] R, float[] t, int maxIter = 200);
+
+ KinectServer oServer;
+
+ //Those three variables are shared with the OpenGLWindow class and are used to exchange data with it.
+ //Vertices from all of the sensors
+ List lAllVertices = new List();
+ //Color data from all of the sensors
+ List lAllColors = new List();
+ //Sensor poses from all of the sensors
+ List lAllCameraPoses = new List();
+
+ bool bServerRunning = false;
+ bool bRecording = false;
+ bool bSaving = false;
+
+ //Live view open or not
+ bool bLiveViewRunning = false;
+
+ System.Timers.Timer oStatusBarTimer = new System.Timers.Timer();
+
+ KinectSettings oSettings = new KinectSettings();
+ //The live view window class
+ OpenGLWindow oOpenGLWindow;
+
+ public MainWindowForm()
+ {
+ //This tries to read the settings from "settings.bin", if it failes the settings stay at default values.
+ try
+ {
+ IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
+ Stream stream = new FileStream("settings.bin", FileMode.Open, FileAccess.Read);
+ oSettings = (KinectSettings)formatter.Deserialize(stream);
+ stream.Close();
+ }
+ catch(Exception)
+ {
+ }
+
+ oServer = new KinectServer(oSettings);
+ oServer.eSocketListChanged += new SocketListChangedHandler(UpdateListView);
+
+ InitializeComponent();
+ }
+
+ private void Form1_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ //The current settings are saved to a files.
+ IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
+
+ Stream stream = new FileStream("settings.bin", FileMode.Create, FileAccess.Write);
+ formatter.Serialize(stream, oSettings);
+ stream.Close();
+
+ oServer.StopServer();
+ }
+
+ //Starts the server
+ private void btStart_Click(object sender, EventArgs e)
+ {
+ bServerRunning = !bServerRunning;
+
+ if (bServerRunning)
+ {
+ oServer.StartServer();
+ btStart.Text = "Stop server";
+ }
+ else
+ {
+ oServer.StopServer();
+ btStart.Text = "Start server";
+ }
+ }
+
+ //Opens the settings form
+ private void btSettings_Click(object sender, EventArgs e)
+ {
+ SettingsForm form = new SettingsForm();
+ form.oSettings = oSettings;
+ form.oServer = oServer;
+ form.Show();
+ }
+
+ //Performs recording which is synchronized frame capture.
+ //The frames are downloaded from the clients and saved once recording is finished.
+ private void recordingWorker_DoWork(object sender, DoWorkEventArgs e)
+ {
+ oServer.ClearStoredFrames();
+
+ int nCaptured = 0;
+ BackgroundWorker worker = (BackgroundWorker)sender;
+ while (!worker.CancellationPending)
+ {
+ oServer.CaptureSynchronizedFrame();
+
+ nCaptured++;
+ SetStatusBarOnTimer("Captured frame " + (nCaptured).ToString() + ".", 5000);
+ }
+ }
+
+ private void recordingWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ //After recording has been terminated it is time to begin saving the frames.
+ //Saving is downloading the frames from clients and saving them locally.
+ bSaving = true;
+
+ btRecord.Text = "Stop saving";
+ btRecord.Enabled = true;
+
+ savingWorker.RunWorkerAsync();
+ }
+
+ //Opens the live view window
+ private void OpenGLWorker_DoWork(object sender, DoWorkEventArgs e)
+ {
+ bLiveViewRunning = true;
+ oOpenGLWindow = new OpenGLWindow();
+
+ //The variables below are shared between this class and the OpenGLWindow.
+ lock (lAllVertices)
+ {
+ oOpenGLWindow.vertices = lAllVertices;
+ oOpenGLWindow.colors = lAllColors;
+ oOpenGLWindow.cameraPoses = lAllCameraPoses;
+ oOpenGLWindow.settings = oSettings;
+ }
+ oOpenGLWindow.Run();
+ }
+
+ private void OpenGLWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ bLiveViewRunning = false;
+ updateWorker.CancelAsync();
+ }
+
+ private void savingWorker_DoWork(object sender, DoWorkEventArgs e)
+ {
+ int nFrames = 0;
+
+ string outDir = "out" + "\\" + txtSeqName.Text + "\\";
+ DirectoryInfo di = Directory.CreateDirectory(outDir);
+
+ BackgroundWorker worker = (BackgroundWorker)sender;
+ //This loop is running till it is either cancelled (using the btRecord button), or till there are no more stored frames.
+ while (!worker.CancellationPending)
+ {
+ List> lFrameRGBAllDevices = new List>();
+ List> lFrameVertsAllDevices = new List>();
+
+ oServer.GetStoredFrame(lFrameRGBAllDevices, lFrameVertsAllDevices);
+
+ nFrames++;
+ int nVerticesTotal = 0;
+ for (int i = 0; i < lFrameRGBAllDevices.Count; i++)
+ {
+ nVerticesTotal += lFrameVertsAllDevices[i].Count;
+ }
+
+ //This indicates that there are no more stored frames.
+ if (nVerticesTotal == 0)
+ break;
+
+ List lFrameRGB = new List();
+ List lFrameVerts = new List();
+
+ SetStatusBarOnTimer("Saving frame " + (nFrames).ToString() + ".", 5000);
+ for (int i = 0; i < lFrameRGBAllDevices.Count; i++)
+ {
+ lFrameRGB.AddRange(lFrameRGBAllDevices[i]);
+ lFrameVerts.AddRange(lFrameVertsAllDevices[i]);
+
+ //This is ran if the frames from each client are to be placed in separate files.
+ if (!oSettings.bMergeScansForSave)
+ {
+ string outputFilename = outDir + "\\" + nFrames.ToString().PadLeft(5, '0') + i.ToString() + ".ply";
+ saveToPly(outputFilename, lFrameVertsAllDevices[i], lFrameRGBAllDevices[i]);
+ }
+ }
+
+ //This is ran if the frames from all clients are to be placed in a single file.
+ if (oSettings.bMergeScansForSave)
+ {
+ string outputFilename = outDir + "\\" + nFrames.ToString().PadLeft(5, '0') + ".ply";
+ saveToPly(outputFilename, lFrameVerts, lFrameRGB);
+ }
+ }
+ }
+
+ private void savingWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ oServer.ClearStoredFrames();
+ bSaving = false;
+
+ //If the live view window was open, we need to restart the UpdateWorker.
+ if (bLiveViewRunning)
+ RestartUpdateWorker();
+
+ btRecord.Enabled = true;
+ btRecord.Text = "Start recording";
+ btRefineCalib.Enabled = true;
+ btCalibrate.Enabled = true;
+ }
+
+ //Continually requests frames that will be displayed in the live view window.
+ private void updateWorker_DoWork(object sender, DoWorkEventArgs e)
+ {
+ List> lFramesRGB = new List>();
+ List> lFramesVerts = new List>();
+
+ BackgroundWorker worker = (BackgroundWorker)sender;
+ while (!worker.CancellationPending)
+ {
+ Thread.Sleep(1);
+ oServer.GetLatestFrame(lFramesRGB, lFramesVerts);
+
+ //Update the vertex and color lists that are common between this class and the OpenGLWindow.
+ lock (lAllVertices)
+ {
+ lAllVertices.Clear();
+ lAllColors.Clear();
+ lAllCameraPoses.Clear();
+
+ for (int i = 0; i < lFramesRGB.Count; i++)
+ {
+ lAllVertices.AddRange(lFramesVerts[i]);
+ lAllColors.AddRange(lFramesRGB[i]);
+ lAllCameraPoses.Add(oServer.lCameraPoses[i]);
+ }
+ }
+
+ //Notes the fact that a new frame was downloaded, this is used to estimate the FPS.
+ if (oOpenGLWindow != null)
+ oOpenGLWindow.CloudUpdateTick();
+ }
+ }
+
+ //Performs the ICP based pose refinement.
+ private void refineWorker_DoWork(object sender, DoWorkEventArgs e)
+ {
+ if (oServer.bAllCalibrated == false)
+ {
+ SetStatusBarOnTimer("Not all of the devices are calibrated.", 5000);
+ return;
+ }
+
+ //Download a frame from each client.
+ List> lAllFrameVertices = new List>();
+ List> lAllFrameColors = new List>();
+ oServer.GetLatestFrame(lAllFrameColors, lAllFrameVertices);
+
+ //Initialize containers for the poses.
+ List Rs = new List();
+ List Ts = new List();
+ for (int i = 0; i < lAllFrameVertices.Count; i++)
+ {
+ float[] tempR = new float[9];
+ float[] tempT = new float[3];
+ for (int j = 0; j < 3; j++)
+ {
+ tempT[j] = 0;
+ tempR[j + j * 3] = 1;
+ }
+
+ Rs.Add(tempR);
+ Ts.Add(tempT);
+ }
+
+ //Use ICP to refine the sensor poses.
+ //This part is explained in more detail in our article (name on top of this file).
+ float error = 1;
+ float oldError = 1;
+ bool firstPass = true;
+ int iter = 0;
+ while (true)
+ {
+ if (iter > oSettings.nMaxNumRefineIters)
+ break;
+
+ error = 0;
+ for (int i = 0; i < lAllFrameVertices.Count; i++)
+ {
+ List otherFramesVertices = new List();
+ for (int j = 0; j < lAllFrameVertices.Count; j++)
+ {
+ if (j == i)
+ continue;
+ otherFramesVertices.AddRange(lAllFrameVertices[j]);
+ }
+
+ float[] verts1 = otherFramesVertices.ToArray();
+ float[] verts2 = lAllFrameVertices[i].ToArray();
+
+ IntPtr pVerts1 = Marshal.AllocHGlobal(otherFramesVertices.Count * sizeof(float));
+ IntPtr pVerts2 = Marshal.AllocHGlobal(lAllFrameVertices[i].Count * sizeof(float));
+
+ Marshal.Copy(verts1, 0, pVerts1, verts1.Length);
+ Marshal.Copy(verts2, 0, pVerts2, verts2.Length);
+
+ error += ICP(pVerts1, pVerts2, otherFramesVertices.Count / 3, lAllFrameVertices[i].Count / 3, Rs[i], Ts[i], oSettings.nNumICPIterations);
+
+ Marshal.Copy(pVerts2, verts2, 0, verts2.Length);
+ lAllFrameVertices[i].Clear();
+ lAllFrameVertices[i].AddRange(verts2);
+ }
+
+ if (firstPass)
+ {
+ firstPass = false;
+ }
+ else
+ {
+ if (Math.Abs(oldError - error) / error < 0.01)
+ break;
+ }
+ oldError = error;
+
+ iter++;
+ }
+
+ //Update the calibration data in client machines.
+ List worldTransforms = oServer.lWorldTransforms;
+
+ for (int i = 0; i < worldTransforms.Count; i++)
+ {
+ float[] tempT = new float[3];
+ float[,] tempR = new float[3, 3];
+ for (int j = 0; j < 3; j++)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ tempT[j] += Ts[i][k] * worldTransforms[i].R[k, j];
+ }
+
+ worldTransforms[i].t[j] += tempT[j];
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ for (int l = 0; l < 3; l++)
+ {
+ tempR[j, k] += Rs[i][l * 3 + j] * worldTransforms[i].R[l, k];
+ }
+
+ worldTransforms[i].R[j, k] = tempR[j, k];
+ }
+ }
+ }
+
+ oServer.lWorldTransforms = worldTransforms;
+
+ oServer.SendCalibrationData();
+ }
+
+ private void refineWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ //Re-enable all of the buttons after refinement.
+ btRefineCalib.Enabled = true;
+ btCalibrate.Enabled = true;
+ btRecord.Enabled = true;
+ }
+
+ //This is used for: starting/stopping the recording worker, stopping the saving worker
+ private void btRecord_Click(object sender, EventArgs e)
+ {
+ if (oServer.nClientCount < 1)
+ {
+ SetStatusBarOnTimer("At least one client needs to be connected for recording.", 5000);
+ return;
+ }
+
+ //If we are saving frames right now, this button stops saving.
+ if (bSaving)
+ {
+ btRecord.Enabled = false;
+ savingWorker.CancelAsync();
+ return;
+ }
+
+ bRecording = !bRecording;
+ if (bRecording)
+ {
+ //Stop the update worker to reduce the network usage (provides better synchronization).
+ updateWorker.CancelAsync();
+
+ recordingWorker.RunWorkerAsync();
+ btRecord.Text = "Stop recording";
+ btRefineCalib.Enabled = false;
+ btCalibrate.Enabled = false;
+ }
+ else
+ {
+ btRecord.Enabled = false;
+ recordingWorker.CancelAsync();
+ }
+
+ }
+
+ private void btCalibrate_Click(object sender, EventArgs e)
+ {
+ oServer.Calibrate();
+ }
+
+ private void btRefineCalib_Click(object sender, EventArgs e)
+ {
+ if (oServer.nClientCount < 2)
+ {
+ SetStatusBarOnTimer("To refine calibration you need at least 2 connected devices.", 5000);
+ return;
+ }
+
+ btRefineCalib.Enabled = false;
+ btCalibrate.Enabled = false;
+ btRecord.Enabled = false;
+
+ refineWorker.RunWorkerAsync();
+ }
+
+ private void saveToPly(string filename, List vertices, List colors)
+ {
+ int nVertices = vertices.Count / 3;
+
+ System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
+
+ //PLY file header is written here.
+ file.WriteLine("ply\nformat ascii 1.0");
+ file.WriteLine("element vertex " + nVertices.ToString());
+ file.WriteLine("property float x\nproperty float y\nproperty float z\nproperty uchar red\nproperty uchar green\nproperty uchar blue\nend_header");
+
+ //Vertex and color data are written here.
+ for (int j = 0; j < vertices.Count / 3; j++)
+ {
+ string s = "";
+ for (int k = 0; k < 3; k++) s += vertices[j * 3 + k].ToString(CultureInfo.InvariantCulture) + " ";
+ for (int k = 0; k < 3; k++) s += colors[j * 3 + k].ToString(CultureInfo.InvariantCulture) + " ";
+ file.WriteLine(s);
+ }
+
+ file.Close();
+ }
+
+ void RestartUpdateWorker()
+ {
+ if (!updateWorker.IsBusy)
+ updateWorker.RunWorkerAsync();
+ }
+
+ private void btShowLive_Click(object sender, EventArgs e)
+ {
+ RestartUpdateWorker();
+
+ //Opens the live view window if it is not open yet.
+ if (!OpenGLWorker.IsBusy)
+ OpenGLWorker.RunWorkerAsync();
+ }
+
+ private void SetStatusBarOnTimer(string message, int milliseconds)
+ {
+ statusLabel.Text = message;
+
+ oStatusBarTimer.Stop();
+ oStatusBarTimer = new System.Timers.Timer();
+
+ oStatusBarTimer.Interval = milliseconds;
+ oStatusBarTimer.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ oStatusBarTimer.Stop();
+ statusLabel.Text = "";
+ };
+ oStatusBarTimer.Start();
+ }
+
+ //Updates the ListBox contaning the connected clients, called by events inside KinectServer.
+ private void UpdateListView(List socketList)
+ {
+ List listBoxItems = new List();
+
+ for (int i = 0; i < socketList.Count; i++)
+ listBoxItems.Add(socketList[i].sSocketState);
+
+ lClientListBox.DataSource = listBoxItems;
+ }
+ }
+}
diff --git a/LiveScanServer/MainWindowForm.resx b/LiveScanServer/MainWindowForm.resx
new file mode 100644
index 0000000..7a47fc6
--- /dev/null
+++ b/LiveScanServer/MainWindowForm.resx
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 155, 17
+
+
+ 435, 17
+
+
+ 579, 17
+
+
+ 702, 19
+
+
+ 828, 19
+
+
+ 958, 19
+
+
\ No newline at end of file
diff --git a/LiveScanServer/OpenGLWindow.cs b/LiveScanServer/OpenGLWindow.cs
new file mode 100644
index 0000000..220a086
--- /dev/null
+++ b/LiveScanServer/OpenGLWindow.cs
@@ -0,0 +1,560 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Globalization;
+
+using OpenTK;
+using OpenTK.Graphics;
+using OpenTK.Input;
+
+enum ECameraMode
+{
+ CAMERA_NONE, CAMERA_TRACK, CAMERA_DOLLY, CAMERA_ORBIT
+}
+
+namespace KinectServer
+{
+ class OpenGLWindow : GameWindow
+ {
+ int PointCount;
+ int LineCount;
+
+ VertexC4ubV3f[] VBO;
+ float PointSize = 0.0f;
+ ECameraMode CameraMode = ECameraMode.CAMERA_NONE;
+
+ static float KEYBOARD_MOVE_SPEED = 0.01f;
+
+ static float MOUSE_ORBIT_SPEED = 0.30f; // 0 = SLOWEST, 1 = FASTEST
+ static float MOUSE_DOLLY_SPEED = 0.2f; // same as above...but much more sensitive
+ static float MOUSE_TRACK_SPEED = 0.003f; // same as above...but much more sensitive
+
+ float g_heading;
+ float g_pitch;
+ float dx = 0.0f;
+ float dy = 0.0f;
+
+ Vector2 MousePrevious = new Vector2();
+ Vector2 MouseCurrent = new Vector2();
+ float[] cameraPosition = new float[3];
+ float[] targetPosition = new float[3];
+
+ public List vertices = new List();
+ public List colors = new List();
+ public List cameraPoses = new List();
+ public KinectSettings settings = new KinectSettings();
+
+ DateTime tFPSUpdateTimer = DateTime.Now;
+ int nTickCounter = 0;
+
+ // this struct is used for drawing
+ struct VertexC4ubV3f
+ {
+ public byte R, G, B, A;
+ public Vector3 Position;
+
+ public static int SizeInBytes = 16;
+ }
+
+ uint VBOHandle;
+
+ /// Creates a 800x600 window with the specified title.
+ public OpenGLWindow()
+ : base(800, 600)
+ {
+ this.VSync = VSyncMode.Off;
+ MouseUp += new EventHandler(OnMouseButtonUp);
+ MouseDown += new EventHandler(OnMouseButtonDown);
+ MouseMove += new EventHandler(OnMouseMove);
+ MouseWheel += new EventHandler(OnMouseWheelChanged);
+
+ KeyDown += new EventHandler(OnKeyDown);
+
+ cameraPosition[0] = 0;
+ cameraPosition[1] = 0;
+ cameraPosition[2] = 1.0f;
+ targetPosition[0] = 0;
+ targetPosition[1] = 0;
+ targetPosition[2] = 0;
+ }
+
+ public void CloudUpdateTick()
+ {
+ nTickCounter++;
+ }
+
+ void OnKeyDown(object sender, KeyboardKeyEventArgs e)
+ {
+// e.Key
+ }
+
+ /// Load resources here.
+ /// Not used.
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+
+ Version version = new Version(GL.GetString(StringName.Version).Substring(0, 3));
+ Version target = new Version(1, 5);
+ if (version < target)
+ {
+ throw new NotSupportedException(String.Format(
+ "OpenGL {0} is required (you only have {1}).", target, version));
+ }
+
+ GL.ClearColor(.1f, 0f, .1f, 0f);
+ GL.Enable(EnableCap.DepthTest);
+
+ // Setup parameters for Points
+ GL.PointSize(PointSize);
+ GL.Enable(EnableCap.PointSmooth);
+ GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest);
+
+ // Setup VBO state
+ GL.EnableClientState(EnableCap.ColorArray);
+ GL.EnableClientState(EnableCap.VertexArray);
+
+ GL.GenBuffers(1, out VBOHandle);
+
+ // Since there's only 1 VBO in the app, might aswell setup here.
+ GL.BindBuffer(BufferTarget.ArrayBuffer, VBOHandle);
+ GL.ColorPointer(4, ColorPointerType.UnsignedByte, VertexC4ubV3f.SizeInBytes, (IntPtr)0);
+ GL.VertexPointer(3, VertexPointerType.Float, VertexC4ubV3f.SizeInBytes, (IntPtr)(4 * sizeof(byte)));
+
+ PointCount = 0;
+ LineCount = 12;
+ VBO = new VertexC4ubV3f[PointCount + 2 * LineCount];
+ }
+
+ protected override void OnUnload(EventArgs e)
+ {
+ GL.DeleteBuffers(1, ref VBOHandle);
+ }
+
+ ///
+ /// Called when your window is resized. Set your viewport here. It is also
+ /// a good place to set up your projection matrix (which probably changes
+ /// along when the aspect ratio of your window).
+ ///
+ /// Contains information on the new Width and Size of the GameWindow.
+ protected override void OnResize(EventArgs e)
+ {
+ GL.Viewport(0, 0, Width, Height);
+
+ GL.MatrixMode(MatrixMode.Projection);
+ Matrix4 p = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Width / (float)Height, 0.1f, 50.0f);
+ GL.LoadMatrix(ref p);
+
+ GL.MatrixMode(MatrixMode.Modelview);
+ Matrix4 mv = Matrix4.LookAt(Vector3.UnitZ, Vector3.Zero, Vector3.UnitY);
+ GL.LoadMatrix(ref mv);
+ }
+
+ void OnMouseWheelChanged(object sender, MouseWheelEventArgs e)
+ {
+ dy = e.Delta * MOUSE_DOLLY_SPEED;
+
+ cameraPosition[2] -= dy;
+
+ //if (cameraPosition[2] < 0)
+ // cameraPosition[2] = 0;
+
+ }
+
+ void OnMouseMove(object sender, MouseMoveEventArgs e)
+ {
+ MouseCurrent.X = e.Mouse.X;
+ MouseCurrent.Y = e.Mouse.Y;
+
+ // Now use mouse_delta to move the camera
+
+ switch (CameraMode)
+ {
+ case ECameraMode.CAMERA_TRACK:
+ dx = MouseCurrent.X - MousePrevious.X;
+ dx *= MOUSE_TRACK_SPEED;
+
+ dy = MouseCurrent.Y - MousePrevious.Y;
+ dy *= MOUSE_TRACK_SPEED;
+
+ cameraPosition[0] -= dx;
+ cameraPosition[1] += dy;
+
+ //targetPosition[0] -= dx;
+ //targetPosition[1] += dy;
+
+ break;
+
+ case ECameraMode.CAMERA_DOLLY:
+ dy = MouseCurrent.Y - MousePrevious.Y;
+ dy *= MOUSE_DOLLY_SPEED;
+
+ cameraPosition[2] -= dy;
+
+ // if (cameraPosition[2] < 0)
+ // cameraPosition[2] = 0;
+
+ break;
+
+ case ECameraMode.CAMERA_ORBIT:
+ dx = MouseCurrent.X - MousePrevious.X;
+ dx *= MOUSE_ORBIT_SPEED;
+
+ dy = MouseCurrent.Y - MousePrevious.Y;
+ dy *= MOUSE_ORBIT_SPEED;
+
+ g_heading += dx;
+ g_pitch += dy;
+
+ break;
+ }
+ MousePrevious.X = MouseCurrent.X;
+ MousePrevious.Y = MouseCurrent.Y;
+ }
+
+ void OnMouseButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ CameraMode = ECameraMode.CAMERA_NONE;
+ }
+
+ void OnMouseButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ switch (e.Button)
+ {
+ case MouseButton.Left:
+ CameraMode = ECameraMode.CAMERA_ORBIT;
+ break;
+ case MouseButton.Middle:
+ CameraMode = ECameraMode.CAMERA_DOLLY;
+ break;
+ case MouseButton.Right:
+ CameraMode = ECameraMode.CAMERA_TRACK;
+ break;
+ }
+ MousePrevious.X = Mouse.X;
+ MousePrevious.Y = Mouse.Y;
+ }
+
+ protected override void OnUpdateFrame(FrameEventArgs e)
+ {
+ if ((DateTime.Now - tFPSUpdateTimer).Seconds >= 1)
+ {
+ double FPS = nTickCounter / (DateTime.Now - tFPSUpdateTimer).TotalSeconds;
+ this.Title = "FPS: " + string.Format("{0:F}", FPS);
+
+ tFPSUpdateTimer = DateTime.Now;
+ nTickCounter = 0;
+ }
+
+ var keyboard = OpenTK.Input.Keyboard.GetState();
+ if (keyboard[Key.Escape])
+ {
+ Exit();
+ }
+ if (keyboard[Key.Plus])
+ {
+ PointSize += 0.1f;
+ GL.PointSize(PointSize);
+ }
+ if (keyboard[Key.Minus])
+ {
+ if (PointSize != 0)
+ PointSize -= 0.1f;
+ GL.PointSize(PointSize);
+ }
+ if (keyboard[Key.W])
+ cameraPosition[2] -= KEYBOARD_MOVE_SPEED;
+ if (keyboard[Key.A])
+ cameraPosition[0] -= KEYBOARD_MOVE_SPEED;
+ if (keyboard[Key.S])
+ cameraPosition[2] += KEYBOARD_MOVE_SPEED;
+ if (keyboard[Key.D])
+ cameraPosition[0] += KEYBOARD_MOVE_SPEED;
+
+ lock (vertices)
+ {
+ lock (settings)
+ {
+ PointCount = vertices.Count / 3;
+ //bounding box
+ LineCount = 12;
+ //markers
+ LineCount += settings.lMarkerPoses.Count * 3;
+ //cameras
+ LineCount += cameraPoses.Count * 3;
+
+ VBO = new VertexC4ubV3f[PointCount + 2 * LineCount];
+
+ for (int i = 0; i < PointCount; i++)
+ {
+ VBO[i].R = (byte)colors[i * 3];
+ VBO[i].G = (byte)colors[i * 3 + 1];
+ VBO[i].B = (byte)colors[i * 3 + 2];
+ VBO[i].A = 255;
+ VBO[i].Position.X = vertices[i * 3];
+ VBO[i].Position.Y = vertices[i * 3 + 1];
+ VBO[i].Position.Z = vertices[i * 3 + 2];
+ }
+
+ int iCurLineCount = 0;
+ iCurLineCount += AddBoundingBox(PointCount + 2 * iCurLineCount);
+ for (int i = 0; i < settings.lMarkerPoses.Count; i++)
+ {
+ iCurLineCount += AddMarker(PointCount + 2 * iCurLineCount, settings.lMarkerPoses[i].pose);
+ }
+ for (int i = 0; i < cameraPoses.Count; i++)
+ {
+ iCurLineCount += AddCamera(PointCount + 2 * iCurLineCount, cameraPoses[i]);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Called when it is time to render the next frame. Add your rendering code here.
+ ///
+ /// Contains timing information.
+ protected override void OnRenderFrame(FrameEventArgs e)
+ {
+ GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+
+ GL.PushMatrix();
+
+ GL.MatrixMode(MatrixMode.Modelview);
+ GL.Translate(-cameraPosition[0], -cameraPosition[1], -cameraPosition[2]);
+ GL.Rotate(g_pitch, 1.0f, 0.0f, 0.0f);
+ GL.Rotate(g_heading, 0.0f, 1.0f, 0.0f);
+
+ // Tell OpenGL to discard old VBO when done drawing it and reserve memory _now_ for a new buffer.
+ // without this, GL would wait until draw operations on old VBO are complete before writing to it
+ GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(VertexC4ubV3f.SizeInBytes * (PointCount + 2 * LineCount)), IntPtr.Zero, BufferUsageHint.StreamDraw);
+ // Fill newly allocated buffer
+ GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(VertexC4ubV3f.SizeInBytes * (PointCount + 2 * LineCount)), VBO, BufferUsageHint.StreamDraw);
+
+ GL.DrawArrays(BeginMode.Points, 0, PointCount);
+ GL.DrawArrays(BeginMode.Lines, PointCount, 2 * LineCount);
+
+ GL.PopMatrix();
+
+ SwapBuffers();
+ }
+
+ private int AddBoundingBox(int startIdx)
+ {
+ int nLinesBeingAdded = 12;
+ //2 points per line
+ int nPointsToAdd = 2 * nLinesBeingAdded;
+
+ for (int i = startIdx; i < startIdx + nPointsToAdd; i++)
+ {
+ VBO[i].R = 255;
+ VBO[i].G = 255;
+ VBO[i].B = 0;
+ VBO[i].A = 0;
+ }
+
+ int n = 0;
+
+ //bottom vertices
+ //first vertex
+ AddLine(startIdx + n, settings.aMinBounds[0], settings.aMinBounds[1], settings.aMinBounds[2],
+ settings.aMaxBounds[0], settings.aMinBounds[1], settings.aMinBounds[2]);
+ n += 2;
+ AddLine(startIdx + n, settings.aMinBounds[0], settings.aMinBounds[1], settings.aMinBounds[2],
+ settings.aMinBounds[0], settings.aMaxBounds[1], settings.aMinBounds[2]);
+ n += 2;
+ AddLine(startIdx + n, settings.aMinBounds[0], settings.aMinBounds[1], settings.aMinBounds[2],
+ settings.aMinBounds[0], settings.aMinBounds[1], settings.aMaxBounds[2]);
+ n += 2;
+
+ //second vertex
+ AddLine(startIdx + n, settings.aMaxBounds[0], settings.aMinBounds[1], settings.aMinBounds[2],
+ settings.aMaxBounds[0], settings.aMaxBounds[1], settings.aMinBounds[2]);
+ n += 2;
+ AddLine(startIdx + n, settings.aMaxBounds[0], settings.aMinBounds[1], settings.aMinBounds[2],
+ settings.aMaxBounds[0], settings.aMinBounds[1], settings.aMaxBounds[2]);
+ n += 2;
+
+ //third vertex
+ AddLine(startIdx + n, settings.aMaxBounds[0], settings.aMinBounds[1], settings.aMaxBounds[2],
+ settings.aMaxBounds[0], settings.aMaxBounds[1], settings.aMaxBounds[2]);
+ n += 2;
+ AddLine(startIdx + n, settings.aMaxBounds[0], settings.aMinBounds[1], settings.aMaxBounds[2],
+ settings.aMinBounds[0], settings.aMinBounds[1], settings.aMaxBounds[2]);
+ n += 2;
+
+ //fourth vertex
+ AddLine(startIdx + n, settings.aMinBounds[0], settings.aMinBounds[1], settings.aMaxBounds[2],
+ settings.aMinBounds[0], settings.aMaxBounds[1], settings.aMaxBounds[2]);
+ n += 2;
+
+ //top vertices
+ //fifth vertex
+ AddLine(startIdx + n, settings.aMinBounds[0], settings.aMaxBounds[1], settings.aMinBounds[2],
+ settings.aMaxBounds[0], settings.aMaxBounds[1], settings.aMinBounds[2]);
+ n += 2;
+ AddLine(startIdx + n, settings.aMinBounds[0], settings.aMaxBounds[1], settings.aMinBounds[2],
+ settings.aMinBounds[0], settings.aMaxBounds[1], settings.aMaxBounds[2]);
+ n += 2;
+
+ //sixth vertex
+ AddLine(startIdx + n, settings.aMaxBounds[0], settings.aMaxBounds[1], settings.aMaxBounds[2],
+ settings.aMaxBounds[0], settings.aMaxBounds[1], settings.aMinBounds[2]);
+ n += 2;
+ AddLine(startIdx + n, settings.aMaxBounds[0], settings.aMaxBounds[1], settings.aMaxBounds[2],
+ settings.aMinBounds[0], settings.aMaxBounds[1], settings.aMaxBounds[2]);
+ n += 2;
+
+ return nLinesBeingAdded;
+ }
+
+ private int AddMarker(int startIdx, AffineTransform pose)
+ {
+ int nLinesBeingAdded = 3;
+ //2 points per line
+ int nPointsToAdd = 2 * nLinesBeingAdded;
+
+ for (int i = startIdx; i < startIdx + nPointsToAdd; i++)
+ {
+ VBO[i].R = 255;
+ VBO[i].G = 0;
+ VBO[i].B = 0;
+ VBO[i].A = 0;
+ }
+
+ int n = 0;
+
+ float x0 = pose.t[0];
+ float y0 = pose.t[1];
+ float z0 = pose.t[2];
+
+ float x1 = 0.1f;
+ float y1 = 0.1f;
+ float z1 = 0.1f;
+
+ float x2 = pose.R[0, 0] * x1;
+ float y2 = pose.R[1, 0] * x1;
+ float z2 = pose.R[2, 0] * x1;
+
+ x2 += pose.t[0];
+ y2 += pose.t[1];
+ z2 += pose.t[2];
+
+ AddLine(startIdx + n, x0, y0, z0, x2, y2, z2);
+ n += 2;
+
+ x2 = pose.R[0, 1] * y1;
+ y2 = pose.R[1, 1] * y1;
+ z2 = pose.R[2, 1] * y1;
+
+ x2 += pose.t[0];
+ y2 += pose.t[1];
+ z2 += pose.t[2];
+
+ AddLine(startIdx + n, x0, y0, z0, x2, y2, z2);
+ n += 2;
+
+ x2 = pose.R[0, 2] * z1;
+ y2 = pose.R[1, 2] * z1;
+ z2 = pose.R[2, 2] * z1;
+
+ x2 += pose.t[0];
+ y2 += pose.t[1];
+ z2 += pose.t[2];
+
+ AddLine(startIdx + n, x0, y0, z0, x2, y2, z2);
+ n += 2;
+
+ return nLinesBeingAdded;
+ }
+
+ private int AddCamera(int startIdx, AffineTransform pose)
+ {
+ int nLinesBeingAdded = 3;
+ //2 points per line
+ int nPointsToAdd = 2 * nLinesBeingAdded;
+
+ for (int i = startIdx; i < startIdx + nPointsToAdd; i++)
+ {
+ VBO[i].R = 0;
+ VBO[i].G = 255;
+ VBO[i].B = 0;
+ VBO[i].A = 0;
+ }
+
+ int n = 0;
+
+ float x0 = pose.t[0];
+ float y0 = pose.t[1];
+ float z0 = pose.t[2];
+
+ float x1 = 0.1f;
+ float y1 = 0.1f;
+ float z1 = 0.1f;
+
+ float x2 = pose.R[0, 0] * x1;
+ float y2 = pose.R[1, 0] * x1;
+ float z2 = pose.R[2, 0] * x1;
+
+ x2 += pose.t[0];
+ y2 += pose.t[1];
+ z2 += pose.t[2];
+
+ AddLine(startIdx + n, x0, y0, z0, x2, y2, z2);
+ n += 2;
+
+ x2 = pose.R[0, 1] * y1;
+ y2 = pose.R[1, 1] * y1;
+ z2 = pose.R[2, 1] * y1;
+
+ x2 += pose.t[0];
+ y2 += pose.t[1];
+ z2 += pose.t[2];
+
+ AddLine(startIdx + n, x0, y0, z0, x2, y2, z2);
+ n += 2;
+
+ x2 = pose.R[0, 2] * z1;
+ y2 = pose.R[1, 2] * z1;
+ z2 = pose.R[2, 2] * z1;
+
+ x2 += pose.t[0];
+ y2 += pose.t[1];
+ z2 += pose.t[2];
+
+ AddLine(startIdx + n, x0, y0, z0, x2, y2, z2);
+ n += 2;
+
+ return nLinesBeingAdded;
+ }
+
+ private void AddLine(int startIdx, float x0, float y0, float z0,
+ float x1, float y1, float z1)
+ {
+ VBO[startIdx].Position.X = x0;
+ VBO[startIdx].Position.Y = y0;
+ VBO[startIdx].Position.Z = z0;
+
+ VBO[startIdx + 1].Position.X = x1;
+ VBO[startIdx + 1].Position.Y = y1;
+ VBO[startIdx + 1].Position.Z = z1;
+ }
+ }
+}
+
diff --git a/LiveScanServer/Program.cs b/LiveScanServer/Program.cs
new file mode 100644
index 0000000..83cd404
--- /dev/null
+++ b/LiveScanServer/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace KinectServer
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainWindowForm());
+ }
+ }
+}
diff --git a/LiveScanServer/Properties/AssemblyInfo.cs b/LiveScanServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b0f18a5
--- /dev/null
+++ b/LiveScanServer/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("KinectServer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("KinectServer")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c781e249-f1ed-41af-89ab-4dbc1dde8bfd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/LiveScanServer/Properties/Resources.Designer.cs b/LiveScanServer/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..29cf13a
--- /dev/null
+++ b/LiveScanServer/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.34014
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace KinectServer.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KinectServer.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/LiveScanServer/Properties/Resources.resx b/LiveScanServer/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/LiveScanServer/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/LiveScanServer/Properties/Settings.Designer.cs b/LiveScanServer/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..c3dfe52
--- /dev/null
+++ b/LiveScanServer/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.34014
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace KinectServer.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/LiveScanServer/Properties/Settings.settings b/LiveScanServer/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/LiveScanServer/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/LiveScanServer/SettingsForm.Designer.cs b/LiveScanServer/SettingsForm.Designer.cs
new file mode 100644
index 0000000..5741ce5
--- /dev/null
+++ b/LiveScanServer/SettingsForm.Designer.cs
@@ -0,0 +1,569 @@
+namespace KinectServer
+{
+ partial class SettingsForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.lbMerge = new System.Windows.Forms.Label();
+ this.chMerge = new System.Windows.Forms.CheckBox();
+ this.lbICPIters = new System.Windows.Forms.Label();
+ this.txtICPIters = new System.Windows.Forms.TextBox();
+ this.grClient = new System.Windows.Forms.GroupBox();
+ this.grMarkers = new System.Windows.Forms.GroupBox();
+ this.lbX2 = new System.Windows.Forms.Label();
+ this.btRemove = new System.Windows.Forms.Button();
+ this.txtOrientationZ = new System.Windows.Forms.TextBox();
+ this.txtId = new System.Windows.Forms.TextBox();
+ this.lbY2 = new System.Windows.Forms.Label();
+ this.txtOrientationY = new System.Windows.Forms.TextBox();
+ this.lbId = new System.Windows.Forms.Label();
+ this.lbZ2 = new System.Windows.Forms.Label();
+ this.txtOrientationX = new System.Windows.Forms.TextBox();
+ this.btAdd = new System.Windows.Forms.Button();
+ this.lbTranslation = new System.Windows.Forms.Label();
+ this.lbOrientation = new System.Windows.Forms.Label();
+ this.txtTranslationZ = new System.Windows.Forms.TextBox();
+ this.txtTranslationX = new System.Windows.Forms.TextBox();
+ this.lisMarkers = new System.Windows.Forms.ListBox();
+ this.txtTranslationY = new System.Windows.Forms.TextBox();
+ this.grBounding = new System.Windows.Forms.GroupBox();
+ this.lbMin = new System.Windows.Forms.Label();
+ this.txtMaxZ = new System.Windows.Forms.TextBox();
+ this.txtMaxY = new System.Windows.Forms.TextBox();
+ this.txtMinX = new System.Windows.Forms.TextBox();
+ this.txtMaxX = new System.Windows.Forms.TextBox();
+ this.txtMinY = new System.Windows.Forms.TextBox();
+ this.lbMax = new System.Windows.Forms.Label();
+ this.txtMinZ = new System.Windows.Forms.TextBox();
+ this.lbZ = new System.Windows.Forms.Label();
+ this.lbY = new System.Windows.Forms.Label();
+ this.lbX = new System.Windows.Forms.Label();
+ this.grFiltering = new System.Windows.Forms.GroupBox();
+ this.txtFilterNeighbors = new System.Windows.Forms.TextBox();
+ this.chFilter = new System.Windows.Forms.CheckBox();
+ this.lbFilterNeighbors = new System.Windows.Forms.Label();
+ this.lbFilterDistance = new System.Windows.Forms.Label();
+ this.txtFilterDistance = new System.Windows.Forms.TextBox();
+ this.grServer = new System.Windows.Forms.GroupBox();
+ this.txtRefinIters = new System.Windows.Forms.TextBox();
+ this.lbOuterIters = new System.Windows.Forms.Label();
+ this.grClient.SuspendLayout();
+ this.grMarkers.SuspendLayout();
+ this.grBounding.SuspendLayout();
+ this.grFiltering.SuspendLayout();
+ this.grServer.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // lbMerge
+ //
+ this.lbMerge.AutoSize = true;
+ this.lbMerge.Location = new System.Drawing.Point(6, 49);
+ this.lbMerge.Name = "lbMerge";
+ this.lbMerge.Size = new System.Drawing.Size(69, 13);
+ this.lbMerge.TabIndex = 22;
+ this.lbMerge.Text = "Scan saving:";
+ //
+ // chMerge
+ //
+ this.chMerge.AutoSize = true;
+ this.chMerge.Location = new System.Drawing.Point(91, 48);
+ this.chMerge.Name = "chMerge";
+ this.chMerge.Size = new System.Drawing.Size(86, 17);
+ this.chMerge.TabIndex = 23;
+ this.chMerge.Text = "merge scans";
+ this.chMerge.UseVisualStyleBackColor = true;
+ this.chMerge.CheckedChanged += new System.EventHandler(this.chMerge_CheckedChanged);
+ //
+ // lbICPIters
+ //
+ this.lbICPIters.AutoSize = true;
+ this.lbICPIters.Location = new System.Drawing.Point(6, 26);
+ this.lbICPIters.Name = "lbICPIters";
+ this.lbICPIters.Size = new System.Drawing.Size(86, 13);
+ this.lbICPIters.TabIndex = 24;
+ this.lbICPIters.Text = "Num of ICP iters:";
+ //
+ // txtICPIters
+ //
+ this.txtICPIters.Location = new System.Drawing.Point(91, 23);
+ this.txtICPIters.Name = "txtICPIters";
+ this.txtICPIters.Size = new System.Drawing.Size(38, 20);
+ this.txtICPIters.TabIndex = 25;
+ this.txtICPIters.TextChanged += new System.EventHandler(this.txtICPIters_TextChanged);
+ //
+ // grClient
+ //
+ this.grClient.Controls.Add(this.grMarkers);
+ this.grClient.Controls.Add(this.grBounding);
+ this.grClient.Controls.Add(this.grFiltering);
+ this.grClient.Location = new System.Drawing.Point(12, 12);
+ this.grClient.Name = "grClient";
+ this.grClient.Size = new System.Drawing.Size(632, 212);
+ this.grClient.TabIndex = 43;
+ this.grClient.TabStop = false;
+ this.grClient.Text = "KinectClient settings";
+ //
+ // grMarkers
+ //
+ this.grMarkers.Controls.Add(this.lbX2);
+ this.grMarkers.Controls.Add(this.btRemove);
+ this.grMarkers.Controls.Add(this.txtOrientationZ);
+ this.grMarkers.Controls.Add(this.txtId);
+ this.grMarkers.Controls.Add(this.lbY2);
+ this.grMarkers.Controls.Add(this.txtOrientationY);
+ this.grMarkers.Controls.Add(this.lbId);
+ this.grMarkers.Controls.Add(this.lbZ2);
+ this.grMarkers.Controls.Add(this.txtOrientationX);
+ this.grMarkers.Controls.Add(this.btAdd);
+ this.grMarkers.Controls.Add(this.lbTranslation);
+ this.grMarkers.Controls.Add(this.lbOrientation);
+ this.grMarkers.Controls.Add(this.txtTranslationZ);
+ this.grMarkers.Controls.Add(this.txtTranslationX);
+ this.grMarkers.Controls.Add(this.lisMarkers);
+ this.grMarkers.Controls.Add(this.txtTranslationY);
+ this.grMarkers.Location = new System.Drawing.Point(271, 19);
+ this.grMarkers.Name = "grMarkers";
+ this.grMarkers.Size = new System.Drawing.Size(353, 185);
+ this.grMarkers.TabIndex = 45;
+ this.grMarkers.TabStop = false;
+ this.grMarkers.Text = "Calibration markers";
+ //
+ // lbX2
+ //
+ this.lbX2.AutoSize = true;
+ this.lbX2.Location = new System.Drawing.Point(230, 19);
+ this.lbX2.Name = "lbX2";
+ this.lbX2.Size = new System.Drawing.Size(14, 13);
+ this.lbX2.TabIndex = 49;
+ this.lbX2.Text = "X";
+ //
+ // btRemove
+ //
+ this.btRemove.Location = new System.Drawing.Point(233, 127);
+ this.btRemove.Name = "btRemove";
+ this.btRemove.Size = new System.Drawing.Size(92, 23);
+ this.btRemove.TabIndex = 59;
+ this.btRemove.Text = "Remove marker";
+ this.btRemove.UseVisualStyleBackColor = true;
+ this.btRemove.Click += new System.EventHandler(this.btRemove_Click);
+ //
+ // txtOrientationZ
+ //
+ this.txtOrientationZ.Location = new System.Drawing.Point(305, 38);
+ this.txtOrientationZ.Name = "txtOrientationZ";
+ this.txtOrientationZ.Size = new System.Drawing.Size(38, 20);
+ this.txtOrientationZ.TabIndex = 48;
+ this.txtOrientationZ.TextChanged += new System.EventHandler(this.txtOrientationZ_TextChanged);
+ //
+ // txtId
+ //
+ this.txtId.Location = new System.Drawing.Point(217, 93);
+ this.txtId.Name = "txtId";
+ this.txtId.Size = new System.Drawing.Size(38, 20);
+ this.txtId.TabIndex = 58;
+ this.txtId.TextChanged += new System.EventHandler(this.txtId_TextChanged);
+ //
+ // lbY2
+ //
+ this.lbY2.AutoSize = true;
+ this.lbY2.Location = new System.Drawing.Point(274, 19);
+ this.lbY2.Name = "lbY2";
+ this.lbY2.Size = new System.Drawing.Size(14, 13);
+ this.lbY2.TabIndex = 50;
+ this.lbY2.Text = "Y";
+ //
+ // txtOrientationY
+ //
+ this.txtOrientationY.Location = new System.Drawing.Point(261, 38);
+ this.txtOrientationY.Name = "txtOrientationY";
+ this.txtOrientationY.Size = new System.Drawing.Size(38, 20);
+ this.txtOrientationY.TabIndex = 47;
+ this.txtOrientationY.TextChanged += new System.EventHandler(this.txtOrientationY_TextChanged);
+ //
+ // lbId
+ //
+ this.lbId.AutoSize = true;
+ this.lbId.Location = new System.Drawing.Point(132, 96);
+ this.lbId.Name = "lbId";
+ this.lbId.Size = new System.Drawing.Size(54, 13);
+ this.lbId.TabIndex = 57;
+ this.lbId.Text = "Marker id:";
+ //
+ // lbZ2
+ //
+ this.lbZ2.AutoSize = true;
+ this.lbZ2.Location = new System.Drawing.Point(317, 19);
+ this.lbZ2.Name = "lbZ2";
+ this.lbZ2.Size = new System.Drawing.Size(14, 13);
+ this.lbZ2.TabIndex = 51;
+ this.lbZ2.Text = "Z";
+ //
+ // txtOrientationX
+ //
+ this.txtOrientationX.Location = new System.Drawing.Point(217, 38);
+ this.txtOrientationX.Name = "txtOrientationX";
+ this.txtOrientationX.Size = new System.Drawing.Size(38, 20);
+ this.txtOrientationX.TabIndex = 46;
+ this.txtOrientationX.TextChanged += new System.EventHandler(this.txtOrientationX_TextChanged);
+ //
+ // btAdd
+ //
+ this.btAdd.Location = new System.Drawing.Point(135, 127);
+ this.btAdd.Name = "btAdd";
+ this.btAdd.Size = new System.Drawing.Size(92, 23);
+ this.btAdd.TabIndex = 56;
+ this.btAdd.Text = "Add marker";
+ this.btAdd.UseVisualStyleBackColor = true;
+ this.btAdd.Click += new System.EventHandler(this.btAdd_Click);
+ //
+ // lbTranslation
+ //
+ this.lbTranslation.AutoSize = true;
+ this.lbTranslation.Location = new System.Drawing.Point(132, 68);
+ this.lbTranslation.Name = "lbTranslation";
+ this.lbTranslation.Size = new System.Drawing.Size(62, 13);
+ this.lbTranslation.TabIndex = 52;
+ this.lbTranslation.Text = "Translation:";
+ //
+ // lbOrientation
+ //
+ this.lbOrientation.AutoSize = true;
+ this.lbOrientation.Location = new System.Drawing.Point(132, 41);
+ this.lbOrientation.Name = "lbOrientation";
+ this.lbOrientation.Size = new System.Drawing.Size(61, 13);
+ this.lbOrientation.TabIndex = 45;
+ this.lbOrientation.Text = "Orientation:";
+ //
+ // txtTranslationZ
+ //
+ this.txtTranslationZ.Location = new System.Drawing.Point(305, 65);
+ this.txtTranslationZ.Name = "txtTranslationZ";
+ this.txtTranslationZ.Size = new System.Drawing.Size(38, 20);
+ this.txtTranslationZ.TabIndex = 55;
+ this.txtTranslationZ.TextChanged += new System.EventHandler(this.txtTranslationZ_TextChanged);
+ //
+ // txtTranslationX
+ //
+ this.txtTranslationX.Location = new System.Drawing.Point(217, 65);
+ this.txtTranslationX.Name = "txtTranslationX";
+ this.txtTranslationX.Size = new System.Drawing.Size(38, 20);
+ this.txtTranslationX.TabIndex = 53;
+ this.txtTranslationX.TextChanged += new System.EventHandler(this.txtTranslationX_TextChanged);
+ //
+ // lisMarkers
+ //
+ this.lisMarkers.FormattingEnabled = true;
+ this.lisMarkers.Location = new System.Drawing.Point(6, 41);
+ this.lisMarkers.Name = "lisMarkers";
+ this.lisMarkers.Size = new System.Drawing.Size(120, 108);
+ this.lisMarkers.TabIndex = 43;
+ //
+ // txtTranslationY
+ //
+ this.txtTranslationY.Location = new System.Drawing.Point(261, 65);
+ this.txtTranslationY.Name = "txtTranslationY";
+ this.txtTranslationY.Size = new System.Drawing.Size(38, 20);
+ this.txtTranslationY.TabIndex = 54;
+ this.txtTranslationY.TextChanged += new System.EventHandler(this.txtTranslationY_TextChanged);
+ //
+ // grBounding
+ //
+ this.grBounding.Controls.Add(this.lbMin);
+ this.grBounding.Controls.Add(this.txtMaxZ);
+ this.grBounding.Controls.Add(this.txtMaxY);
+ this.grBounding.Controls.Add(this.txtMinX);
+ this.grBounding.Controls.Add(this.txtMaxX);
+ this.grBounding.Controls.Add(this.txtMinY);
+ this.grBounding.Controls.Add(this.lbMax);
+ this.grBounding.Controls.Add(this.txtMinZ);
+ this.grBounding.Controls.Add(this.lbZ);
+ this.grBounding.Controls.Add(this.lbY);
+ this.grBounding.Controls.Add(this.lbX);
+ this.grBounding.Location = new System.Drawing.Point(9, 19);
+ this.grBounding.Name = "grBounding";
+ this.grBounding.Size = new System.Drawing.Size(249, 91);
+ this.grBounding.TabIndex = 46;
+ this.grBounding.TabStop = false;
+ this.grBounding.Text = "Bounding box";
+ //
+ // lbMin
+ //
+ this.lbMin.AutoSize = true;
+ this.lbMin.Location = new System.Drawing.Point(8, 38);
+ this.lbMin.Name = "lbMin";
+ this.lbMin.Size = new System.Drawing.Size(65, 13);
+ this.lbMin.TabIndex = 13;
+ this.lbMin.Text = "Min bounds:";
+ //
+ // txtMaxZ
+ //
+ this.txtMaxZ.Location = new System.Drawing.Point(181, 62);
+ this.txtMaxZ.Name = "txtMaxZ";
+ this.txtMaxZ.Size = new System.Drawing.Size(38, 20);
+ this.txtMaxZ.TabIndex = 23;
+ this.txtMaxZ.TextChanged += new System.EventHandler(this.txtMaxZ_TextChanged);
+ //
+ // txtMaxY
+ //
+ this.txtMaxY.Location = new System.Drawing.Point(137, 62);
+ this.txtMaxY.Name = "txtMaxY";
+ this.txtMaxY.Size = new System.Drawing.Size(38, 20);
+ this.txtMaxY.TabIndex = 22;
+ this.txtMaxY.TextChanged += new System.EventHandler(this.txtMaxY_TextChanged);
+ //
+ // txtMinX
+ //
+ this.txtMinX.Location = new System.Drawing.Point(93, 35);
+ this.txtMinX.Name = "txtMinX";
+ this.txtMinX.Size = new System.Drawing.Size(38, 20);
+ this.txtMinX.TabIndex = 14;
+ this.txtMinX.TextChanged += new System.EventHandler(this.txtMinX_TextChanged);
+ //
+ // txtMaxX
+ //
+ this.txtMaxX.Location = new System.Drawing.Point(93, 62);
+ this.txtMaxX.Name = "txtMaxX";
+ this.txtMaxX.Size = new System.Drawing.Size(38, 20);
+ this.txtMaxX.TabIndex = 21;
+ this.txtMaxX.TextChanged += new System.EventHandler(this.txtMaxX_TextChanged);
+ //
+ // txtMinY
+ //
+ this.txtMinY.Location = new System.Drawing.Point(137, 35);
+ this.txtMinY.Name = "txtMinY";
+ this.txtMinY.Size = new System.Drawing.Size(38, 20);
+ this.txtMinY.TabIndex = 15;
+ this.txtMinY.TextChanged += new System.EventHandler(this.txtMinY_TextChanged);
+ //
+ // lbMax
+ //
+ this.lbMax.AutoSize = true;
+ this.lbMax.Location = new System.Drawing.Point(8, 65);
+ this.lbMax.Name = "lbMax";
+ this.lbMax.Size = new System.Drawing.Size(68, 13);
+ this.lbMax.TabIndex = 20;
+ this.lbMax.Text = "Max bounds:";
+ //
+ // txtMinZ
+ //
+ this.txtMinZ.Location = new System.Drawing.Point(181, 35);
+ this.txtMinZ.Name = "txtMinZ";
+ this.txtMinZ.Size = new System.Drawing.Size(38, 20);
+ this.txtMinZ.TabIndex = 16;
+ this.txtMinZ.TextChanged += new System.EventHandler(this.txtMinZ_TextChanged);
+ //
+ // lbZ
+ //
+ this.lbZ.AutoSize = true;
+ this.lbZ.Location = new System.Drawing.Point(193, 16);
+ this.lbZ.Name = "lbZ";
+ this.lbZ.Size = new System.Drawing.Size(14, 13);
+ this.lbZ.TabIndex = 19;
+ this.lbZ.Text = "Z";
+ //
+ // lbY
+ //
+ this.lbY.AutoSize = true;
+ this.lbY.Location = new System.Drawing.Point(150, 16);
+ this.lbY.Name = "lbY";
+ this.lbY.Size = new System.Drawing.Size(14, 13);
+ this.lbY.TabIndex = 18;
+ this.lbY.Text = "Y";
+ //
+ // lbX
+ //
+ this.lbX.AutoSize = true;
+ this.lbX.Location = new System.Drawing.Point(106, 16);
+ this.lbX.Name = "lbX";
+ this.lbX.Size = new System.Drawing.Size(14, 13);
+ this.lbX.TabIndex = 17;
+ this.lbX.Text = "X";
+ //
+ // grFiltering
+ //
+ this.grFiltering.Controls.Add(this.txtFilterNeighbors);
+ this.grFiltering.Controls.Add(this.chFilter);
+ this.grFiltering.Controls.Add(this.lbFilterNeighbors);
+ this.grFiltering.Controls.Add(this.lbFilterDistance);
+ this.grFiltering.Controls.Add(this.txtFilterDistance);
+ this.grFiltering.Location = new System.Drawing.Point(9, 116);
+ this.grFiltering.Name = "grFiltering";
+ this.grFiltering.Size = new System.Drawing.Size(249, 88);
+ this.grFiltering.TabIndex = 45;
+ this.grFiltering.TabStop = false;
+ this.grFiltering.Text = "Filtering";
+ //
+ // txtFilterNeighbors
+ //
+ this.txtFilterNeighbors.Location = new System.Drawing.Point(93, 39);
+ this.txtFilterNeighbors.Name = "txtFilterNeighbors";
+ this.txtFilterNeighbors.Size = new System.Drawing.Size(38, 20);
+ this.txtFilterNeighbors.TabIndex = 20;
+ this.txtFilterNeighbors.TextChanged += new System.EventHandler(this.txtFilterNeighbors_TextChanged);
+ //
+ // chFilter
+ //
+ this.chFilter.AutoSize = true;
+ this.chFilter.Location = new System.Drawing.Point(93, 16);
+ this.chFilter.Name = "chFilter";
+ this.chFilter.Size = new System.Drawing.Size(100, 17);
+ this.chFilter.TabIndex = 18;
+ this.chFilter.Text = "filtering enabled";
+ this.chFilter.UseVisualStyleBackColor = true;
+ this.chFilter.CheckedChanged += new System.EventHandler(this.chFilter_CheckedChanged);
+ //
+ // lbFilterNeighbors
+ //
+ this.lbFilterNeighbors.AutoSize = true;
+ this.lbFilterNeighbors.Location = new System.Drawing.Point(8, 42);
+ this.lbFilterNeighbors.Name = "lbFilterNeighbors";
+ this.lbFilterNeighbors.Size = new System.Drawing.Size(67, 13);
+ this.lbFilterNeighbors.TabIndex = 19;
+ this.lbFilterNeighbors.Text = "N neighbors:";
+ //
+ // lbFilterDistance
+ //
+ this.lbFilterDistance.AutoSize = true;
+ this.lbFilterDistance.Location = new System.Drawing.Point(8, 68);
+ this.lbFilterDistance.Name = "lbFilterDistance";
+ this.lbFilterDistance.Size = new System.Drawing.Size(73, 13);
+ this.lbFilterDistance.TabIndex = 21;
+ this.lbFilterDistance.Text = "Max distance:";
+ //
+ // txtFilterDistance
+ //
+ this.txtFilterDistance.Location = new System.Drawing.Point(93, 65);
+ this.txtFilterDistance.Name = "txtFilterDistance";
+ this.txtFilterDistance.Size = new System.Drawing.Size(38, 20);
+ this.txtFilterDistance.TabIndex = 22;
+ this.txtFilterDistance.TextChanged += new System.EventHandler(this.txtFilterDistance_TextChanged);
+ //
+ // grServer
+ //
+ this.grServer.Controls.Add(this.txtRefinIters);
+ this.grServer.Controls.Add(this.lbOuterIters);
+ this.grServer.Controls.Add(this.lbMerge);
+ this.grServer.Controls.Add(this.txtICPIters);
+ this.grServer.Controls.Add(this.chMerge);
+ this.grServer.Controls.Add(this.lbICPIters);
+ this.grServer.Location = new System.Drawing.Point(12, 230);
+ this.grServer.Name = "grServer";
+ this.grServer.Size = new System.Drawing.Size(632, 78);
+ this.grServer.TabIndex = 44;
+ this.grServer.TabStop = false;
+ this.grServer.Text = "KinectServer settings";
+ //
+ // txtRefinIters
+ //
+ this.txtRefinIters.Location = new System.Drawing.Point(271, 23);
+ this.txtRefinIters.Name = "txtRefinIters";
+ this.txtRefinIters.Size = new System.Drawing.Size(38, 20);
+ this.txtRefinIters.TabIndex = 27;
+ this.txtRefinIters.TextChanged += new System.EventHandler(this.txtRefinIters_TextChanged);
+ //
+ // lbOuterIters
+ //
+ this.lbOuterIters.AutoSize = true;
+ this.lbOuterIters.Location = new System.Drawing.Point(135, 26);
+ this.lbOuterIters.Name = "lbOuterIters";
+ this.lbOuterIters.Size = new System.Drawing.Size(139, 13);
+ this.lbOuterIters.TabIndex = 26;
+ this.lbOuterIters.Text = "Max num of refinement iters:";
+ //
+ // SettingsForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(656, 319);
+ this.Controls.Add(this.grServer);
+ this.Controls.Add(this.grClient);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.MaximizeBox = false;
+ this.Name = "SettingsForm";
+ this.Text = "Settings";
+ this.Load += new System.EventHandler(this.SettingsForm_Load);
+ this.grClient.ResumeLayout(false);
+ this.grMarkers.ResumeLayout(false);
+ this.grMarkers.PerformLayout();
+ this.grBounding.ResumeLayout(false);
+ this.grBounding.PerformLayout();
+ this.grFiltering.ResumeLayout(false);
+ this.grFiltering.PerformLayout();
+ this.grServer.ResumeLayout(false);
+ this.grServer.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label lbMerge;
+ private System.Windows.Forms.CheckBox chMerge;
+ private System.Windows.Forms.Label lbICPIters;
+ private System.Windows.Forms.TextBox txtICPIters;
+ private System.Windows.Forms.GroupBox grClient;
+ private System.Windows.Forms.GroupBox grServer;
+ private System.Windows.Forms.TextBox txtRefinIters;
+ private System.Windows.Forms.Label lbOuterIters;
+ private System.Windows.Forms.GroupBox grFiltering;
+ private System.Windows.Forms.TextBox txtFilterNeighbors;
+ private System.Windows.Forms.CheckBox chFilter;
+ private System.Windows.Forms.Label lbFilterNeighbors;
+ private System.Windows.Forms.Label lbFilterDistance;
+ private System.Windows.Forms.TextBox txtFilterDistance;
+ private System.Windows.Forms.GroupBox grMarkers;
+ private System.Windows.Forms.Label lbX2;
+ private System.Windows.Forms.Button btRemove;
+ private System.Windows.Forms.TextBox txtOrientationZ;
+ private System.Windows.Forms.TextBox txtId;
+ private System.Windows.Forms.Label lbY2;
+ private System.Windows.Forms.TextBox txtOrientationY;
+ private System.Windows.Forms.Label lbId;
+ private System.Windows.Forms.Label lbZ2;
+ private System.Windows.Forms.TextBox txtOrientationX;
+ private System.Windows.Forms.Button btAdd;
+ private System.Windows.Forms.Label lbTranslation;
+ private System.Windows.Forms.Label lbOrientation;
+ private System.Windows.Forms.TextBox txtTranslationZ;
+ private System.Windows.Forms.TextBox txtTranslationX;
+ private System.Windows.Forms.ListBox lisMarkers;
+ private System.Windows.Forms.TextBox txtTranslationY;
+ private System.Windows.Forms.GroupBox grBounding;
+ private System.Windows.Forms.Label lbMin;
+ private System.Windows.Forms.TextBox txtMaxZ;
+ private System.Windows.Forms.TextBox txtMaxY;
+ private System.Windows.Forms.TextBox txtMinX;
+ private System.Windows.Forms.TextBox txtMaxX;
+ private System.Windows.Forms.TextBox txtMinY;
+ private System.Windows.Forms.Label lbMax;
+ private System.Windows.Forms.TextBox txtMinZ;
+ private System.Windows.Forms.Label lbZ;
+ private System.Windows.Forms.Label lbY;
+ private System.Windows.Forms.Label lbX;
+
+ }
+}
\ No newline at end of file
diff --git a/LiveScanServer/SettingsForm.cs b/LiveScanServer/SettingsForm.cs
new file mode 100644
index 0000000..31436e6
--- /dev/null
+++ b/LiveScanServer/SettingsForm.cs
@@ -0,0 +1,285 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Globalization;
+
+namespace KinectServer
+{
+ public partial class SettingsForm : Form
+ {
+ public KinectSettings oSettings;
+ public KinectServer oServer;
+
+ public SettingsForm()
+ {
+ InitializeComponent();
+ }
+
+ private void SettingsForm_Load(object sender, EventArgs e)
+ {
+ txtMinX.Text = oSettings.aMinBounds[0].ToString(CultureInfo.InvariantCulture);
+ txtMinY.Text = oSettings.aMinBounds[1].ToString(CultureInfo.InvariantCulture);
+ txtMinZ.Text = oSettings.aMinBounds[2].ToString(CultureInfo.InvariantCulture);
+
+ txtMaxX.Text = oSettings.aMaxBounds[0].ToString(CultureInfo.InvariantCulture);
+ txtMaxY.Text = oSettings.aMaxBounds[1].ToString(CultureInfo.InvariantCulture);
+ txtMaxZ.Text = oSettings.aMaxBounds[2].ToString(CultureInfo.InvariantCulture);
+
+ chFilter.Checked = oSettings.bFilter;
+ txtFilterNeighbors.Text = oSettings.nFilterNeighbors.ToString();
+ txtFilterDistance.Text = oSettings.fFilterThreshold.ToString(CultureInfo.InvariantCulture);
+
+ lisMarkers.DataSource = oSettings.lMarkerPoses;
+
+
+ chMerge.Checked = oSettings.bMergeScansForSave;
+ txtICPIters.Text = oSettings.nNumICPIterations.ToString();
+ txtRefinIters.Text = oSettings.nMaxNumRefineIters.ToString();
+ }
+
+ void UpdateClients()
+ {
+ oServer.SendSettings();
+ }
+
+ void UpdateMarkerFields()
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+
+ float X, Y, Z;
+ pose.GetOrientation(out X, out Y, out Z);
+
+ txtOrientationX.Text = X.ToString(CultureInfo.InvariantCulture);
+ txtOrientationY.Text = Y.ToString(CultureInfo.InvariantCulture);
+ txtOrientationZ.Text = Z.ToString(CultureInfo.InvariantCulture);
+
+ txtTranslationX.Text = pose.pose.t[0].ToString(CultureInfo.InvariantCulture);
+ txtTranslationY.Text = pose.pose.t[1].ToString(CultureInfo.InvariantCulture);
+ txtTranslationZ.Text = pose.pose.t[2].ToString(CultureInfo.InvariantCulture);
+
+ txtId.Text = pose.id.ToString(CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ txtOrientationX.Text = "";
+ txtOrientationY.Text = "";
+ txtOrientationZ.Text = "";
+
+ txtTranslationX.Text = "";
+ txtTranslationY.Text = "";
+ txtTranslationZ.Text = "";
+
+ txtId.Text = "";
+ }
+ }
+
+ private void txtMinX_TextChanged(object sender, EventArgs e)
+ {
+ Single.TryParse(txtMinX.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out oSettings.aMinBounds[0]);
+ UpdateClients();
+ }
+
+ private void txtMinY_TextChanged(object sender, EventArgs e)
+ {
+ Single.TryParse(txtMinY.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out oSettings.aMinBounds[1]);
+ UpdateClients();
+ }
+
+ private void txtMinZ_TextChanged(object sender, EventArgs e)
+ {
+ Single.TryParse(txtMinZ.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out oSettings.aMinBounds[2]);
+ UpdateClients();
+ }
+
+ private void txtMaxX_TextChanged(object sender, EventArgs e)
+ {
+ Single.TryParse(txtMaxX.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out oSettings.aMaxBounds[0]);
+ UpdateClients();
+ }
+
+ private void txtMaxY_TextChanged(object sender, EventArgs e)
+ {
+ Single.TryParse(txtMaxY.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out oSettings.aMaxBounds[1]);
+ UpdateClients();
+ }
+
+ private void txtMaxZ_TextChanged(object sender, EventArgs e)
+ {
+ Single.TryParse(txtMaxZ.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out oSettings.aMaxBounds[2]);
+ UpdateClients();
+ }
+
+ private void chFilter_CheckedChanged(object sender, EventArgs e)
+ {
+ oSettings.bFilter = chFilter.Checked;
+ UpdateClients();
+ }
+
+ private void txtFilterNeighbors_TextChanged(object sender, EventArgs e)
+ {
+ Int32.TryParse(txtFilterNeighbors.Text, out oSettings.nFilterNeighbors);
+ UpdateClients();
+ }
+
+ private void txtFilterDistance_TextChanged(object sender, EventArgs e)
+ {
+ Single.TryParse(txtFilterDistance.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out oSettings.fFilterThreshold);
+ UpdateClients();
+ }
+
+ private void txtICPIters_TextChanged(object sender, EventArgs e)
+ {
+ Int32.TryParse(txtICPIters.Text, out oSettings.nNumICPIterations);
+ }
+
+ private void txtRefinIters_TextChanged(object sender, EventArgs e)
+ {
+ Int32.TryParse(txtRefinIters.Text, out oSettings.nMaxNumRefineIters);
+ }
+
+ private void chMerge_CheckedChanged(object sender, EventArgs e)
+ {
+ oSettings.bMergeScansForSave = chMerge.Checked;
+ }
+
+ private void btAdd_Click(object sender, EventArgs e)
+ {
+ lock (oSettings)
+ oSettings.lMarkerPoses.Add(new MarkerPose());
+ lisMarkers.SelectedIndex = oSettings.lMarkerPoses.Count - 1;
+ UpdateMarkerFields();
+ UpdateClients();
+ }
+ private void btRemove_Click(object sender, EventArgs e)
+ {
+ if (oSettings.lMarkerPoses.Count > 0)
+ {
+ oSettings.lMarkerPoses.RemoveAt(lisMarkers.SelectedIndex);
+ lisMarkers.SelectedIndex = oSettings.lMarkerPoses.Count - 1;
+ UpdateMarkerFields();
+ UpdateClients();
+ }
+ }
+
+ private void lisMarkers_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ UpdateMarkerFields();
+ }
+
+ private void txtOrientationX_TextChanged(object sender, EventArgs e)
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+ float X, Y, Z;
+ pose.GetOrientation(out X, out Y, out Z);
+ Single.TryParse(txtOrientationX.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out X);
+
+ pose.SetOrientation(X, Y, Z);
+ UpdateClients();
+ }
+ }
+
+ private void txtOrientationY_TextChanged(object sender, EventArgs e)
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+ float X, Y, Z;
+ pose.GetOrientation(out X, out Y, out Z);
+ Single.TryParse(txtOrientationY.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out Y);
+
+ pose.SetOrientation(X, Y, Z);
+ UpdateClients();
+ }
+ }
+
+ private void txtOrientationZ_TextChanged(object sender, EventArgs e)
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+ float X, Y, Z;
+ pose.GetOrientation(out X, out Y, out Z);
+ Single.TryParse(txtOrientationZ.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out Z);
+
+ pose.SetOrientation(X, Y, Z);
+ UpdateClients();
+ }
+ }
+
+ private void txtTranslationX_TextChanged(object sender, EventArgs e)
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ float X;
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+ Single.TryParse(txtTranslationX.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out X);
+
+ pose.pose.t[0] = X;
+ UpdateClients();
+ }
+ }
+
+ private void txtTranslationY_TextChanged(object sender, EventArgs e)
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ float Y;
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+ Single.TryParse(txtTranslationY.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out Y);
+
+ pose.pose.t[1] = Y;
+ UpdateClients();
+ }
+ }
+
+ private void txtTranslationZ_TextChanged(object sender, EventArgs e)
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ float Z;
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+ Single.TryParse(txtTranslationZ.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out Z);
+
+ pose.pose.t[2] = Z;
+ UpdateClients();
+ }
+ }
+
+ private void txtId_TextChanged(object sender, EventArgs e)
+ {
+ if (lisMarkers.SelectedIndex >= 0)
+ {
+ int id;
+ MarkerPose pose = oSettings.lMarkerPoses[lisMarkers.SelectedIndex];
+ Int32.TryParse(txtId.Text, out id);
+
+ pose.id = id;
+ UpdateClients();
+ }
+ }
+ }
+}
diff --git a/LiveScanServer/SettingsForm.resx b/LiveScanServer/SettingsForm.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/LiveScanServer/SettingsForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/LiveScanServer/Utils.cs b/LiveScanServer/Utils.cs
new file mode 100644
index 0000000..9c5ae78
--- /dev/null
+++ b/LiveScanServer/Utils.cs
@@ -0,0 +1,95 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+using System;
+
+namespace KinectServer
+{
+ [Serializable]
+ public class AffineTransform
+ {
+ public float[,] R = new float[3, 3];
+ public float[] t = new float[3];
+
+ public AffineTransform()
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ if (i == j)
+ R[i, j] = 1;
+ else
+ R[i, j] = 0;
+ }
+ t[i] = 0;
+ }
+ }
+ }
+
+ [Serializable]
+ public class MarkerPose
+ {
+ public AffineTransform pose = new AffineTransform();
+ public int id = -1;
+
+ public MarkerPose()
+ {
+ UpdateRotationMatrix();
+ }
+
+ public void SetOrientation(float X, float Y, float Z)
+ {
+ r[0] = X;
+ r[1] = Y;
+ r[2] = Z;
+
+ UpdateRotationMatrix();
+ }
+
+ public void GetOrientation(out float X, out float Y, out float Z)
+ {
+ X = r[0];
+ Y = r[1];
+ Z = r[2];
+ }
+
+ private void UpdateRotationMatrix()
+ {
+ float radX = r[0] * (float)Math.PI / 180.0f;
+ float radY = r[1] * (float)Math.PI / 180.0f;
+ float radZ = r[2] * (float)Math.PI / 180.0f;
+
+ float c1 = (float)Math.Cos(radZ);
+ float c2 = (float)Math.Cos(radY);
+ float c3 = (float)Math.Cos(radX);
+ float s1 = (float)Math.Sin(radZ);
+ float s2 = (float)Math.Sin(radY);
+ float s3 = (float)Math.Sin(radX);
+
+ //Z Y X rotation
+ pose.R[0, 0] = c1 * c2;
+ pose.R[0, 1] = c1 * s2 * s3 - c3 * s1;
+ pose.R[0, 2] = s1 * s3 + c1 * c3 * s2;
+ pose.R[1, 0] = c2 * s1;
+ pose.R[1, 1] = c1 * c3 + s1 * s2 * s3;
+ pose.R[1, 2] = c3 * s1 * s2 - c1 * s3;
+ pose.R[2, 0] = -s2;
+ pose.R[2, 1] = c2 * s3;
+ pose.R[2, 2] = c2 * c3;
+ }
+
+ private float[] r = new float[3];
+ }
+}
\ No newline at end of file
diff --git a/docs/calibration markers/0b.gif b/docs/calibration markers/0b.gif
new file mode 100644
index 0000000..fb0f8ec
Binary files /dev/null and b/docs/calibration markers/0b.gif differ
diff --git a/docs/calibration markers/1b.gif b/docs/calibration markers/1b.gif
new file mode 100644
index 0000000..fc65716
Binary files /dev/null and b/docs/calibration markers/1b.gif differ
diff --git a/docs/calibration markers/2b.gif b/docs/calibration markers/2b.gif
new file mode 100644
index 0000000..748b9c7
Binary files /dev/null and b/docs/calibration markers/2b.gif differ
diff --git a/docs/calibration markers/3b.gif b/docs/calibration markers/3b.gif
new file mode 100644
index 0000000..4199d15
Binary files /dev/null and b/docs/calibration markers/3b.gif differ
diff --git a/docs/calibration markers/4b.gif b/docs/calibration markers/4b.gif
new file mode 100644
index 0000000..6cc446a
Binary files /dev/null and b/docs/calibration markers/4b.gif differ
diff --git a/docs/calibration markers/5b.gif b/docs/calibration markers/5b.gif
new file mode 100644
index 0000000..00b898c
Binary files /dev/null and b/docs/calibration markers/5b.gif differ
diff --git a/docs/manual.pdf b/docs/manual.pdf
new file mode 100644
index 0000000..07c1df8
Binary files /dev/null and b/docs/manual.pdf differ
diff --git a/include/ICP/icp.h b/include/ICP/icp.h
new file mode 100644
index 0000000..6b9fe5f
--- /dev/null
+++ b/include/ICP/icp.h
@@ -0,0 +1,65 @@
+#include
+#include
+
+#include "nanoflann.h"
+
+#if defined(ICP_DLL_EXPORTS) // inside DLL
+# define ICP_API __declspec(dllexport)
+#else // outside DLL
+# define ICP_API __declspec(dllimport)
+#endif
+
+
+using namespace std;
+
+struct Point3f
+{
+ float X, Y, Z;
+};
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+struct PointCloud
+{
+ std::vector pts;
+
+ // Must return the number of data points
+ inline size_t kdtree_get_point_count() const { return pts.size(); }
+ // Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
+ inline float kdtree_distance(const float *p1, const size_t idx_p2, size_t /*size*/) const
+ {
+ const float d0 = p1[0] - pts[idx_p2].X;
+ const float d1 = p1[1] - pts[idx_p2].Y;
+ const float d2 = p1[2] - pts[idx_p2].Z;
+
+ return d0*d0 + d1*d1 + d2*d2;
+ }
+ // Returns the dim'th component of the idx'th point in the class:
+ // Since this is inlined and the "dim" argument is typically an immediate value, the
+ // "if/else's" are actually solved at compile time.
+ inline float kdtree_get_pt(const size_t idx, int dim) const
+ {
+ if (dim == 0) return pts[idx].X;
+ else if (dim == 1) return pts[idx].Y;
+ else return pts[idx].Z;
+ }
+ // Optional bounding-box computation: return false to default to a standard bbox computation loop.
+ // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
+ // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
+ template
+ bool kdtree_get_bbox(BBOX& /*bb*/) const { return false; }
+};
+
+
+extern "C" ICP_API float __stdcall ICP(Point3f *verts1, Point3f *verts2, int nVerts1, int nVerts2, float *R, float *t, int maxIter = 10);
\ No newline at end of file
diff --git a/include/LiveScanClient/calibration.h b/include/LiveScanClient/calibration.h
new file mode 100644
index 0000000..767be2b
--- /dev/null
+++ b/include/LiveScanClient/calibration.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+#include "stdafx.h"
+#include "marker.h"
+#include "utils.h"
+
+vector RotatePoint(vector &point, std::vector> &R);
+vector InverseRotatePoint(vector &point, std::vector> &R);
+
+struct MarkerPose
+{
+ int markerId;
+ float R[3][3];
+ float t[3];
+};
+
+class Calibration
+{
+public:
+ vector worldT;
+ vector> worldR;
+ int iUsedMarkerId;
+
+ vector cameraT;
+ vector> cameraR;
+
+ vector markerPoses;
+
+ bool bCalibrated;
+
+ Calibration();
+ ~Calibration();
+
+ bool Calibrate(RGB *pBuffer, Point3f *pCameraCoordinates, int cColorWidth, int cColorHeight);
+private:
+ IMarker *pDetector;
+ int nSampleCounter;
+ int nRequiredSamples;
+
+ vector> marker3DSamples;
+
+ void Procrustes(MarkerInfo &marker, vector &markerInWorld, vector &markerT, vector> &markerR);
+ bool GetMarkerCorners3D(vector &marker3D, MarkerInfo &marker, Point3f *pCameraCoordinates, int cColorWidth, int cColorHeight);
+};
+
diff --git a/include/LiveScanClient/filter.h b/include/LiveScanClient/filter.h
new file mode 100644
index 0000000..b79a9e7
--- /dev/null
+++ b/include/LiveScanClient/filter.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+
+#include
+
+#include "nanoflann.h"
+#include "utils.h"
+
+struct KNNeighborsResult
+{
+ std::vector neighbors;
+ std::vector distances;
+ float kDistance;
+};
+
+struct PointCloud
+{
+ std::vector pts;
+
+ // Must return the number of data points
+ inline size_t kdtree_get_point_count() const { return pts.size(); }
+ // Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
+ inline float kdtree_distance(const float *p1, const size_t idx_p2, size_t /*size*/) const
+ {
+ const float d0 = p1[0] - pts[idx_p2].X;
+ const float d1 = p1[1] - pts[idx_p2].Y;
+ const float d2 = p1[2] - pts[idx_p2].Z;
+
+ return d0*d0 + d1*d1 + d2*d2;
+ }
+ // Returns the dim'th component of the idx'th point in the class:
+ // Since this is inlined and the "dim" argument is typically an immediate value, the
+ // "if/else's" are actually solved at compile time.
+ inline float kdtree_get_pt(const size_t idx, int dim) const
+ {
+ if (dim == 0) return pts[idx].X;
+ else if (dim == 1) return pts[idx].Y;
+ else return pts[idx].Z;
+ }
+ // Optional bounding-box computation: return false to default to a standard bbox computation loop.
+ // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
+ // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
+ template
+ bool kdtree_get_bbox(BBOX& /*bb*/) const { return false; }
+};
+
+typedef nanoflann::KDTreeSingleIndexAdaptor, PointCloud, 3> kdTree;
+
+void filter(std::vector &vertices, std::vector &colors, int k = 10, float maxDist = 0.01);
\ No newline at end of file
diff --git a/include/LiveScanClient/iCapture.h b/include/LiveScanClient/iCapture.h
new file mode 100644
index 0000000..5d55710
--- /dev/null
+++ b/include/LiveScanClient/iCapture.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+
+#include "utils.h"
+
+class ICapture
+{
+public:
+ ICapture();
+ ~ICapture();
+
+ virtual bool Initialize() = 0;
+ virtual bool AcquireFrame() = 0;
+ virtual void MapDepthFrameToCameraSpace(Point3f *pCameraSpacePoints) = 0;
+ virtual void MapColorFrameToCameraSpace(Point3f *pCameraSpacePoints) = 0;
+ virtual void MapDepthFrameToColorSpace(Point2f *pColorSpacePoints) = 0;
+ virtual void MapColorFrameToDepthSpace(Point2f *pDepthSpacePoints) = 0;
+
+ bool bInitialized;
+
+ int nColorFrameHeight, nColorFrameWidth;
+ int nDepthFrameHeight, nDepthFrameWidth;
+
+ UINT16 *pDepth;
+ RGB *pColorRGBX;
+};
\ No newline at end of file
diff --git a/include/LiveScanClient/iMarker.h b/include/LiveScanClient/iMarker.h
new file mode 100644
index 0000000..9b19b35
--- /dev/null
+++ b/include/LiveScanClient/iMarker.h
@@ -0,0 +1,49 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+
+#include "utils.h"
+
+//struktura przechowywuj¹ca wszystkie dane markera
+typedef struct MarkerStruct
+{
+ int id;
+ //po³o¿enie naro¿ników markera w obrazie
+ std::vector corners;
+ //te same punkty w uk³adzie wspó³rzêdnych markera
+ std::vector points;
+
+ MarkerStruct()
+ {
+ id = -1;
+ }
+
+ MarkerStruct(int id, std::vector corners, std::vector points)
+ {
+ this->id = id;
+
+ this->corners = corners;
+ this->points = points;
+ }
+} MarkerInfo;
+
+class IMarker
+{
+public:
+ IMarker() {};
+
+ //znajduje wszystkie markery w obrazie i zapisuje je w zmiennej markers
+ virtual bool GetMarker(RGB *img, int height, int width, MarkerInfo &marker) = 0;
+};
\ No newline at end of file
diff --git a/include/LiveScanClient/imageRenderer.h b/include/LiveScanClient/imageRenderer.h
new file mode 100644
index 0000000..65282d6
--- /dev/null
+++ b/include/LiveScanClient/imageRenderer.h
@@ -0,0 +1,69 @@
+//------------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//------------------------------------------------------------------------------
+
+// Manages the drawing of image data
+
+#pragma once
+
+#include
+
+class ImageRenderer
+{
+public:
+ ///
+ /// Constructor
+ ///
+ ImageRenderer();
+
+ ///
+ /// Destructor
+ ///
+ virtual ~ImageRenderer();
+
+ ///
+ /// Set the window to draw to as well as the video format
+ /// Implied bits per pixel is 32
+ ///
+ /// window to draw to
+ /// already created D2D factory object
+ /// width (in pixels) of image data to be drawn
+ /// height (in pixels) of image data to be drawn
+ /// length (in bytes) of a single scanline
+ /// indicates success or failure
+ HRESULT Initialize(HWND hwnd, ID2D1Factory* pD2DFactory, int sourceWidth, int sourceHeight, int sourceStride);
+
+ ///
+ /// Draws a 32 bit per pixel image of previously specified width, height, and stride to the associated hwnd
+ ///
+ /// image data in RGBX format
+ /// size of image data in bytes
+ /// indicates success or failure
+ HRESULT Draw(BYTE* pImage, unsigned long cbImage);
+
+private:
+ HWND m_hWnd;
+
+ // Format information
+ UINT m_sourceHeight;
+ UINT m_sourceWidth;
+ LONG m_sourceStride;
+
+ // Direct2D
+ ID2D1Factory* m_pD2DFactory;
+ ID2D1HwndRenderTarget* m_pRenderTarget;
+ ID2D1Bitmap* m_pBitmap;
+
+ ///
+ /// Ensure necessary Direct2d resources are created
+ ///
+ /// indicates success or failure
+ HRESULT EnsureResources();
+
+ ///
+ /// Dispose of Direct2d resources
+ ///
+ void DiscardResources();
+};
\ No newline at end of file
diff --git a/include/LiveScanClient/kinectCapture.h b/include/LiveScanClient/kinectCapture.h
new file mode 100644
index 0000000..3df9fcc
--- /dev/null
+++ b/include/LiveScanClient/kinectCapture.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+
+#include "stdafx.h"
+#include "ICapture.h"
+#include "Kinect.h"
+#include "utils.h"
+
+class KinectCapture : public ICapture
+{
+public:
+ KinectCapture();
+ ~KinectCapture();
+
+ bool Initialize();
+ bool AcquireFrame();
+ void MapDepthFrameToCameraSpace(Point3f *pCameraSpacePoints);
+ void MapColorFrameToCameraSpace(Point3f *pCameraSpacePoints);
+ void MapDepthFrameToColorSpace(Point2f *pColorSpacePoints);
+ void MapColorFrameToDepthSpace(Point2f *pDepthSpacePoints);
+private:
+ ICoordinateMapper* pCoordinateMapper;
+ IKinectSensor* pKinectSensor;
+ IMultiSourceFrameReader* pMultiSourceFrameReader;
+};
diff --git a/include/LiveScanClient/liveScanClient.h b/include/LiveScanClient/liveScanClient.h
new file mode 100644
index 0000000..5225097
--- /dev/null
+++ b/include/LiveScanClient/liveScanClient.h
@@ -0,0 +1,90 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+
+#include "resource.h"
+#include "ImageRenderer.h"
+#include "SocketCS.h"
+#include "calibration.h"
+#include "utils.h"
+#include "KinectCapture.h"
+#include
+#include
+
+class LiveScanClient
+{
+public:
+ LiveScanClient();
+ ~LiveScanClient();
+
+
+ static LRESULT CALLBACK MessageRouter(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ LRESULT CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ int Run(HINSTANCE hInstance, int nCmdShow);
+
+ bool m_bSocketThread;
+private:
+ Calibration calibration;
+
+ bool m_bCalibrate;
+ bool m_bFilter;
+
+ ICapture *pCapture;
+
+ int m_nFilterNeighbors;
+ float m_fFilterThreshold;
+
+ bool m_bCaptureFrame;
+ bool m_bConnected;
+ bool m_bConfirmCaptured;
+ bool m_bConfirmCalibrated;
+ bool m_bShowDepth;
+
+ SocketClient *m_pClientSocket;
+ std::vector m_vBounds;
+
+ std::vector m_vLastFrameVertices;
+ std::vector m_vLastFrameRGB;
+ std::vector> m_vGatheredVertices;
+ std::vector> m_vGatheredRGBPoints;
+
+ HWND m_hWnd;
+ INT64 m_nLastCounter;
+ double m_fFreq;
+ INT64 m_nNextStatusTime;
+ DWORD m_nFramesSinceUpdate;
+
+ Point3f* m_pCameraSpaceCoordinates;
+ Point2f* m_pColorCoordinates;
+
+ // Direct2D
+ ImageRenderer* m_pDrawColor;
+ ID2D1Factory* m_pD2DFactory;
+ RGB* m_pDepthRGBX;
+
+ void UpdateFrame();
+ void ProcessColor(RGB* pBuffer, int nWidth, int nHeight);
+ void ProcessDepth(const UINT16* pBuffer, int nHeight, int nWidth);
+
+ bool SetStatusMessage(_In_z_ WCHAR* szMessage, DWORD nShowTimeMsec, bool bForce);
+
+ void HandleSocket();
+ void SocketThreadFunction();
+ void StoreFrame(Point3f *vertices, Point2f *mapping, RGB *color);
+ void ShowFPS();
+ void ReadIPFromFile();
+ void WriteIPToFile();
+};
+
diff --git a/include/LiveScanClient/marker.h b/include/LiveScanClient/marker.h
new file mode 100644
index 0000000..751fc7a
--- /dev/null
+++ b/include/LiveScanClient/marker.h
@@ -0,0 +1,49 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+
+#include "stdafx.h"
+#include
+#include "utils.h"
+#include "IMarker.h"
+
+using namespace std;
+
+class MarkerDetector : public IMarker
+{
+public:
+ MarkerDetector();
+
+ bool GetMarker(RGB *img, int height, int width, MarkerInfo &marker);
+private:
+ int nMarkerCorners;
+ vector vPts;
+
+ int nMinSize;
+ int nMaxSize;
+ int nThreshold;
+ double dApproxPolyCoef;
+ double dMarkerFrame;
+ bool bDraw;
+
+ bool GetMarker(cv::Mat &img, MarkerInfo &marker);
+ bool OrderCorners(vector &corners);
+ int GetCode(cv::Mat &img, vector points, vector corners);
+ void CornersSubPix(vector &corners, vector contour, bool order);
+ cv::Point2f GetIntersection(cv::Vec4f lin1, cv::Vec4f lin2);
+ void GetMarkerPoints(vector &pts);
+ void GetMarkerPointsForWarp(vector &pts);
+ double GetMarkerArea(MarkerInfo &marker);
+};
\ No newline at end of file
diff --git a/include/LiveScanClient/utils.h b/include/LiveScanClient/utils.h
new file mode 100644
index 0000000..bc7aba5
--- /dev/null
+++ b/include/LiveScanClient/utils.h
@@ -0,0 +1,85 @@
+// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
+// License: MIT Software License See LICENSE.txt for the full license.
+
+// If you use this software in your research, then please use the following citation:
+
+// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
+// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
+
+// @INPROCEEDINGS{Kowalski15,
+// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
+// booktitle={3D Vision (3DV), 2015 International Conference on},
+// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
+// year={2015},
+// }
+#pragma once
+
+#include "stdafx.h"
+#include
+#include
+#include
+
+enum INCOMING_MESSAGE_TYPE
+{
+ MSG_CAPTURE_FRAME,
+ MSG_CALIBRATE,
+ MSG_RECEIVE_SETTINGS,
+ MSG_REQUEST_STORED_FRAME,
+ MSG_REQUEST_LAST_FRAME,
+ MSG_RECEIVE_CALIBRATION,
+ MSG_CLEAR_STORED_FRAMES
+};
+
+enum OUTGOING_MESSAGE_TYPE
+{
+ MSG_CONFIRM_CAPTURED,
+ MSG_CONFIRM_CALIBRATED,
+ MSG_STORED_FRAME,
+ MSG_LAST_FRAME
+};
+
+typedef struct Point3f
+{
+ Point3f()
+ {
+ this->X = 0;
+ this->Y = 0;
+ this->Z = 0;
+ }
+ Point3f(float X, float Y, float Z)
+ {
+ this->X = X;
+ this->Y = Y;
+ this->Z = Z;
+ }
+ float X;
+ float Y;
+ float Z;
+} Point3f;
+
+typedef struct Point2f
+{
+ Point2f()
+ {
+ this->X = 0;
+ this->Y = 0;
+ }
+ Point2f(float X, float Y)
+ {
+ this->X = X;
+ this->Y = Y;
+ }
+ float X;
+ float Y;
+} Point2f;
+
+typedef struct RGB
+{
+ BYTE rgbBlue;
+ BYTE rgbGreen;
+ BYTE rgbRed;
+ BYTE rgbReserved;
+} RGB;
+
+Point3f RotatePoint(Point3f &point, std::vector> &R);
+Point3f InverseRotatePoint(Point3f &point, std::vector> &R);
diff --git a/include/nanoflann.h b/include/nanoflann.h
new file mode 100644
index 0000000..cf372e7
--- /dev/null
+++ b/include/nanoflann.h
@@ -0,0 +1,1391 @@
+/***********************************************************************
+* Software License Agreement (BSD License)
+*
+* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
+* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
+* Copyright 2011-2014 Jose Luis Blanco (joseluisblancoc@gmail.com).
+* All rights reserved.
+*
+* THE BSD LICENSE
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*************************************************************************/
+
+/** \mainpage nanoflann C++ API documentation
+* nanoflann is a C++ header-only library for building KD-Trees, mostly
+* optimized for 2D or 3D point clouds.
+*
+* nanoflann does not require compiling or installing, just an
+* #include in your code.
+*
+* See:
+* - C++ API organized by modules
+* - Online README
+*/
+
+#ifndef NANOFLANN_HPP_
+#define NANOFLANN_HPP_
+
+#include
+#include
+#include
+#include
+#include // for fwrite()
+#include // for fabs(),...
+#include
+
+// Avoid conflicting declaration of min/max macros in windows headers
+#if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
+# define NOMINMAX
+# ifdef max
+# undef max
+# undef min
+# endif
+#endif
+
+namespace nanoflann
+{
+ /** @addtogroup nanoflann_grp nanoflann C++ library for ANN
+ * @{ */
+
+ /** Library version: 0xMmP (M=Major,m=minor,P=patch) */
+#define NANOFLANN_VERSION 0x119
+
+ /** @addtogroup result_sets_grp Result set classes
+ * @{ */
+ template
+ class KNNResultSet
+ {
+ IndexType * indices;
+ DistanceType* dists;
+ CountType capacity;
+ CountType count;
+
+ public:
+ inline KNNResultSet(CountType capacity_) : indices(0), dists(0), capacity(capacity_), count(0)
+ {
+ }
+
+ inline void init(IndexType* indices_, DistanceType* dists_)
+ {
+ indices = indices_;
+ dists = dists_;
+ count = 0;
+ dists[capacity - 1] = (std::numeric_limits::max)();
+ }
+
+ inline CountType size() const
+ {
+ return count;
+ }
+
+ inline bool full() const
+ {
+ return count == capacity;
+ }
+
+
+ inline void addPoint(DistanceType dist, IndexType index)
+ {
+ CountType i;
+ for (i = count; i>0; --i) {
+#ifdef NANOFLANN_FIRST_MATCH // If defined and two poins have the same distance, the one with the lowest-index will be returned first.
+ if ((dists[i - 1]>dist) || ((dist == dists[i - 1]) && (indices[i - 1]>index))) {
+#else
+ if (dists[i - 1]>dist) {
+#endif
+ if (i
+ class RadiusResultSet
+ {
+ public:
+ const DistanceType radius;
+
+ std::vector >& m_indices_dists;
+
+ inline RadiusResultSet(DistanceType radius_, std::vector >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
+ {
+ init();
+ }
+
+ inline ~RadiusResultSet() { }
+
+ inline void init() { clear(); }
+ inline void clear() { m_indices_dists.clear(); }
+
+ inline size_t size() const { return m_indices_dists.size(); }
+
+ inline bool full() const { return true; }
+
+ inline void addPoint(DistanceType dist, IndexType index)
+ {
+ if (dist 0
+ */
+ std::pair worst_item() const
+ {
+ if (m_indices_dists.empty()) throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on an empty list of results.");
+ typedef typename std::vector >::const_iterator DistIt;
+ DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end());
+ return *it;
+ }
+ };
+
+ /** operator "<" for std::sort() */
+ struct IndexDist_Sorter
+ {
+ /** PairType will be typically: std::pair */
+ template
+ inline bool operator()(const PairType &p1, const PairType &p2) const {
+ return p1.second < p2.second;
+ }
+ };
+
+ /** @} */
+
+
+ /** @addtogroup loadsave_grp Load/save auxiliary functions
+ * @{ */
+ template
+ void save_value(FILE* stream, const T& value, size_t count = 1)
+ {
+ fwrite(&value, sizeof(value), count, stream);
+ }
+
+ template
+ void save_value(FILE* stream, const std::vector& value)
+ {
+ size_t size = value.size();
+ fwrite(&size, sizeof(size_t), 1, stream);
+ fwrite(&value[0], sizeof(T), size, stream);
+ }
+
+ template
+ void load_value(FILE* stream, T& value, size_t count = 1)
+ {
+ size_t read_cnt = fread(&value, sizeof(value), count, stream);
+ if (read_cnt != count) {
+ throw std::runtime_error("Cannot read from file");
+ }
+ }
+
+
+ template
+ void load_value(FILE* stream, std::vector& value)
+ {
+ size_t size;
+ size_t read_cnt = fread(&size, sizeof(size_t), 1, stream);
+ if (read_cnt != 1) {
+ throw std::runtime_error("Cannot read from file");
+ }
+ value.resize(size);
+ read_cnt = fread(&value[0], sizeof(T), size, stream);
+ if (read_cnt != size) {
+ throw std::runtime_error("Cannot read from file");
+ }
+ }
+ /** @} */
+
+
+ /** @addtogroup metric_grp Metric (distance) classes
+ * @{ */
+
+ template inline T abs(T x) { return (x<0) ? -x : x; }
+ template<> inline int abs(int x) { return ::abs(x); }
+ template<> inline float abs(float x) { return fabsf(x); }
+ template<> inline double abs(double x) { return fabs(x); }
+ template<> inline long double abs(long double x) { return fabsl(x); }
+
+ /** Manhattan distance functor (generic version, optimized for high-dimensionality data sets).
+ * Corresponding distance traits: nanoflann::metric_L1
+ * \tparam T Type of the elements (e.g. double, float, uint8_t)
+ * \tparam _DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t)
+ */
+ template
+ struct L1_Adaptor
+ {
+ typedef T ElementType;
+ typedef _DistanceType DistanceType;
+
+ const DataSource &data_source;
+
+ L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
+
+ inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const
+ {
+ DistanceType result = DistanceType();
+ const T* last = a + size;
+ const T* lastgroup = last - 3;
+ size_t d = 0;
+
+ /* Process 4 items with each loop for efficiency. */
+ while (a < lastgroup) {
+ const DistanceType diff0 = nanoflann::abs(a[0] - data_source.kdtree_get_pt(b_idx, d++));
+ const DistanceType diff1 = nanoflann::abs(a[1] - data_source.kdtree_get_pt(b_idx, d++));
+ const DistanceType diff2 = nanoflann::abs(a[2] - data_source.kdtree_get_pt(b_idx, d++));
+ const DistanceType diff3 = nanoflann::abs(a[3] - data_source.kdtree_get_pt(b_idx, d++));
+ result += diff0 + diff1 + diff2 + diff3;
+ a += 4;
+ if ((worst_dist>0) && (result>worst_dist)) {
+ return result;
+ }
+ }
+ /* Process last 0-3 components. Not needed for standard vector lengths. */
+ while (a < last) {
+ result += nanoflann::abs(*a++ - data_source.kdtree_get_pt(b_idx, d++));
+ }
+ return result;
+ }
+
+ template
+ inline DistanceType accum_dist(const U a, const V b, int) const
+ {
+ return nanoflann::abs(a - b);
+ }
+ };
+
+ /** Squared Euclidean distance functor (generic version, optimized for high-dimensionality data sets).
+ * Corresponding distance traits: nanoflann::metric_L2
+ * \tparam T Type of the elements (e.g. double, float, uint8_t)
+ * \tparam _DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t)
+ */
+ template
+ struct L2_Adaptor
+ {
+ typedef T ElementType;
+ typedef _DistanceType DistanceType;
+
+ const DataSource &data_source;
+
+ L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
+
+ inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const
+ {
+ DistanceType result = DistanceType();
+ const T* last = a + size;
+ const T* lastgroup = last - 3;
+ size_t d = 0;
+
+ /* Process 4 items with each loop for efficiency. */
+ while (a < lastgroup) {
+ const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx, d++);
+ const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx, d++);
+ const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx, d++);
+ const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx, d++);
+ result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
+ a += 4;
+ if ((worst_dist>0) && (result>worst_dist)) {
+ return result;
+ }
+ }
+ /* Process last 0-3 components. Not needed for standard vector lengths. */
+ while (a < last) {
+ const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx, d++);
+ result += diff0 * diff0;
+ }
+ return result;
+ }
+
+ template
+ inline DistanceType accum_dist(const U a, const V b, int) const
+ {
+ return (a - b)*(a - b);
+ }
+ };
+
+ /** Squared Euclidean (L2) distance functor (suitable for low-dimensionality datasets, like 2D or 3D point clouds)
+ * Corresponding distance traits: nanoflann::metric_L2_Simple
+ * \tparam T Type of the elements (e.g. double, float, uint8_t)
+ * \tparam _DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t)
+ */
+ template
+ struct L2_Simple_Adaptor
+ {
+ typedef T ElementType;
+ typedef _DistanceType DistanceType;
+
+ const DataSource &data_source;
+
+ L2_Simple_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
+
+ inline DistanceType operator()(const T* a, const size_t b_idx, size_t size) const {
+ return data_source.kdtree_distance(a, b_idx, size);
+ }
+
+ template
+ inline DistanceType accum_dist(const U a, const V b, int) const
+ {
+ return (a - b)*(a - b);
+ }
+ };
+
+ /** Metaprogramming helper traits class for the L1 (Manhattan) metric */
+ struct metric_L1 {
+ template
+ struct traits {
+ typedef L1_Adaptor distance_t;
+ };
+ };
+ /** Metaprogramming helper traits class for the L2 (Euclidean) metric */
+ struct metric_L2 {
+ template
+ struct traits {
+ typedef L2_Adaptor distance_t;
+ };
+ };
+ /** Metaprogramming helper traits class for the L2_simple (Euclidean) metric */
+ struct metric_L2_Simple {
+ template
+ struct traits {
+ typedef L2_Simple_Adaptor distance_t;
+ };
+ };
+
+ /** @} */
+
+ /** @addtogroup param_grp Parameter structs
+ * @{ */
+
+ /** Parameters (see README.md) */
+ struct KDTreeSingleIndexAdaptorParams
+ {
+ KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10) :
+ leaf_max_size(_leaf_max_size)
+ {}
+
+ size_t leaf_max_size;
+ };
+
+ /** Search options for KDTreeSingleIndexAdaptor::findNeighbors() */
+ struct SearchParams
+ {
+ /** Note: The first argument (checks_IGNORED_) is ignored, but kept for compatibility with the FLANN interface */
+ SearchParams(int checks_IGNORED_ = 32, float eps_ = 0, bool sorted_ = true) :
+ checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {}
+
+ int checks; //!< Ignored parameter (Kept for compatibility with the FLANN interface).
+ float eps; //!< search for eps-approximate neighbours (default: 0)
+ bool sorted; //!< only for radius search, require neighbours sorted by distance (default: true)
+ };
+ /** @} */
+
+
+ /** @addtogroup memalloc_grp Memory allocation
+ * @{ */
+
+ /**
+ * Allocates (using C's malloc) a generic type T.
+ *
+ * Params:
+ * count = number of instances to allocate.
+ * Returns: pointer (of type T*) to memory buffer
+ */
+ template
+ inline T* allocate(size_t count = 1)
+ {
+ T* mem = static_cast(::malloc(sizeof(T)*count));
+ return mem;
+ }
+
+
+ /**
+ * Pooled storage allocator
+ *
+ * The following routines allow for the efficient allocation of storage in
+ * small chunks from a specified pool. Rather than allowing each structure
+ * to be freed individually, an entire pool of storage is freed at once.
+ * This method has two advantages over just using malloc() and free(). First,
+ * it is far more efficient for allocating small objects, as there is
+ * no overhead for remembering all the information needed to free each
+ * object or consolidating fragmented memory. Second, the decision about
+ * how long to keep an object is made at the time of allocation, and there
+ * is no need to track down all the objects to free them.
+ *
+ */
+
+ const size_t WORDSIZE = 16;
+ const size_t BLOCKSIZE = 8192;
+
+ class PooledAllocator
+ {
+ /* We maintain memory alignment to word boundaries by requiring that all
+ allocations be in multiples of the machine wordsize. */
+ /* Size of machine word in bytes. Must be power of 2. */
+ /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */
+
+
+ size_t remaining; /* Number of bytes left in current block of storage. */
+ void* base; /* Pointer to base of current block of storage. */
+ void* loc; /* Current location in block to next allocate memory. */
+
+ void internal_init()
+ {
+ remaining = 0;
+ base = NULL;
+ usedMemory = 0;
+ wastedMemory = 0;
+ }
+
+ public:
+ size_t usedMemory;
+ size_t wastedMemory;
+
+ /**
+ Default constructor. Initializes a new pool.
+ */
+ PooledAllocator() {
+ internal_init();
+ }
+
+ /**
+ * Destructor. Frees all the memory allocated in this pool.
+ */
+ ~PooledAllocator() {
+ free_all();
+ }
+
+ /** Frees all allocated memory chunks */
+ void free_all()
+ {
+ while (base != NULL) {
+ void *prev = *(static_cast(base)); /* Get pointer to prev block. */
+ ::free(base);
+ base = prev;
+ }
+ internal_init();
+ }
+
+ /**
+ * Returns a pointer to a piece of new memory of the given size in bytes
+ * allocated from the pool.
+ */
+ void* malloc(const size_t req_size)
+ {
+ /* Round size up to a multiple of wordsize. The following expression
+ only works for WORDSIZE that is a power of 2, by masking last bits of
+ incremented size to zero.
+ */
+ const size_t size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
+
+ /* Check whether a new block must be allocated. Note that the first word
+ of a block is reserved for a pointer to the previous block.
+ */
+ if (size > remaining) {
+
+ wastedMemory += remaining;
+
+ /* Allocate new storage. */
+ const size_t blocksize = (size + sizeof(void*)+(WORDSIZE - 1) > BLOCKSIZE) ?
+ size + sizeof(void*)+(WORDSIZE - 1) : BLOCKSIZE;
+
+ // use the standard C malloc to allocate memory
+ void* m = ::malloc(blocksize);
+ if (!m) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ return NULL;
+ }
+
+ /* Fill first word of new block with pointer to previous block. */
+ static_cast(m)[0] = base;
+ base = m;
+
+ size_t shift = 0;
+ //int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1);
+
+ remaining = blocksize - sizeof(void*)-shift;
+ loc = (static_cast(m)+sizeof(void*)+shift);
+ }
+ void* rloc = loc;
+ loc = static_cast(loc)+size;
+ remaining -= size;
+
+ usedMemory += size;
+
+ return rloc;
+ }
+
+ /**
+ * Allocates (using this pool) a generic type T.
+ *
+ * Params:
+ * count = number of instances to allocate.
+ * Returns: pointer (of type T*) to memory buffer
+ */
+ template
+ T* allocate(const size_t count = 1)
+ {
+ T* mem = static_cast(this->malloc(sizeof(T)*count));
+ return mem;
+ }
+
+ };
+ /** @} */
+
+ /** @addtogroup nanoflann_metaprog_grp Auxiliary metaprogramming stuff
+ * @{ */
+
+ // ---------------- CArray -------------------------
+ /** A STL container (as wrapper) for arrays of constant size defined at compile time (class imported from the MRPT project)
+ * This code is an adapted version from Boost, modifed for its integration
+ * within MRPT (JLBC, Dec/2009) (Renamed array -> CArray to avoid possible potential conflicts).
+ * See
+ * http://www.josuttis.com/cppcode
+ * for details and the latest version.
+ * See
+ * http://www.boost.org/libs/array for Documentation.
+ * for documentation.
+ *
+ * (C) Copyright Nicolai M. Josuttis 2001.
+ * Permission to copy, use, modify, sell and distribute this software
+ * is granted provided this copyright notice appears in all copies.
+ * This software is provided "as is" without express or implied
+ * warranty, and with no claim as to its suitability for any purpose.
+ *
+ * 29 Jan 2004 - minor fixes (Nico Josuttis)
+ * 04 Dec 2003 - update to synch with library TR1 (Alisdair Meredith)
+ * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.
+ * 05 Aug 2001 - minor update (Nico Josuttis)
+ * 20 Jan 2001 - STLport fix (Beman Dawes)
+ * 29 Sep 2000 - Initial Revision (Nico Josuttis)
+ *
+ * Jan 30, 2004
+ */
+ template
+ class CArray {
+ public:
+ T elems[N]; // fixed-size array of elements of type T
+
+ public:
+ // type definitions
+ typedef T value_type;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ // iterator support
+ inline iterator begin() { return elems; }
+ inline const_iterator begin() const { return elems; }
+ inline iterator end() { return elems + N; }
+ inline const_iterator end() const { return elems + N; }
+
+ // reverse iterator support
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
+ typedef std::reverse_iterator reverse_iterator;
+ typedef std::reverse_iterator const_reverse_iterator;
+#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
+ // workaround for broken reverse_iterator in VC7
+ typedef std::reverse_iterator > reverse_iterator;
+ typedef std::reverse_iterator > const_reverse_iterator;
+#else
+ // workaround for broken reverse_iterator implementations
+ typedef std::reverse_iterator reverse_iterator;
+ typedef std::reverse_iterator const_reverse_iterator;
+#endif
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+ // operator[]
+ inline reference operator[](size_type i) { return elems[i]; }
+ inline const_reference operator[](size_type i) const { return elems[i]; }
+ // at() with range check
+ reference at(size_type i) { rangecheck(i); return elems[i]; }
+ const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
+ // front() and back()
+ reference front() { return elems[0]; }
+ const_reference front() const { return elems[0]; }
+ reference back() { return elems[N - 1]; }
+ const_reference back() const { return elems[N - 1]; }
+ // size is constant
+ static inline size_type size() { return N; }
+ static bool empty() { return false; }
+ static size_type max_size() { return N; }
+ enum { static_size = N };
+ /** This method has no effects in this class, but raises an exception if the expected size does not match */
+ inline void resize(const size_t nElements) { if (nElements != N) throw std::logic_error("Try to change the size of a CArray."); }
+ // swap (note: linear complexity in N, constant for given instantiation)
+ void swap(CArray& y) { std::swap_ranges(begin(), end(), y.begin()); }
+ // direct access to data (read-only)
+ const T* data() const { return elems; }
+ // use array as C array (direct read/write access to data)
+ T* data() { return elems; }
+ // assignment with type conversion
+ template CArray& operator= (const CArray& rhs) {
+ std::copy(rhs.begin(), rhs.end(), begin());
+ return *this;
+ }
+ // assign one value to all elements
+ inline void assign(const T& value) { for (size_t i = 0; i= size()) { throw std::out_of_range("CArray<>: index out of range"); } }
+ }; // end of CArray
+
+ /** Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors when DIM=-1.
+ * Fixed size version for a generic DIM:
+ */
+ template
+ struct array_or_vector_selector
+ {
+ typedef CArray container_t;
+ };
+ /** Dynamic size version */
+ template
+ struct array_or_vector_selector<-1, T> {
+ typedef std::vector container_t;
+ };
+ /** @} */
+
+ /** @addtogroup kdtrees_grp KD-tree classes and adaptors
+ * @{ */
+
+ /** kd-tree index
+ *
+ * Contains the k-d trees and other information for indexing a set of points
+ * for nearest-neighbor matching.
+ *
+ * The class "DatasetAdaptor" must provide the following interface (can be non-virtual, inlined methods):
+ *
+ * \code
+ * // Must return the number of data points
+ * inline size_t kdtree_get_point_count() const { ... }
+ *
+ * // [Only if using the metric_L2_Simple type] Must return the Euclidean (L2) distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
+ * inline DistanceType kdtree_distance(const T *p1, const size_t idx_p2,size_t size) const { ... }
+ *
+ * // Must return the dim'th component of the idx'th point in the class:
+ * inline T kdtree_get_pt(const size_t idx, int dim) const { ... }
+ *
+ * // Optional bounding-box computation: return false to default to a standard bbox computation loop.
+ * // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
+ * // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
+ * template
+ * bool kdtree_get_bbox(BBOX &bb) const
+ * {
+ * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits
+ * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits
+ * ...
+ * return true;
+ * }
+ *
+ * \endcode
+ *
+ * \tparam DatasetAdaptor The user-provided adaptor (see comments above).
+ * \tparam Distance The distance metric to use: nanoflann::metric_L1, nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc.
+ * \tparam DIM Dimensionality of data points (e.g. 3 for 3D points)
+ * \tparam IndexType Will be typically size_t or int
+ */
+ template
+ class KDTreeSingleIndexAdaptor
+ {
+ private:
+ /** Hidden copy constructor, to disallow copying indices (Not implemented) */
+ KDTreeSingleIndexAdaptor(const KDTreeSingleIndexAdaptor&);
+ public:
+ typedef typename Distance::ElementType ElementType;
+ typedef typename Distance::DistanceType DistanceType;
+ protected:
+
+ /**
+ * Array of indices to vectors in the dataset.
+ */
+ std::vector vind;
+
+ size_t m_leaf_max_size;
+
+
+ /**
+ * The dataset used by this index
+ */
+ const DatasetAdaptor &dataset; //!< The source of our data
+
+ const KDTreeSingleIndexAdaptorParams index_params;
+
+ size_t m_size; //!< Number of current points in the dataset
+ size_t m_size_at_index_build; //!< Number of points in the dataset when the index was built
+ int dim; //!< Dimensionality of each data point
+
+
+ /*--------------------- Internal Data Structures --------------------------*/
+ struct Node
+ {
+ /** Union used because a node can be either a LEAF node or a non-leaf node, so both data fields are never used simultaneously */
+ union {
+ struct {
+ IndexType left, right; //!< Indices of points in leaf node
+ } lr;
+ struct {
+ int divfeat; //!< Dimension used for subdivision.
+ DistanceType divlow, divhigh; //!< The values used for subdivision.
+ } sub;
+ };
+ Node* child1, *child2; //!< Child nodes (both=NULL mean its a leaf node)
+ };
+ typedef Node* NodePtr;
+
+
+ struct Interval
+ {
+ ElementType low, high;
+ };
+
+ /** Define "BoundingBox" as a fixed-size or variable-size container depending on "DIM" */
+ typedef typename array_or_vector_selector::container_t BoundingBox;
+
+ /** Define "distance_vector_t" as a fixed-size or variable-size container depending on "DIM" */
+ typedef typename array_or_vector_selector::container_t distance_vector_t;
+
+ /** The KD-tree used to find neighbours */
+ NodePtr root_node;
+ BoundingBox root_bbox;
+
+ /**
+ * Pooled memory allocator.
+ *
+ * Using a pooled memory allocator is more efficient
+ * than allocating memory directly when there is a large
+ * number small of memory allocations.
+ */
+ PooledAllocator pool;
+
+ public:
+
+ Distance distance;
+
+ /**
+ * KDTree constructor
+ *
+ * Refer to docs in README.md or online in https://github.com/jlblancoc/nanoflann
+ *
+ * The KD-Tree point dimension (the length of each point in the datase, e.g. 3 for 3D points)
+ * is determined by means of:
+ * - The \a DIM template parameter if >0 (highest priority)
+ * - Otherwise, the \a dimensionality parameter of this constructor.
+ *
+ * @param inputData Dataset with the input features
+ * @param params Basically, the maximum leaf node size
+ */
+ KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor& inputData, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams()) :
+ dataset(inputData), index_params(params), root_node(NULL), distance(inputData)
+ {
+ m_size = dataset.kdtree_get_point_count();
+ m_size_at_index_build = m_size;
+ dim = dimensionality;
+ if (DIM>0) dim = DIM;
+ m_leaf_max_size = params.leaf_max_size;
+
+ // Create a permutable array of indices to the input vectors.
+ init_vind();
+ }
+
+ /** Standard destructor */
+ ~KDTreeSingleIndexAdaptor() { }
+
+ /** Frees the previously-built index. Automatically called within buildIndex(). */
+ void freeIndex()
+ {
+ pool.free_all();
+ root_node = NULL;
+ m_size_at_index_build = 0;
+ }
+
+ /**
+ * Builds the index
+ */
+ void buildIndex()
+ {
+ init_vind();
+ freeIndex();
+ m_size_at_index_build = m_size;
+ if (m_size == 0) return;
+ computeBoundingBox(root_bbox);
+ root_node = divideTree(0, m_size, root_bbox); // construct the tree
+ }
+
+ /** Returns number of points in dataset */
+ size_t size() const { return m_size; }
+
+ /** Returns the length of each point in the dataset */
+ size_t veclen() const {
+ return static_cast(DIM>0 ? DIM : dim);
+ }
+
+ /**
+ * Computes the inde memory usage
+ * Returns: memory used by the index
+ */
+ size_t usedMemory() const
+ {
+ return pool.usedMemory + pool.wastedMemory + dataset.kdtree_get_point_count()*sizeof(IndexType); // pool memory and vind array memory
+ }
+
+ /** \name Query methods
+ * @{ */
+
+ /**
+ * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored inside
+ * the result object.
+ *
+ * Params:
+ * result = the result object in which the indices of the nearest-neighbors are stored
+ * vec = the vector for which to search the nearest neighbors
+ *
+ * \tparam RESULTSET Should be any ResultSet
+ * \sa knnSearch, radiusSearch
+ */
+ template
+ void findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const
+ {
+ assert(vec);
+ if (!root_node) throw std::runtime_error("[nanoflann] findNeighbors() called before building the index or no data points.");
+ float epsError = 1 + searchParams.eps;
+
+ distance_vector_t dists; // fixed or variable-sized container (depending on DIM)
+ dists.assign((DIM>0 ? DIM : dim), 0); // Fill it with zeros.
+ DistanceType distsq = computeInitialDistances(vec, dists);
+ searchLevel(result, vec, root_node, distsq, dists, epsError); // "count_leaf" parameter removed since was neither used nor returned to the user.
+ }
+
+ /**
+ * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. Their indices are stored inside
+ * the result object.
+ * \sa radiusSearch, findNeighbors
+ * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface.
+ */
+ inline void knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int /* nChecks_IGNORED */ = 10) const
+ {
+ nanoflann::KNNResultSet resultSet(num_closest);
+ resultSet.init(out_indices, out_distances_sq);
+ this->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
+ }
+
+ /**
+ * Find all the neighbors to \a query_point[0:dim-1] within a maximum radius.
+ * The output is given as a vector of pairs, of which the first element is a point index and the second the corresponding distance.
+ * Previous contents of \a IndicesDists are cleared.
+ *
+ * If searchParams.sorted==true, the output list is sorted by ascending distances.
+ *
+ * For a better performance, it is advisable to do a .reserve() on the vector if you have any wild guess about the number of expected matches.
+ *
+ * \sa knnSearch, findNeighbors, radiusSearchCustomCallback
+ * \return The number of points within the given radius (i.e. indices.size() or dists.size() )
+ */
+ size_t radiusSearch(const ElementType *query_point, const DistanceType radius, std::vector >& IndicesDists, const SearchParams& searchParams) const
+ {
+ RadiusResultSet resultSet(radius, IndicesDists);
+ const size_t nFound = radiusSearchCustomCallback(query_point, resultSet, searchParams);
+ if (searchParams.sorted)
+ std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter());
+ return nFound;
+ }
+
+ /**
+ * Just like radiusSearch() but with a custom callback class for each point found in the radius of the query.
+ * See the source of RadiusResultSet<> as a start point for your own classes.
+ * \sa radiusSearch
+ */
+ template
+ size_t radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParams& searchParams = SearchParams()) const
+ {
+ this->findNeighbors(resultSet, query_point, searchParams);
+ return resultSet.size();
+ }
+
+ /** @} */
+
+ private:
+ /** Make sure the auxiliary list \a vind has the same size than the current dataset, and re-generate if size has changed. */
+ void init_vind()
+ {
+ // Create a permutable array of indices to the input vectors.
+ m_size = dataset.kdtree_get_point_count();
+ if (vind.size() != m_size) vind.resize(m_size);
+ for (size_t i = 0; i < m_size; i++) vind[i] = i;
+ }
+
+ /// Helper accessor to the dataset points:
+ inline ElementType dataset_get(size_t idx, int component) const {
+ return dataset.kdtree_get_pt(idx, component);
+ }
+
+
+ void save_tree(FILE* stream, NodePtr tree)
+ {
+ save_value(stream, *tree);
+ if (tree->child1 != NULL) {
+ save_tree(stream, tree->child1);
+ }
+ if (tree->child2 != NULL) {
+ save_tree(stream, tree->child2);
+ }
+ }
+
+
+ void load_tree(FILE* stream, NodePtr& tree)
+ {
+ tree = pool.allocate();
+ load_value(stream, *tree);
+ if (tree->child1 != NULL) {
+ load_tree(stream, tree->child1);
+ }
+ if (tree->child2 != NULL) {
+ load_tree(stream, tree->child2);
+ }
+ }
+
+
+ void computeBoundingBox(BoundingBox& bbox)
+ {
+ bbox.resize((DIM>0 ? DIM : dim));
+ if (dataset.kdtree_get_bbox(bbox))
+ {
+ // Done! It was implemented in derived class
+ }
+ else
+ {
+ const size_t N = dataset.kdtree_get_point_count();
+ if (!N) throw std::runtime_error("[nanoflann] computeBoundingBox() called but no data points found.");
+ for (int i = 0; i<(DIM>0 ? DIM : dim); ++i) {
+ bbox[i].low =
+ bbox[i].high = dataset_get(0, i);
+ }
+ for (size_t k = 1; k0 ? DIM : dim); ++i) {
+ if (dataset_get(k, i)bbox[i].high) bbox[i].high = dataset_get(k, i);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Create a tree node that subdivides the list of vecs from vind[first]
+ * to vind[last]. The routine is called recursively on each sublist.
+ *
+ * @param left index of the first vector
+ * @param right index of the last vector
+ */
+ NodePtr divideTree(const IndexType left, const IndexType right, BoundingBox& bbox)
+ {
+ NodePtr node = pool.allocate(); // allocate memory
+
+ /* If too few exemplars remain, then make this a leaf node. */
+ if ((right - left) <= m_leaf_max_size) {
+ node->child1 = node->child2 = NULL; /* Mark as leaf node. */
+ node->lr.left = left;
+ node->lr.right = right;
+
+ // compute bounding-box of leaf points
+ for (int i = 0; i<(DIM>0 ? DIM : dim); ++i) {
+ bbox[i].low = dataset_get(vind[left], i);
+ bbox[i].high = dataset_get(vind[left], i);
+ }
+ for (IndexType k = left + 1; k0 ? DIM : dim); ++i) {
+ if (bbox[i].low>dataset_get(vind[k], i)) bbox[i].low = dataset_get(vind[k], i);
+ if (bbox[i].highsub.divfeat = cutfeat;
+
+ BoundingBox left_bbox(bbox);
+ left_bbox[cutfeat].high = cutval;
+ node->child1 = divideTree(left, left + idx, left_bbox);
+
+ BoundingBox right_bbox(bbox);
+ right_bbox[cutfeat].low = cutval;
+ node->child2 = divideTree(left + idx, right, right_bbox);
+
+ node->sub.divlow = left_bbox[cutfeat].high;
+ node->sub.divhigh = right_bbox[cutfeat].low;
+
+ for (int i = 0; i<(DIM>0 ? DIM : dim); ++i) {
+ bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
+ bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
+ }
+ }
+
+ return node;
+ }
+
+
+ void computeMinMax(IndexType* ind, IndexType count, int element, ElementType& min_elem, ElementType& max_elem)
+ {
+ min_elem = dataset_get(ind[0], element);
+ max_elem = dataset_get(ind[0], element);
+ for (IndexType i = 1; imax_elem) max_elem = val;
+ }
+ }
+
+ void middleSplit_(IndexType* ind, IndexType count, IndexType& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
+ {
+ const DistanceType EPS = static_cast(0.00001);
+ ElementType max_span = bbox[0].high - bbox[0].low;
+ for (int i = 1; i<(DIM>0 ? DIM : dim); ++i) {
+ ElementType span = bbox[i].high - bbox[i].low;
+ if (span>max_span) {
+ max_span = span;
+ }
+ }
+ ElementType max_spread = -1;
+ cutfeat = 0;
+ for (int i = 0; i<(DIM>0 ? DIM : dim); ++i) {
+ ElementType span = bbox[i].high - bbox[i].low;
+ if (span>(1 - EPS)*max_span) {
+ ElementType min_elem, max_elem;
+ computeMinMax(ind, count, cutfeat, min_elem, max_elem);
+ ElementType spread = max_elem - min_elem;;
+ if (spread>max_spread) {
+ cutfeat = i;
+ max_spread = spread;
+ }
+ }
+ }
+ // split in the middle
+ DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2;
+ ElementType min_elem, max_elem;
+ computeMinMax(ind, count, cutfeat, min_elem, max_elem);
+
+ if (split_valmax_elem) cutval = max_elem;
+ else cutval = split_val;
+
+ IndexType lim1, lim2;
+ planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
+
+ if (lim1>count / 2) index = lim1;
+ else if (lim2cutval
+ */
+ void planeSplit(IndexType* ind, const IndexType count, int cutfeat, DistanceType cutval, IndexType& lim1, IndexType& lim2)
+ {
+ /* Move vector indices for left subtree to front of list. */
+ IndexType left = 0;
+ IndexType right = count - 1;
+ for (;;) {
+ while (left <= right && dataset_get(ind[left], cutfeat)= cutval) --right;
+ if (left>right || !right) break; // "!right" was added to support unsigned Index types
+ std::swap(ind[left], ind[right]);
+ ++left;
+ --right;
+ }
+ /* If either list is empty, it means that all remaining features
+ * are identical. Split in the middle to maintain a balanced tree.
+ */
+ lim1 = left;
+ right = count - 1;
+ for (;;) {
+ while (left <= right && dataset_get(ind[left], cutfeat) <= cutval) ++left;
+ while (right && left <= right && dataset_get(ind[right], cutfeat)>cutval) --right;
+ if (left>right || !right) break; // "!right" was added to support unsigned Index types
+ std::swap(ind[left], ind[right]);
+ ++left;
+ --right;
+ }
+ lim2 = left;
+ }
+
+ DistanceType computeInitialDistances(const ElementType* vec, distance_vector_t& dists) const
+ {
+ assert(vec);
+ DistanceType distsq = DistanceType();
+
+ for (int i = 0; i < (DIM>0 ? DIM : dim); ++i) {
+ if (vec[i] < root_bbox[i].low) {
+ dists[i] = distance.accum_dist(vec[i], root_bbox[i].low, i);
+ distsq += dists[i];
+ }
+ if (vec[i] > root_bbox[i].high) {
+ dists[i] = distance.accum_dist(vec[i], root_bbox[i].high, i);
+ distsq += dists[i];
+ }
+ }
+
+ return distsq;
+ }
+
+ /**
+ * Performs an exact search in the tree starting from a node.
+ * \tparam RESULTSET Should be any ResultSet
+ */
+ template
+ void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq,
+ distance_vector_t& dists, const float epsError) const
+ {
+ /* If this is a leaf node, then do check and return. */
+ if ((node->child1 == NULL) && (node->child2 == NULL)) {
+ //count_leaf += (node->lr.right-node->lr.left); // Removed since was neither used nor returned to the user.
+ DistanceType worst_dist = result_set.worstDist();
+ for (IndexType i = node->lr.left; ilr.right; ++i) {
+ const IndexType index = vind[i];// reorder... : i;
+ DistanceType dist = distance(vec, index, (DIM>0 ? DIM : dim));
+ if (distsub.divfeat;
+ ElementType val = vec[idx];
+ DistanceType diff1 = val - node->sub.divlow;
+ DistanceType diff2 = val - node->sub.divhigh;
+
+ NodePtr bestChild;
+ NodePtr otherChild;
+ DistanceType cut_dist;
+ if ((diff1 + diff2)<0) {
+ bestChild = node->child1;
+ otherChild = node->child2;
+ cut_dist = distance.accum_dist(val, node->sub.divhigh, idx);
+ }
+ else {
+ bestChild = node->child2;
+ otherChild = node->child1;
+ cut_dist = distance.accum_dist(val, node->sub.divlow, idx);
+ }
+
+ /* Call recursively to search next level down. */
+ searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError);
+
+ DistanceType dst = dists[idx];
+ mindistsq = mindistsq + cut_dist - dst;
+ dists[idx] = cut_dist;
+ if (mindistsq*epsError <= result_set.worstDist()) {
+ searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError);
+ }
+ dists[idx] = dst;
+ }
+
+ public:
+ /** Stores the index in a binary file.
+ * IMPORTANT NOTE: The set of data points is NOT stored in the file, so when loading the index object it must be constructed associated to the same source of data points used while building it.
+ * See the example: examples/saveload_example.cpp
+ * \sa loadIndex */
+ void saveIndex(FILE* stream)
+ {
+ save_value(stream, m_size);
+ save_value(stream, dim);
+ save_value(stream, root_bbox);
+ save_value(stream, m_leaf_max_size);
+ save_value(stream, vind);
+ save_tree(stream, root_node);
+ }
+
+ /** Loads a previous index from a binary file.
+ * IMPORTANT NOTE: The set of data points is NOT stored in the file, so the index object must be constructed associated to the same source of data points used while building the index.
+ * See the example: examples/saveload_example.cpp
+ * \sa loadIndex */
+ void loadIndex(FILE* stream)
+ {
+ load_value(stream, m_size);
+ load_value(stream, dim);
+ load_value(stream, root_bbox);
+ load_value(stream, m_leaf_max_size);
+ load_value(stream, vind);
+ load_tree(stream, root_node);
+ }
+
+ }; // class KDTree
+
+
+ /** An L2-metric KD-tree adaptor for working with data directly stored in an Eigen Matrix, without duplicating the data storage.
+ * Each row in the matrix represents a point in the state space.
+ *
+ * Example of usage:
+ * \code
+ * Eigen::Matrix mat;
+ * // Fill out "mat"...
+ *
+ * typedef KDTreeEigenMatrixAdaptor< Eigen::Matrix > my_kd_tree_t;
+ * const int max_leaf = 10;
+ * my_kd_tree_t mat_index(dimdim, mat, max_leaf );
+ * mat_index.index->buildIndex();
+ * mat_index.index->...
+ * \endcode
+ *
+ * \tparam DIM If set to >0, it specifies a compile-time fixed dimensionality for the points in the data set, allowing more compiler optimizations.
+ * \tparam Distance The distance metric to use: nanoflann::metric_L1, nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc.
+ */
+ template
+ struct KDTreeEigenMatrixAdaptor
+ {
+ typedef KDTreeEigenMatrixAdaptor self_t;
+ typedef typename MatrixType::Scalar num_t;
+ typedef typename MatrixType::Index IndexType;
+ typedef typename Distance::template traits::distance_t metric_t;
+ typedef KDTreeSingleIndexAdaptor< metric_t, self_t, DIM, IndexType> index_t;
+
+ index_t* index; //! The kd-tree index for the user to call its methods as usual with any other FLANN index.
+
+ /// Constructor: takes a const ref to the matrix object with the data points
+ KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size = 10) : m_data_matrix(mat)
+ {
+ const IndexType dims = mat.cols();
+ if (dims != dimensionality) throw std::runtime_error("Error: 'dimensionality' must match column count in data matrix");
+ if (DIM>0 && static_cast(dims) != DIM)
+ throw std::runtime_error("Data set dimensionality does not match the 'DIM' template argument");
+ index = new index_t(dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size));
+ index->buildIndex();
+ }
+ private:
+ /** Hidden copy constructor, to disallow copying this class (Not implemented) */
+ KDTreeEigenMatrixAdaptor(const self_t&);
+ public:
+
+ ~KDTreeEigenMatrixAdaptor() {
+ delete index;
+ }
+
+ const MatrixType &m_data_matrix;
+
+ /** Query for the \a num_closest closest points to a given point (entered as query_point[0:dim-1]).
+ * Note that this is a short-cut method for index->findNeighbors().
+ * The user can also call index->... methods as desired.
+ * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface.
+ */
+ inline void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq, const int /* nChecks_IGNORED */ = 10) const
+ {
+ nanoflann::KNNResultSet resultSet(num_closest);
+ resultSet.init(out_indices, out_distances_sq);
+ index->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
+ }
+
+ /** @name Interface expected by KDTreeSingleIndexAdaptor
+ * @{ */
+
+ const self_t & derived() const {
+ return *this;
+ }
+ self_t & derived() {
+ return *this;
+ }
+
+ // Must return the number of data points
+ inline size_t kdtree_get_point_count() const {
+ return m_data_matrix.rows();
+ }
+
+ // Returns the L2 distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
+ inline num_t kdtree_distance(const num_t *p1, const IndexType idx_p2, IndexType size) const
+ {
+ num_t s = 0;
+ for (IndexType i = 0; i
+ bool kdtree_get_bbox(BBOX& /*bb*/) const {
+ return false;
+ }
+
+ /** @} */
+
+ }; // end of KDTreeEigenMatrixAdaptor
+ /** @} */
+
+ /** @} */ // end of grouping
+} // end of NS
+
+
+#endif /* NANOFLANN_HPP_ */
diff --git a/include/opencv/cv.h b/include/opencv/cv.h
new file mode 100644
index 0000000..77d0971
--- /dev/null
+++ b/include/opencv/cv.h
@@ -0,0 +1,82 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_CV_H__
+#define __OPENCV_OLD_CV_H__
+
+#if defined(_MSC_VER)
+ #define CV_DO_PRAGMA(x) __pragma(x)
+ #define __CVSTR2__(x) #x
+ #define __CVSTR1__(x) __CVSTR2__(x)
+ #define __CVMSVCLOC__ __FILE__ "("__CVSTR1__(__LINE__)") : "
+ #define CV_MSG_PRAGMA(_msg) CV_DO_PRAGMA(message (__CVMSVCLOC__ _msg))
+#elif defined(__GNUC__)
+ #define CV_DO_PRAGMA(x) _Pragma (#x)
+ #define CV_MSG_PRAGMA(_msg) CV_DO_PRAGMA(message (_msg))
+#else
+ #define CV_DO_PRAGMA(x)
+ #define CV_MSG_PRAGMA(_msg)
+#endif
+#define CV_WARNING(x) CV_MSG_PRAGMA("Warning: " #x)
+
+//CV_WARNING("This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module")
+
+#include "opencv2/core/core_c.h"
+#include "opencv2/core/core.hpp"
+#include "opencv2/imgproc/imgproc_c.h"
+#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/video/tracking.hpp"
+#include "opencv2/features2d/features2d.hpp"
+#include "opencv2/flann/flann.hpp"
+#include "opencv2/calib3d/calib3d.hpp"
+#include "opencv2/objdetect/objdetect.hpp"
+#include "opencv2/legacy/compat.hpp"
+
+#if !defined(CV_IMPL)
+#define CV_IMPL extern "C"
+#endif //CV_IMPL
+
+#if defined(__cplusplus)
+#include "opencv2/core/internal.hpp"
+#endif //__cplusplus
+
+#endif // __OPENCV_OLD_CV_H_
diff --git a/include/opencv/cv.hpp b/include/opencv/cv.hpp
new file mode 100644
index 0000000..37b523b
--- /dev/null
+++ b/include/opencv/cv.hpp
@@ -0,0 +1,52 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_CV_HPP__
+#define __OPENCV_OLD_CV_HPP__
+
+//#if defined(__GNUC__)
+//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
+//#endif
+
+#include
+
+#endif
diff --git a/include/opencv/cvaux.h b/include/opencv/cvaux.h
new file mode 100644
index 0000000..b15d068
--- /dev/null
+++ b/include/opencv/cvaux.h
@@ -0,0 +1,65 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// Intel License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_AUX_H__
+#define __OPENCV_OLD_AUX_H__
+
+//#if defined(__GNUC__)
+//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
+//#endif
+
+#include "opencv2/core/core_c.h"
+#include "opencv2/core/core.hpp"
+#include "opencv2/imgproc/imgproc_c.h"
+#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/video/tracking.hpp"
+#include "opencv2/video/background_segm.hpp"
+#include "opencv2/features2d/features2d.hpp"
+#include "opencv2/calib3d/calib3d.hpp"
+#include "opencv2/objdetect/objdetect.hpp"
+#include "opencv2/legacy/legacy.hpp"
+#include "opencv2/legacy/compat.hpp"
+#include "opencv2/legacy/blobtrack.hpp"
+#include "opencv2/contrib/contrib.hpp"
+
+#endif
+
+/* End of file. */
diff --git a/include/opencv/cvaux.hpp b/include/opencv/cvaux.hpp
new file mode 100644
index 0000000..952210b
--- /dev/null
+++ b/include/opencv/cvaux.hpp
@@ -0,0 +1,51 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// Intel License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_AUX_HPP__
+#define __OPENCV_OLD_AUX_HPP__
+
+//#if defined(__GNUC__)
+//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
+//#endif
+
+#include
+
+#endif
diff --git a/include/opencv/cvwimage.h b/include/opencv/cvwimage.h
new file mode 100644
index 0000000..de89c92
--- /dev/null
+++ b/include/opencv/cvwimage.h
@@ -0,0 +1,46 @@
+///////////////////////////////////////////////////////////////////////////////
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to
+// this license. If you do not agree to this license, do not download,
+// install, copy or use the software.
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2008, Google, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation or contributors may not be used to endorse
+// or promote products derived from this software without specific
+// prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is"
+// and any express or implied warranties, including, but not limited to, the
+// implied warranties of merchantability and fitness for a particular purpose
+// are disclaimed. In no event shall the Intel Corporation or contributors be
+// liable for any direct, indirect, incidental, special, exemplary, or
+// consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+
+
+#ifndef __OPENCV_OLD_WIMAGE_HPP__
+#define __OPENCV_OLD_WIMAGE_HPP__
+
+#include "opencv2/core/wimage.hpp"
+
+#endif
diff --git a/include/opencv/cxcore.h b/include/opencv/cxcore.h
new file mode 100644
index 0000000..d52ad4f
--- /dev/null
+++ b/include/opencv/cxcore.h
@@ -0,0 +1,53 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_CXCORE_H__
+#define __OPENCV_OLD_CXCORE_H__
+
+//#if defined(__GNUC__)
+//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
+//#endif
+
+#include "opencv2/core/core_c.h"
+#include "opencv2/core/core.hpp"
+
+#endif
diff --git a/include/opencv/cxcore.hpp b/include/opencv/cxcore.hpp
new file mode 100644
index 0000000..033b365
--- /dev/null
+++ b/include/opencv/cxcore.hpp
@@ -0,0 +1,52 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_CXCORE_HPP__
+#define __OPENCV_OLD_CXCORE_HPP__
+
+//#if defined(__GNUC__)
+//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
+//#endif
+
+#include
+
+#endif
diff --git a/include/opencv/cxeigen.hpp b/include/opencv/cxeigen.hpp
new file mode 100644
index 0000000..1f04d1a
--- /dev/null
+++ b/include/opencv/cxeigen.hpp
@@ -0,0 +1,48 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_EIGEN_HPP__
+#define __OPENCV_OLD_EIGEN_HPP__
+
+#include "opencv2/core/eigen.hpp"
+
+#endif
diff --git a/include/opencv/cxmisc.h b/include/opencv/cxmisc.h
new file mode 100644
index 0000000..6446944
--- /dev/null
+++ b/include/opencv/cxmisc.h
@@ -0,0 +1,6 @@
+#ifndef __OPENCV_OLD_CXMISC_H__
+#define __OPENCV_OLD_CXMISC_H__
+
+#include "opencv2/core/internal.hpp"
+
+#endif
diff --git a/include/opencv/highgui.h b/include/opencv/highgui.h
new file mode 100644
index 0000000..9725c9f
--- /dev/null
+++ b/include/opencv/highgui.h
@@ -0,0 +1,50 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// Intel License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_HIGHGUI_H__
+#define __OPENCV_OLD_HIGHGUI_H__
+
+#include "opencv2/core/core_c.h"
+#include "opencv2/core/core.hpp"
+#include "opencv2/highgui/highgui_c.h"
+#include "opencv2/highgui/highgui.hpp"
+
+#endif
diff --git a/include/opencv/ml.h b/include/opencv/ml.h
new file mode 100644
index 0000000..0383a2f
--- /dev/null
+++ b/include/opencv/ml.h
@@ -0,0 +1,48 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// Intel License Agreement
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_OLD_ML_H__
+#define __OPENCV_OLD_ML_H__
+
+#include "opencv2/core/core_c.h"
+#include "opencv2/core/core.hpp"
+#include "opencv2/ml/ml.hpp"
+
+#endif
diff --git a/include/opencv2/calib3d/calib3d.hpp b/include/opencv2/calib3d/calib3d.hpp
new file mode 100644
index 0000000..f213a11
--- /dev/null
+++ b/include/opencv2/calib3d/calib3d.hpp
@@ -0,0 +1,751 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_CALIB3D_HPP__
+#define __OPENCV_CALIB3D_HPP__
+
+#include "opencv2/core/core.hpp"
+#include "opencv2/features2d/features2d.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************************\
+* Camera Calibration, Pose Estimation and Stereo *
+\****************************************************************************************/
+
+typedef struct CvPOSITObject CvPOSITObject;
+
+/* Allocates and initializes CvPOSITObject structure before doing cvPOSIT */
+CVAPI(CvPOSITObject*) cvCreatePOSITObject( CvPoint3D32f* points, int point_count );
+
+
+/* Runs POSIT (POSe from ITeration) algorithm for determining 3d position of
+ an object given its model and projection in a weak-perspective case */
+CVAPI(void) cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* image_points,
+ double focal_length, CvTermCriteria criteria,
+ float* rotation_matrix, float* translation_vector);
+
+/* Releases CvPOSITObject structure */
+CVAPI(void) cvReleasePOSITObject( CvPOSITObject** posit_object );
+
+/* updates the number of RANSAC iterations */
+CVAPI(int) cvRANSACUpdateNumIters( double p, double err_prob,
+ int model_points, int max_iters );
+
+CVAPI(void) cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst );
+
+/* Calculates fundamental matrix given a set of corresponding points */
+#define CV_FM_7POINT 1
+#define CV_FM_8POINT 2
+
+#define CV_LMEDS 4
+#define CV_RANSAC 8
+
+#define CV_FM_LMEDS_ONLY CV_LMEDS
+#define CV_FM_RANSAC_ONLY CV_RANSAC
+#define CV_FM_LMEDS CV_LMEDS
+#define CV_FM_RANSAC CV_RANSAC
+
+enum
+{
+ CV_ITERATIVE = 0,
+ CV_EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation"
+ CV_P3P = 2 // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem"
+};
+
+CVAPI(int) cvFindFundamentalMat( const CvMat* points1, const CvMat* points2,
+ CvMat* fundamental_matrix,
+ int method CV_DEFAULT(CV_FM_RANSAC),
+ double param1 CV_DEFAULT(3.), double param2 CV_DEFAULT(0.99),
+ CvMat* status CV_DEFAULT(NULL) );
+
+/* For each input point on one of images
+ computes parameters of the corresponding
+ epipolar line on the other image */
+CVAPI(void) cvComputeCorrespondEpilines( const CvMat* points,
+ int which_image,
+ const CvMat* fundamental_matrix,
+ CvMat* correspondent_lines );
+
+/* Triangulation functions */
+
+CVAPI(void) cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2,
+ CvMat* projPoints1, CvMat* projPoints2,
+ CvMat* points4D);
+
+CVAPI(void) cvCorrectMatches(CvMat* F, CvMat* points1, CvMat* points2,
+ CvMat* new_points1, CvMat* new_points2);
+
+
+/* Computes the optimal new camera matrix according to the free scaling parameter alpha:
+ alpha=0 - only valid pixels will be retained in the undistorted image
+ alpha=1 - all the source image pixels will be retained in the undistorted image
+*/
+CVAPI(void) cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix,
+ const CvMat* dist_coeffs,
+ CvSize image_size, double alpha,
+ CvMat* new_camera_matrix,
+ CvSize new_imag_size CV_DEFAULT(cvSize(0,0)),
+ CvRect* valid_pixel_ROI CV_DEFAULT(0),
+ int center_principal_point CV_DEFAULT(0));
+
+/* Converts rotation vector to rotation matrix or vice versa */
+CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst,
+ CvMat* jacobian CV_DEFAULT(0) );
+
+/* Finds perspective transformation between the object plane and image (view) plane */
+CVAPI(int) cvFindHomography( const CvMat* src_points,
+ const CvMat* dst_points,
+ CvMat* homography,
+ int method CV_DEFAULT(0),
+ double ransacReprojThreshold CV_DEFAULT(3),
+ CvMat* mask CV_DEFAULT(0));
+
+/* Computes RQ decomposition for 3x3 matrices */
+CVAPI(void) cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ,
+ CvMat *matrixQx CV_DEFAULT(NULL),
+ CvMat *matrixQy CV_DEFAULT(NULL),
+ CvMat *matrixQz CV_DEFAULT(NULL),
+ CvPoint3D64f *eulerAngles CV_DEFAULT(NULL));
+
+/* Computes projection matrix decomposition */
+CVAPI(void) cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr,
+ CvMat *rotMatr, CvMat *posVect,
+ CvMat *rotMatrX CV_DEFAULT(NULL),
+ CvMat *rotMatrY CV_DEFAULT(NULL),
+ CvMat *rotMatrZ CV_DEFAULT(NULL),
+ CvPoint3D64f *eulerAngles CV_DEFAULT(NULL));
+
+/* Computes d(AB)/dA and d(AB)/dB */
+CVAPI(void) cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB );
+
+/* Computes r3 = rodrigues(rodrigues(r2)*rodrigues(r1)),
+ t3 = rodrigues(r2)*t1 + t2 and the respective derivatives */
+CVAPI(void) cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1,
+ const CvMat* _rvec2, const CvMat* _tvec2,
+ CvMat* _rvec3, CvMat* _tvec3,
+ CvMat* dr3dr1 CV_DEFAULT(0), CvMat* dr3dt1 CV_DEFAULT(0),
+ CvMat* dr3dr2 CV_DEFAULT(0), CvMat* dr3dt2 CV_DEFAULT(0),
+ CvMat* dt3dr1 CV_DEFAULT(0), CvMat* dt3dt1 CV_DEFAULT(0),
+ CvMat* dt3dr2 CV_DEFAULT(0), CvMat* dt3dt2 CV_DEFAULT(0) );
+
+/* Projects object points to the view plane using
+ the specified extrinsic and intrinsic camera parameters */
+CVAPI(void) cvProjectPoints2( const CvMat* object_points, const CvMat* rotation_vector,
+ const CvMat* translation_vector, const CvMat* camera_matrix,
+ const CvMat* distortion_coeffs, CvMat* image_points,
+ CvMat* dpdrot CV_DEFAULT(NULL), CvMat* dpdt CV_DEFAULT(NULL),
+ CvMat* dpdf CV_DEFAULT(NULL), CvMat* dpdc CV_DEFAULT(NULL),
+ CvMat* dpddist CV_DEFAULT(NULL),
+ double aspect_ratio CV_DEFAULT(0));
+
+/* Finds extrinsic camera parameters from
+ a few known corresponding point pairs and intrinsic parameters */
+CVAPI(void) cvFindExtrinsicCameraParams2( const CvMat* object_points,
+ const CvMat* image_points,
+ const CvMat* camera_matrix,
+ const CvMat* distortion_coeffs,
+ CvMat* rotation_vector,
+ CvMat* translation_vector,
+ int use_extrinsic_guess CV_DEFAULT(0) );
+
+/* Computes initial estimate of the intrinsic camera parameters
+ in case of planar calibration target (e.g. chessboard) */
+CVAPI(void) cvInitIntrinsicParams2D( const CvMat* object_points,
+ const CvMat* image_points,
+ const CvMat* npoints, CvSize image_size,
+ CvMat* camera_matrix,
+ double aspect_ratio CV_DEFAULT(1.) );
+
+#define CV_CALIB_CB_ADAPTIVE_THRESH 1
+#define CV_CALIB_CB_NORMALIZE_IMAGE 2
+#define CV_CALIB_CB_FILTER_QUADS 4
+#define CV_CALIB_CB_FAST_CHECK 8
+
+// Performs a fast check if a chessboard is in the input image. This is a workaround to
+// a problem of cvFindChessboardCorners being slow on images with no chessboard
+// - src: input image
+// - size: chessboard size
+// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
+// 0 if there is no chessboard, -1 in case of error
+CVAPI(int) cvCheckChessboard(IplImage* src, CvSize size);
+
+ /* Detects corners on a chessboard calibration pattern */
+CVAPI(int) cvFindChessboardCorners( const void* image, CvSize pattern_size,
+ CvPoint2D32f* corners,
+ int* corner_count CV_DEFAULT(NULL),
+ int flags CV_DEFAULT(CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE) );
+
+/* Draws individual chessboard corners or the whole chessboard detected */
+CVAPI(void) cvDrawChessboardCorners( CvArr* image, CvSize pattern_size,
+ CvPoint2D32f* corners,
+ int count, int pattern_was_found );
+
+#define CV_CALIB_USE_INTRINSIC_GUESS 1
+#define CV_CALIB_FIX_ASPECT_RATIO 2
+#define CV_CALIB_FIX_PRINCIPAL_POINT 4
+#define CV_CALIB_ZERO_TANGENT_DIST 8
+#define CV_CALIB_FIX_FOCAL_LENGTH 16
+#define CV_CALIB_FIX_K1 32
+#define CV_CALIB_FIX_K2 64
+#define CV_CALIB_FIX_K3 128
+#define CV_CALIB_FIX_K4 2048
+#define CV_CALIB_FIX_K5 4096
+#define CV_CALIB_FIX_K6 8192
+#define CV_CALIB_RATIONAL_MODEL 16384
+
+/* Finds intrinsic and extrinsic camera parameters
+ from a few views of known calibration pattern */
+CVAPI(double) cvCalibrateCamera2( const CvMat* object_points,
+ const CvMat* image_points,
+ const CvMat* point_counts,
+ CvSize image_size,
+ CvMat* camera_matrix,
+ CvMat* distortion_coeffs,
+ CvMat* rotation_vectors CV_DEFAULT(NULL),
+ CvMat* translation_vectors CV_DEFAULT(NULL),
+ int flags CV_DEFAULT(0),
+ CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria(
+ CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) );
+
+/* Computes various useful characteristics of the camera from the data computed by
+ cvCalibrateCamera2 */
+CVAPI(void) cvCalibrationMatrixValues( const CvMat *camera_matrix,
+ CvSize image_size,
+ double aperture_width CV_DEFAULT(0),
+ double aperture_height CV_DEFAULT(0),
+ double *fovx CV_DEFAULT(NULL),
+ double *fovy CV_DEFAULT(NULL),
+ double *focal_length CV_DEFAULT(NULL),
+ CvPoint2D64f *principal_point CV_DEFAULT(NULL),
+ double *pixel_aspect_ratio CV_DEFAULT(NULL));
+
+#define CV_CALIB_FIX_INTRINSIC 256
+#define CV_CALIB_SAME_FOCAL_LENGTH 512
+
+/* Computes the transformation from one camera coordinate system to another one
+ from a few correspondent views of the same calibration target. Optionally, calibrates
+ both cameras */
+CVAPI(double) cvStereoCalibrate( const CvMat* object_points, const CvMat* image_points1,
+ const CvMat* image_points2, const CvMat* npoints,
+ CvMat* camera_matrix1, CvMat* dist_coeffs1,
+ CvMat* camera_matrix2, CvMat* dist_coeffs2,
+ CvSize image_size, CvMat* R, CvMat* T,
+ CvMat* E CV_DEFAULT(0), CvMat* F CV_DEFAULT(0),
+ CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria(
+ CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6)),
+ int flags CV_DEFAULT(CV_CALIB_FIX_INTRINSIC));
+
+#define CV_CALIB_ZERO_DISPARITY 1024
+
+/* Computes 3D rotations (+ optional shift) for each camera coordinate system to make both
+ views parallel (=> to make all the epipolar lines horizontal or vertical) */
+CVAPI(void) cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_matrix2,
+ const CvMat* dist_coeffs1, const CvMat* dist_coeffs2,
+ CvSize image_size, const CvMat* R, const CvMat* T,
+ CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2,
+ CvMat* Q CV_DEFAULT(0),
+ int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY),
+ double alpha CV_DEFAULT(-1),
+ CvSize new_image_size CV_DEFAULT(cvSize(0,0)),
+ CvRect* valid_pix_ROI1 CV_DEFAULT(0),
+ CvRect* valid_pix_ROI2 CV_DEFAULT(0));
+
+/* Computes rectification transformations for uncalibrated pair of images using a set
+ of point correspondences */
+CVAPI(int) cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2,
+ const CvMat* F, CvSize img_size,
+ CvMat* H1, CvMat* H2,
+ double threshold CV_DEFAULT(5));
+
+
+
+/* stereo correspondence parameters and functions */
+
+#define CV_STEREO_BM_NORMALIZED_RESPONSE 0
+#define CV_STEREO_BM_XSOBEL 1
+
+/* Block matching algorithm structure */
+typedef struct CvStereoBMState
+{
+ // pre-filtering (normalization of input images)
+ int preFilterType; // =CV_STEREO_BM_NORMALIZED_RESPONSE now
+ int preFilterSize; // averaging window size: ~5x5..21x21
+ int preFilterCap; // the output of pre-filtering is clipped by [-preFilterCap,preFilterCap]
+
+ // correspondence using Sum of Absolute Difference (SAD)
+ int SADWindowSize; // ~5x5..21x21
+ int minDisparity; // minimum disparity (can be negative)
+ int numberOfDisparities; // maximum disparity - minimum disparity (> 0)
+
+ // post-filtering
+ int textureThreshold; // the disparity is only computed for pixels
+ // with textured enough neighborhood
+ int uniquenessRatio; // accept the computed disparity d* only if
+ // SAD(d) >= SAD(d*)*(1 + uniquenessRatio/100.)
+ // for any d != d*+/-1 within the search range.
+ int speckleWindowSize; // disparity variation window
+ int speckleRange; // acceptable range of variation in window
+
+ int trySmallerWindows; // if 1, the results may be more accurate,
+ // at the expense of slower processing
+ CvRect roi1, roi2;
+ int disp12MaxDiff;
+
+ // temporary buffers
+ CvMat* preFilteredImg0;
+ CvMat* preFilteredImg1;
+ CvMat* slidingSumBuf;
+ CvMat* cost;
+ CvMat* disp;
+} CvStereoBMState;
+
+#define CV_STEREO_BM_BASIC 0
+#define CV_STEREO_BM_FISH_EYE 1
+#define CV_STEREO_BM_NARROW 2
+
+CVAPI(CvStereoBMState*) cvCreateStereoBMState(int preset CV_DEFAULT(CV_STEREO_BM_BASIC),
+ int numberOfDisparities CV_DEFAULT(0));
+
+CVAPI(void) cvReleaseStereoBMState( CvStereoBMState** state );
+
+CVAPI(void) cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right,
+ CvArr* disparity, CvStereoBMState* state );
+
+CVAPI(CvRect) cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity,
+ int numberOfDisparities, int SADWindowSize );
+
+CVAPI(void) cvValidateDisparity( CvArr* disparity, const CvArr* cost,
+ int minDisparity, int numberOfDisparities,
+ int disp12MaxDiff CV_DEFAULT(1) );
+
+/* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */
+CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage,
+ CvArr* _3dImage, const CvMat* Q,
+ int handleMissingValues CV_DEFAULT(0) );
+
+
+#ifdef __cplusplus
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+class CV_EXPORTS CvLevMarq
+{
+public:
+ CvLevMarq();
+ CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria=
+ cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),
+ bool completeSymmFlag=false );
+ ~CvLevMarq();
+ void init( int nparams, int nerrs, CvTermCriteria criteria=
+ cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),
+ bool completeSymmFlag=false );
+ bool update( const CvMat*& param, CvMat*& J, CvMat*& err );
+ bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm );
+
+ void clear();
+ void step();
+ enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 };
+
+ cv::Ptr mask;
+ cv::Ptr prevParam;
+ cv::Ptr param;
+ cv::Ptr J;
+ cv::Ptr err;
+ cv::Ptr JtJ;
+ cv::Ptr JtJN;
+ cv::Ptr JtErr;
+ cv::Ptr JtJV;
+ cv::Ptr JtJW;
+ double prevErrNorm, errNorm;
+ int lambdaLg10;
+ CvTermCriteria criteria;
+ int state;
+ int iters;
+ bool completeSymmFlag;
+};
+
+namespace cv
+{
+//! converts rotation vector to rotation matrix or vice versa using Rodrigues transformation
+CV_EXPORTS_W void Rodrigues(InputArray src, OutputArray dst, OutputArray jacobian=noArray());
+
+//! type of the robust estimation algorithm
+enum
+{
+ LMEDS=CV_LMEDS, //!< least-median algorithm
+ RANSAC=CV_RANSAC //!< RANSAC algorithm
+};
+
+//! computes the best-fit perspective transformation mapping srcPoints to dstPoints.
+CV_EXPORTS_W Mat findHomography( InputArray srcPoints, InputArray dstPoints,
+ int method=0, double ransacReprojThreshold=3,
+ OutputArray mask=noArray());
+
+//! variant of findHomography for backward compatibility
+CV_EXPORTS Mat findHomography( InputArray srcPoints, InputArray dstPoints,
+ OutputArray mask, int method=0, double ransacReprojThreshold=3);
+
+//! Computes RQ decomposition of 3x3 matrix
+CV_EXPORTS_W Vec3d RQDecomp3x3( InputArray src, OutputArray mtxR, OutputArray mtxQ,
+ OutputArray Qx=noArray(),
+ OutputArray Qy=noArray(),
+ OutputArray Qz=noArray());
+
+//! Decomposes the projection matrix into camera matrix and the rotation martix and the translation vector
+CV_EXPORTS_W void decomposeProjectionMatrix( InputArray projMatrix, OutputArray cameraMatrix,
+ OutputArray rotMatrix, OutputArray transVect,
+ OutputArray rotMatrixX=noArray(),
+ OutputArray rotMatrixY=noArray(),
+ OutputArray rotMatrixZ=noArray(),
+ OutputArray eulerAngles=noArray() );
+
+//! computes derivatives of the matrix product w.r.t each of the multiplied matrix coefficients
+CV_EXPORTS_W void matMulDeriv( InputArray A, InputArray B,
+ OutputArray dABdA,
+ OutputArray dABdB );
+
+//! composes 2 [R|t] transformations together. Also computes the derivatives of the result w.r.t the arguments
+CV_EXPORTS_W void composeRT( InputArray rvec1, InputArray tvec1,
+ InputArray rvec2, InputArray tvec2,
+ OutputArray rvec3, OutputArray tvec3,
+ OutputArray dr3dr1=noArray(), OutputArray dr3dt1=noArray(),
+ OutputArray dr3dr2=noArray(), OutputArray dr3dt2=noArray(),
+ OutputArray dt3dr1=noArray(), OutputArray dt3dt1=noArray(),
+ OutputArray dt3dr2=noArray(), OutputArray dt3dt2=noArray() );
+
+//! projects points from the model coordinate space to the image coordinates. Also computes derivatives of the image coordinates w.r.t the intrinsic and extrinsic camera parameters
+CV_EXPORTS_W void projectPoints( InputArray objectPoints,
+ InputArray rvec, InputArray tvec,
+ InputArray cameraMatrix, InputArray distCoeffs,
+ OutputArray imagePoints,
+ OutputArray jacobian=noArray(),
+ double aspectRatio=0 );
+
+//! computes the camera pose from a few 3D points and the corresponding projections. The outliers are not handled.
+enum
+{
+ ITERATIVE=CV_ITERATIVE,
+ EPNP=CV_EPNP,
+ P3P=CV_P3P
+};
+CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints,
+ InputArray cameraMatrix, InputArray distCoeffs,
+ OutputArray rvec, OutputArray tvec,
+ bool useExtrinsicGuess=false, int flags=ITERATIVE);
+
+//! computes the camera pose from a few 3D points and the corresponding projections. The outliers are possible.
+CV_EXPORTS_W void solvePnPRansac( InputArray objectPoints,
+ InputArray imagePoints,
+ InputArray cameraMatrix,
+ InputArray distCoeffs,
+ OutputArray rvec,
+ OutputArray tvec,
+ bool useExtrinsicGuess = false,
+ int iterationsCount = 100,
+ float reprojectionError = 8.0,
+ int minInliersCount = 100,
+ OutputArray inliers = noArray(),
+ int flags = ITERATIVE);
+
+//! initializes camera matrix from a few 3D points and the corresponding projections.
+CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints,
+ InputArrayOfArrays imagePoints,
+ Size imageSize, double aspectRatio=1. );
+
+enum { CALIB_CB_ADAPTIVE_THRESH = 1, CALIB_CB_NORMALIZE_IMAGE = 2,
+ CALIB_CB_FILTER_QUADS = 4, CALIB_CB_FAST_CHECK = 8 };
+
+//! finds checkerboard pattern of the specified size in the image
+CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize,
+ OutputArray corners,
+ int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE );
+
+//! finds subpixel-accurate positions of the chessboard corners
+CV_EXPORTS bool find4QuadCornerSubpix(InputArray img, InputOutputArray corners, Size region_size);
+
+//! draws the checkerboard pattern (found or partly found) in the image
+CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize,
+ InputArray corners, bool patternWasFound );
+
+enum { CALIB_CB_SYMMETRIC_GRID = 1, CALIB_CB_ASYMMETRIC_GRID = 2,
+ CALIB_CB_CLUSTERING = 4 };
+
+//! finds circles' grid pattern of the specified size in the image
+CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
+ OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID,
+ const Ptr &blobDetector = new SimpleBlobDetector());
+
+//! the deprecated function. Use findCirclesGrid() instead of it.
+CV_EXPORTS_W bool findCirclesGridDefault( InputArray image, Size patternSize,
+ OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID );
+enum
+{
+ CALIB_USE_INTRINSIC_GUESS = CV_CALIB_USE_INTRINSIC_GUESS,
+ CALIB_FIX_ASPECT_RATIO = CV_CALIB_FIX_ASPECT_RATIO,
+ CALIB_FIX_PRINCIPAL_POINT = CV_CALIB_FIX_PRINCIPAL_POINT,
+ CALIB_ZERO_TANGENT_DIST = CV_CALIB_ZERO_TANGENT_DIST,
+ CALIB_FIX_FOCAL_LENGTH = CV_CALIB_FIX_FOCAL_LENGTH,
+ CALIB_FIX_K1 = CV_CALIB_FIX_K1,
+ CALIB_FIX_K2 = CV_CALIB_FIX_K2,
+ CALIB_FIX_K3 = CV_CALIB_FIX_K3,
+ CALIB_FIX_K4 = CV_CALIB_FIX_K4,
+ CALIB_FIX_K5 = CV_CALIB_FIX_K5,
+ CALIB_FIX_K6 = CV_CALIB_FIX_K6,
+ CALIB_RATIONAL_MODEL = CV_CALIB_RATIONAL_MODEL,
+ // only for stereo
+ CALIB_FIX_INTRINSIC = CV_CALIB_FIX_INTRINSIC,
+ CALIB_SAME_FOCAL_LENGTH = CV_CALIB_SAME_FOCAL_LENGTH,
+ // for stereo rectification
+ CALIB_ZERO_DISPARITY = CV_CALIB_ZERO_DISPARITY
+};
+
+//! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern.
+CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,
+ InputArrayOfArrays imagePoints,
+ Size imageSize,
+ CV_OUT InputOutputArray cameraMatrix,
+ CV_OUT InputOutputArray distCoeffs,
+ OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
+ int flags=0, TermCriteria criteria = TermCriteria(
+ TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON) );
+
+//! computes several useful camera characteristics from the camera matrix, camera frame resolution and the physical sensor size.
+CV_EXPORTS_W void calibrationMatrixValues( InputArray cameraMatrix,
+ Size imageSize,
+ double apertureWidth,
+ double apertureHeight,
+ CV_OUT double& fovx,
+ CV_OUT double& fovy,
+ CV_OUT double& focalLength,
+ CV_OUT Point2d& principalPoint,
+ CV_OUT double& aspectRatio );
+
+//! finds intrinsic and extrinsic parameters of a stereo camera
+CV_EXPORTS_W double stereoCalibrate( InputArrayOfArrays objectPoints,
+ InputArrayOfArrays imagePoints1,
+ InputArrayOfArrays imagePoints2,
+ CV_OUT InputOutputArray cameraMatrix1,
+ CV_OUT InputOutputArray distCoeffs1,
+ CV_OUT InputOutputArray cameraMatrix2,
+ CV_OUT InputOutputArray distCoeffs2,
+ Size imageSize, OutputArray R,
+ OutputArray T, OutputArray E, OutputArray F,
+ TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6),
+ int flags=CALIB_FIX_INTRINSIC );
+
+
+//! computes the rectification transformation for a stereo camera from its intrinsic and extrinsic parameters
+CV_EXPORTS_W void stereoRectify( InputArray cameraMatrix1, InputArray distCoeffs1,
+ InputArray cameraMatrix2, InputArray distCoeffs2,
+ Size imageSize, InputArray R, InputArray T,
+ OutputArray R1, OutputArray R2,
+ OutputArray P1, OutputArray P2,
+ OutputArray Q, int flags=CALIB_ZERO_DISPARITY,
+ double alpha=-1, Size newImageSize=Size(),
+ CV_OUT Rect* validPixROI1=0, CV_OUT Rect* validPixROI2=0 );
+
+//! computes the rectification transformation for an uncalibrated stereo camera (zero distortion is assumed)
+CV_EXPORTS_W bool stereoRectifyUncalibrated( InputArray points1, InputArray points2,
+ InputArray F, Size imgSize,
+ OutputArray H1, OutputArray H2,
+ double threshold=5 );
+
+//! computes the rectification transformations for 3-head camera, where all the heads are on the same line.
+CV_EXPORTS_W float rectify3Collinear( InputArray cameraMatrix1, InputArray distCoeffs1,
+ InputArray cameraMatrix2, InputArray distCoeffs2,
+ InputArray cameraMatrix3, InputArray distCoeffs3,
+ InputArrayOfArrays imgpt1, InputArrayOfArrays imgpt3,
+ Size imageSize, InputArray R12, InputArray T12,
+ InputArray R13, InputArray T13,
+ OutputArray R1, OutputArray R2, OutputArray R3,
+ OutputArray P1, OutputArray P2, OutputArray P3,
+ OutputArray Q, double alpha, Size newImgSize,
+ CV_OUT Rect* roi1, CV_OUT Rect* roi2, int flags );
+
+//! returns the optimal new camera matrix
+CV_EXPORTS_W Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs,
+ Size imageSize, double alpha, Size newImgSize=Size(),
+ CV_OUT Rect* validPixROI=0, bool centerPrincipalPoint=false);
+
+//! converts point coordinates from normal pixel coordinates to homogeneous coordinates ((x,y)->(x,y,1))
+CV_EXPORTS_W void convertPointsToHomogeneous( InputArray src, OutputArray dst );
+
+//! converts point coordinates from homogeneous to normal pixel coordinates ((x,y,z)->(x/z, y/z))
+CV_EXPORTS_W void convertPointsFromHomogeneous( InputArray src, OutputArray dst );
+
+//! for backward compatibility
+CV_EXPORTS void convertPointsHomogeneous( InputArray src, OutputArray dst );
+
+//! the algorithm for finding fundamental matrix
+enum
+{
+ FM_7POINT = CV_FM_7POINT, //!< 7-point algorithm
+ FM_8POINT = CV_FM_8POINT, //!< 8-point algorithm
+ FM_LMEDS = CV_FM_LMEDS, //!< least-median algorithm
+ FM_RANSAC = CV_FM_RANSAC //!< RANSAC algorithm
+};
+
+//! finds fundamental matrix from a set of corresponding 2D points
+CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2,
+ int method=FM_RANSAC,
+ double param1=3., double param2=0.99,
+ OutputArray mask=noArray());
+
+//! variant of findFundamentalMat for backward compatibility
+CV_EXPORTS Mat findFundamentalMat( InputArray points1, InputArray points2,
+ OutputArray mask, int method=FM_RANSAC,
+ double param1=3., double param2=0.99);
+
+//! finds coordinates of epipolar lines corresponding the specified points
+CV_EXPORTS_W void computeCorrespondEpilines( InputArray points,
+ int whichImage, InputArray F,
+ OutputArray lines );
+
+CV_EXPORTS_W void triangulatePoints( InputArray projMatr1, InputArray projMatr2,
+ InputArray projPoints1, InputArray projPoints2,
+ OutputArray points4D );
+
+CV_EXPORTS_W void correctMatches( InputArray F, InputArray points1, InputArray points2,
+ OutputArray newPoints1, OutputArray newPoints2 );
+
+template<> CV_EXPORTS void Ptr::delete_obj();
+
+/*!
+ Block Matching Stereo Correspondence Algorithm
+
+ The class implements BM stereo correspondence algorithm by K. Konolige.
+*/
+class CV_EXPORTS_W StereoBM
+{
+public:
+ enum { PREFILTER_NORMALIZED_RESPONSE = 0, PREFILTER_XSOBEL = 1,
+ BASIC_PRESET=0, FISH_EYE_PRESET=1, NARROW_PRESET=2 };
+
+ //! the default constructor
+ CV_WRAP StereoBM();
+ //! the full constructor taking the camera-specific preset, number of disparities and the SAD window size
+ CV_WRAP StereoBM(int preset, int ndisparities=0, int SADWindowSize=21);
+ //! the method that reinitializes the state. The previous content is destroyed
+ void init(int preset, int ndisparities=0, int SADWindowSize=21);
+ //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair
+ CV_WRAP_AS(compute) void operator()( InputArray left, InputArray right,
+ OutputArray disparity, int disptype=CV_16S );
+
+ //! pointer to the underlying CvStereoBMState
+ Ptr state;
+};
+
+
+/*!
+ Semi-Global Block Matching Stereo Correspondence Algorithm
+
+ The class implements the original SGBM stereo correspondence algorithm by H. Hirschmuller and some its modification.
+ */
+class CV_EXPORTS_W StereoSGBM
+{
+public:
+ enum { DISP_SHIFT=4, DISP_SCALE = (1<(X,Y,Z) using the matrix Q returned by cv::stereoRectify
+CV_EXPORTS_W void reprojectImageTo3D( InputArray disparity,
+ OutputArray _3dImage, InputArray Q,
+ bool handleMissingValues=false,
+ int ddepth=-1 );
+
+CV_EXPORTS_W int estimateAffine3D(InputArray src, InputArray dst,
+ OutputArray out, OutputArray inliers,
+ double ransacThreshold=3, double confidence=0.99);
+
+}
+
+#endif
+
+#endif
diff --git a/include/opencv2/contrib/contrib.hpp b/include/opencv2/contrib/contrib.hpp
new file mode 100644
index 0000000..7d881c3
--- /dev/null
+++ b/include/opencv2/contrib/contrib.hpp
@@ -0,0 +1,985 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of the copyright holders may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_CONTRIB_HPP__
+#define __OPENCV_CONTRIB_HPP__
+
+#include "opencv2/core/core.hpp"
+#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/features2d/features2d.hpp"
+#include "opencv2/objdetect/objdetect.hpp"
+
+#ifdef __cplusplus
+
+/****************************************************************************************\
+* Adaptive Skin Detector *
+\****************************************************************************************/
+
+class CV_EXPORTS CvAdaptiveSkinDetector
+{
+private:
+ enum {
+ GSD_HUE_LT = 3,
+ GSD_HUE_UT = 33,
+ GSD_INTENSITY_LT = 15,
+ GSD_INTENSITY_UT = 250
+ };
+
+ class CV_EXPORTS Histogram
+ {
+ private:
+ enum {
+ HistogramSize = (GSD_HUE_UT - GSD_HUE_LT + 1)
+ };
+
+ protected:
+ int findCoverageIndex(double surfaceToCover, int defaultValue = 0);
+
+ public:
+ CvHistogram *fHistogram;
+ Histogram();
+ virtual ~Histogram();
+
+ void findCurveThresholds(int &x1, int &x2, double percent = 0.05);
+ void mergeWith(Histogram *source, double weight);
+ };
+
+ int nStartCounter, nFrameCount, nSkinHueLowerBound, nSkinHueUpperBound, nMorphingMethod, nSamplingDivider;
+ double fHistogramMergeFactor, fHuePercentCovered;
+ Histogram histogramHueMotion, skinHueHistogram;
+ IplImage *imgHueFrame, *imgSaturationFrame, *imgLastGrayFrame, *imgMotionFrame, *imgFilteredFrame;
+ IplImage *imgShrinked, *imgTemp, *imgGrayFrame, *imgHSVFrame;
+
+protected:
+ void initData(IplImage *src, int widthDivider, int heightDivider);
+ void adaptiveFilter();
+
+public:
+
+ enum {
+ MORPHING_METHOD_NONE = 0,
+ MORPHING_METHOD_ERODE = 1,
+ MORPHING_METHOD_ERODE_ERODE = 2,
+ MORPHING_METHOD_ERODE_DILATE = 3
+ };
+
+ CvAdaptiveSkinDetector(int samplingDivider = 1, int morphingMethod = MORPHING_METHOD_NONE);
+ virtual ~CvAdaptiveSkinDetector();
+
+ virtual void process(IplImage *inputBGRImage, IplImage *outputHueMask);
+};
+
+
+/****************************************************************************************\
+ * Fuzzy MeanShift Tracker *
+ \****************************************************************************************/
+
+class CV_EXPORTS CvFuzzyPoint {
+public:
+ double x, y, value;
+
+ CvFuzzyPoint(double _x, double _y);
+};
+
+class CV_EXPORTS CvFuzzyCurve {
+private:
+ std::vector points;
+ double value, centre;
+
+ bool between(double x, double x1, double x2);
+
+public:
+ CvFuzzyCurve();
+ ~CvFuzzyCurve();
+
+ void setCentre(double _centre);
+ double getCentre();
+ void clear();
+ void addPoint(double x, double y);
+ double calcValue(double param);
+ double getValue();
+ void setValue(double _value);
+};
+
+class CV_EXPORTS CvFuzzyFunction {
+public:
+ std::vector curves;
+
+ CvFuzzyFunction();
+ ~CvFuzzyFunction();
+ void addCurve(CvFuzzyCurve *curve, double value = 0);
+ void resetValues();
+ double calcValue();
+ CvFuzzyCurve *newCurve();
+};
+
+class CV_EXPORTS CvFuzzyRule {
+private:
+ CvFuzzyCurve *fuzzyInput1, *fuzzyInput2;
+ CvFuzzyCurve *fuzzyOutput;
+public:
+ CvFuzzyRule();
+ ~CvFuzzyRule();
+ void setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1);
+ double calcValue(double param1, double param2);
+ CvFuzzyCurve *getOutputCurve();
+};
+
+class CV_EXPORTS CvFuzzyController {
+private:
+ std::vector rules;
+public:
+ CvFuzzyController();
+ ~CvFuzzyController();
+ void addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1);
+ double calcOutput(double param1, double param2);
+};
+
+class CV_EXPORTS CvFuzzyMeanShiftTracker
+{
+private:
+ class FuzzyResizer
+ {
+ private:
+ CvFuzzyFunction iInput, iOutput;
+ CvFuzzyController fuzzyController;
+ public:
+ FuzzyResizer();
+ int calcOutput(double edgeDensity, double density);
+ };
+
+ class SearchWindow
+ {
+ public:
+ FuzzyResizer *fuzzyResizer;
+ int x, y;
+ int width, height, maxWidth, maxHeight, ellipseHeight, ellipseWidth;
+ int ldx, ldy, ldw, ldh, numShifts, numIters;
+ int xGc, yGc;
+ long m00, m01, m10, m11, m02, m20;
+ double ellipseAngle;
+ double density;
+ unsigned int depthLow, depthHigh;
+ int verticalEdgeLeft, verticalEdgeRight, horizontalEdgeTop, horizontalEdgeBottom;
+
+ SearchWindow();
+ ~SearchWindow();
+ void setSize(int _x, int _y, int _width, int _height);
+ void initDepthValues(IplImage *maskImage, IplImage *depthMap);
+ bool shift();
+ void extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth);
+ void getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);
+ void getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);
+ void getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);
+ bool meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth);
+ };
+
+public:
+ enum TrackingState
+ {
+ tsNone = 0,
+ tsSearching = 1,
+ tsTracking = 2,
+ tsSetWindow = 3,
+ tsDisabled = 10
+ };
+
+ enum ResizeMethod {
+ rmEdgeDensityLinear = 0,
+ rmEdgeDensityFuzzy = 1,
+ rmInnerDensity = 2
+ };
+
+ enum {
+ MinKernelMass = 1000
+ };
+
+ SearchWindow kernel;
+ int searchMode;
+
+private:
+ enum
+ {
+ MaxMeanShiftIteration = 5,
+ MaxSetSizeIteration = 5
+ };
+
+ void findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth);
+
+public:
+ CvFuzzyMeanShiftTracker();
+ ~CvFuzzyMeanShiftTracker();
+
+ void track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass = MinKernelMass);
+};
+
+
+namespace cv
+{
+
+ class CV_EXPORTS Octree
+ {
+ public:
+ struct Node
+ {
+ Node() {}
+ int begin, end;
+ float x_min, x_max, y_min, y_max, z_min, z_max;
+ int maxLevels;
+ bool isLeaf;
+ int children[8];
+ };
+
+ Octree();
+ Octree( const vector& points, int maxLevels = 10, int minPoints = 20 );
+ virtual ~Octree();
+
+ virtual void buildTree( const vector& points, int maxLevels = 10, int minPoints = 20 );
+ virtual void getPointsWithinSphere( const Point3f& center, float radius,
+ vector& points ) const;
+ const vector