Adapting matlab video demo. Removing duplicate Piece Wise Affine Warp code

This commit is contained in:
Tadas Baltrusaitis
2018-04-16 19:13:40 +01:00
parent a78bcdc70a
commit 9653668086
13 changed files with 100 additions and 795 deletions

2
.gitignore vendored
View File

@@ -82,3 +82,5 @@ lib/3rdParty/CameraEnumerator/x64/
matlab_runners/Action Unit Experiments/out_bosph/
matlab_runners/Action Unit Experiments/out_bp4d/
matlab_runners/Feature Point Experiments/300VW_experiment/
gui/OpenFaceOffline/obj/
gui/OpenFaceDemo/obj/

View File

@@ -43,166 +43,128 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraEnumerator", "lib\3rd
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B47A5F12-2567-44E9-AE49-35763EC82149}.Debug|Any CPU.ActiveCfg = Debug|Win32
{B47A5F12-2567-44E9-AE49-35763EC82149}.Debug|Win32.ActiveCfg = Debug|Win32
{B47A5F12-2567-44E9-AE49-35763EC82149}.Debug|Win32.Build.0 = Debug|Win32
{B47A5F12-2567-44E9-AE49-35763EC82149}.Debug|x64.ActiveCfg = Debug|x64
{B47A5F12-2567-44E9-AE49-35763EC82149}.Debug|x64.Build.0 = Debug|x64
{B47A5F12-2567-44E9-AE49-35763EC82149}.Release|Any CPU.ActiveCfg = Release|Win32
{B47A5F12-2567-44E9-AE49-35763EC82149}.Release|Win32.ActiveCfg = Release|Win32
{B47A5F12-2567-44E9-AE49-35763EC82149}.Release|Win32.Build.0 = Release|Win32
{B47A5F12-2567-44E9-AE49-35763EC82149}.Release|x64.ActiveCfg = Release|x64
{B47A5F12-2567-44E9-AE49-35763EC82149}.Release|x64.Build.0 = Release|x64
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Debug|Any CPU.ActiveCfg = Debug|Win32
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Debug|Win32.ActiveCfg = Debug|Win32
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Debug|Win32.Build.0 = Debug|Win32
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Debug|x64.ActiveCfg = Debug|x64
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Debug|x64.Build.0 = Debug|x64
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Release|Any CPU.ActiveCfg = Release|Win32
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Release|Win32.ActiveCfg = Release|Win32
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Release|Win32.Build.0 = Release|Win32
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Release|x64.ActiveCfg = Release|x64
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8}.Release|x64.Build.0 = Release|x64
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Debug|Any CPU.ActiveCfg = Debug|Win32
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Debug|Win32.ActiveCfg = Debug|Win32
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Debug|Win32.Build.0 = Debug|Win32
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Debug|x64.ActiveCfg = Debug|x64
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Debug|x64.Build.0 = Debug|x64
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Release|Any CPU.ActiveCfg = Release|Win32
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Release|Win32.ActiveCfg = Release|Win32
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Release|Win32.Build.0 = Release|Win32
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Release|x64.ActiveCfg = Release|x64
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7}.Release|x64.Build.0 = Release|x64
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Debug|Any CPU.ActiveCfg = Debug|Win32
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Debug|Win32.ActiveCfg = Debug|Win32
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Debug|Win32.Build.0 = Debug|Win32
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Debug|x64.ActiveCfg = Debug|x64
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Debug|x64.Build.0 = Debug|x64
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Release|Any CPU.ActiveCfg = Release|Win32
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Release|Win32.ActiveCfg = Release|Win32
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Release|Win32.Build.0 = Release|Win32
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Release|x64.ActiveCfg = Release|x64
{8A23C00D-767D-422D-89A3-CF225E3DAB4B}.Release|x64.Build.0 = Release|x64
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Debug|Any CPU.ActiveCfg = Debug|Win32
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Debug|Win32.ActiveCfg = Debug|Win32
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Debug|Win32.Build.0 = Debug|Win32
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Debug|x64.ActiveCfg = Debug|x64
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Debug|x64.Build.0 = Debug|x64
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Release|Any CPU.ActiveCfg = Release|Win32
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Release|Win32.ActiveCfg = Release|Win32
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Release|Win32.Build.0 = Release|Win32
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Release|x64.ActiveCfg = Release|x64
{C3FAF36F-44BC-4454-87C2-C5106575FE50}.Release|x64.Build.0 = Release|x64
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Debug|Any CPU.ActiveCfg = Debug|Win32
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Debug|Win32.ActiveCfg = Debug|Win32
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Debug|Win32.Build.0 = Debug|Win32
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Debug|x64.ActiveCfg = Debug|x64
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Debug|x64.Build.0 = Debug|x64
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Release|Any CPU.ActiveCfg = Release|Win32
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Release|Win32.ActiveCfg = Release|Win32
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Release|Win32.Build.0 = Release|Win32
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Release|x64.ActiveCfg = Release|x64
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC}.Release|x64.Build.0 = Release|x64
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Debug|Any CPU.ActiveCfg = Debug|Win32
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Debug|Win32.ActiveCfg = Debug|Win32
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Debug|Win32.Build.0 = Debug|Win32
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Debug|x64.ActiveCfg = Debug|x64
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Debug|x64.Build.0 = Debug|x64
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Release|Any CPU.ActiveCfg = Release|Win32
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Release|Win32.ActiveCfg = Release|Win32
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Release|Win32.Build.0 = Release|Win32
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Release|x64.ActiveCfg = Release|x64
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A}.Release|x64.Build.0 = Release|x64
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Debug|Any CPU.ActiveCfg = Debug|Win32
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Debug|Win32.ActiveCfg = Debug|Win32
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Debug|Win32.Build.0 = Debug|Win32
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Debug|x64.ActiveCfg = Debug|x64
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Debug|x64.Build.0 = Debug|x64
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|Any CPU.ActiveCfg = Release|Win32
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|Win32.ActiveCfg = Release|Win32
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|Win32.Build.0 = Release|Win32
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|x64.ActiveCfg = Release|x64
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|x64.Build.0 = Release|x64
{5F915541-F531-434F-9C81-79F5DB58012B}.Debug|Any CPU.ActiveCfg = Debug|Win32
{5F915541-F531-434F-9C81-79F5DB58012B}.Debug|Win32.ActiveCfg = Debug|Win32
{5F915541-F531-434F-9C81-79F5DB58012B}.Debug|Win32.Build.0 = Debug|Win32
{5F915541-F531-434F-9C81-79F5DB58012B}.Debug|x64.ActiveCfg = Debug|x64
{5F915541-F531-434F-9C81-79F5DB58012B}.Debug|x64.Build.0 = Debug|x64
{5F915541-F531-434F-9C81-79F5DB58012B}.Release|Any CPU.ActiveCfg = Release|Win32
{5F915541-F531-434F-9C81-79F5DB58012B}.Release|Win32.ActiveCfg = Release|Win32
{5F915541-F531-434F-9C81-79F5DB58012B}.Release|Win32.Build.0 = Release|Win32
{5F915541-F531-434F-9C81-79F5DB58012B}.Release|x64.ActiveCfg = Release|x64
{5F915541-F531-434F-9C81-79F5DB58012B}.Release|x64.Build.0 = Release|x64
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Debug|Any CPU.ActiveCfg = Debug|Win32
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Debug|Win32.ActiveCfg = Debug|Win32
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Debug|Win32.Build.0 = Debug|Win32
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Debug|x64.ActiveCfg = Debug|x64
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Debug|x64.Build.0 = Debug|x64
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Release|Any CPU.ActiveCfg = Release|Win32
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Release|Win32.ActiveCfg = Release|Win32
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Release|Win32.Build.0 = Release|Win32
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Release|x64.ActiveCfg = Release|x64
{8E741EA2-9386-4CF2-815E-6F9B08991EAC}.Release|x64.Build.0 = Release|x64
{F396362D-821E-4EA6-9BBF-1F6050844118}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F396362D-821E-4EA6-9BBF-1F6050844118}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F396362D-821E-4EA6-9BBF-1F6050844118}.Debug|Win32.ActiveCfg = Debug|x86
{F396362D-821E-4EA6-9BBF-1F6050844118}.Debug|Win32.Build.0 = Debug|x86
{F396362D-821E-4EA6-9BBF-1F6050844118}.Debug|x64.ActiveCfg = Debug|Any CPU
{F396362D-821E-4EA6-9BBF-1F6050844118}.Debug|x64.Build.0 = Debug|Any CPU
{F396362D-821E-4EA6-9BBF-1F6050844118}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F396362D-821E-4EA6-9BBF-1F6050844118}.Release|Any CPU.Build.0 = Release|Any CPU
{F396362D-821E-4EA6-9BBF-1F6050844118}.Release|Win32.ActiveCfg = Release|x86
{F396362D-821E-4EA6-9BBF-1F6050844118}.Release|Win32.Build.0 = Release|x86
{F396362D-821E-4EA6-9BBF-1F6050844118}.Release|x64.ActiveCfg = Release|Any CPU
{F396362D-821E-4EA6-9BBF-1F6050844118}.Release|x64.Build.0 = Release|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Debug|Win32.ActiveCfg = Debug|x86
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Debug|Win32.Build.0 = Debug|x86
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Debug|x64.ActiveCfg = Debug|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Debug|x64.Build.0 = Debug|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Release|Any CPU.Build.0 = Release|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Release|Win32.ActiveCfg = Release|x86
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Release|Win32.Build.0 = Release|x86
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Release|x64.ActiveCfg = Release|Any CPU
{E143A2AA-312E-4DFE-B61D-9A87CCBC8E90}.Release|x64.Build.0 = Release|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|Win32.ActiveCfg = Debug|x86
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|Win32.Build.0 = Debug|x86
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|x64.ActiveCfg = Debug|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|x64.Build.0 = Debug|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|Any CPU.Build.0 = Release|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|Win32.ActiveCfg = Release|x86
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|Win32.Build.0 = Release|x86
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|x64.ActiveCfg = Release|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|x64.Build.0 = Release|Any CPU
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|Any CPU.ActiveCfg = Debug|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|Win32.ActiveCfg = Debug|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|Win32.Build.0 = Debug|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|x64.ActiveCfg = Debug|x64
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|x64.Build.0 = Debug|x64
{78196985-EE54-411F-822B-5A23EDF80642}.Release|Any CPU.ActiveCfg = Release|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Release|Win32.ActiveCfg = Release|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Release|Win32.Build.0 = Release|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Release|x64.ActiveCfg = Release|x64
{78196985-EE54-411F-822B-5A23EDF80642}.Release|x64.Build.0 = Release|x64
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Debug|Any CPU.ActiveCfg = Debug|Win32
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Debug|Win32.ActiveCfg = Debug|Win32
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Debug|Win32.Build.0 = Debug|Win32
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Debug|x64.ActiveCfg = Debug|x64
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Debug|x64.Build.0 = Debug|x64
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Release|Any CPU.ActiveCfg = Release|Win32
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Release|Win32.ActiveCfg = Release|Win32
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Release|Win32.Build.0 = Release|Win32
{50B7D4BF-E33B-41D0-AA89-76BBA57BF5CC}.Release|x64.ActiveCfg = Release|x64

View File

@@ -33,7 +33,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\x64\Release\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>

View File

@@ -98,7 +98,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;$(SolutionDir)lib/local/LandmarkDetector/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
@@ -117,7 +117,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;$(SolutionDir)lib/local/LandmarkDetector/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>WIN64;_DEBUG;_LIB;EIGEN_MPL2_ONLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -140,7 +140,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>
</SDLCheck>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;$(SolutionDir)lib/local/LandmarkDetector/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
@@ -165,7 +165,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>
</SDLCheck>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>./include;$(SolutionDir)lib/local/Utilities/include;$(SolutionDir)lib/local/LandmarkDetector/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -187,13 +187,15 @@
<ProjectReference Include="..\..\3rdParty\dlib\dlib.vcxproj">
<Project>{b47a5f12-2567-44e9-ae49-35763ec82149}</Project>
</ProjectReference>
<ProjectReference Include="..\LandmarkDetector\LandmarkDetector.vcxproj">
<Project>{bdc1d107-de17-4705-8e7b-cdde8bfb2bf8}</Project>
</ProjectReference>
<ProjectReference Include="..\Utilities\Utilities.vcxproj">
<Project>{8e741ea2-9386-4cf2-815e-6f9b08991eac}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\FaceAnalyserParameters.cpp" />
<ClCompile Include="src\PAW.cpp" />
<ClCompile Include="src\PDM.cpp" />
<ClCompile Include="src\SVM_dynamic_lin.cpp" />
<ClCompile Include="src\SVM_static_lin.cpp" />
@@ -206,7 +208,6 @@
</ClInclude>
<ClCompile Include="src\FaceAnalyser.cpp" />
<ClCompile Include="src\Face_utils.cpp" />
<ClInclude Include="include\PAW.h" />
<ClInclude Include="include\PDM.h" />
<ClInclude Include="include\SVM_dynamic_lin.h" />
<ClInclude Include="include\SVM_static_lin.h" />

View File

@@ -36,9 +36,6 @@
<ClInclude Include="include\PDM.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\PAW.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\FaceAnalyserParameters.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -65,9 +62,6 @@
<ClCompile Include="src\PDM.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\PAW.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\FaceAnalyserParameters.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@@ -1,138 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY
//
// BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT.
// IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE.
//
// License can be found in OpenFace-license.txt
//
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltru<72>aitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltru<72>aitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltru<72>aitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltru<72>aitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef __PAWA_h_
#define __PAWA_h_
// OpenCV includes
#include <opencv2/core/core.hpp>
namespace FaceAnalysis
{
//===========================================================================
/**
A Piece-wise Affine Warp
The ideas for this piece-wise affine triangular warping are taken from the
Active appearance models revisited by Iain Matthews and Simon Baker in IJCV 2004
This is used for both validation of landmark detection, and for avatar animation
The code is based on the CLM tracker by Jason Saragih et al.
*/
class PAW{
public:
// Number of pixels after the warping to neutral shape
int number_of_pixels;
// Minimum x coordinate in destination
float min_x;
// minimum y coordinate in destination
float min_y;
// Destination points (landmarks to be warped to)
cv::Mat_<float> destination_landmarks;
// Destination points (landmarks to be warped from)
cv::Mat_<float> source_landmarks;
// Triangulation, each triangle is warped using an affine transform
cv::Mat_<int> triangulation;
// Triangle index, indicating which triangle each of destination pixels lies in
cv::Mat_<int> triangle_id;
// Indicating if the destination warped pixels is valid (lies within a face)
cv::Mat_<uchar> pixel_mask;
// A number of precomputed coefficients that are helpful for quick warping
// affine coefficients for all triangles (see Matthews and Baker 2004)
// 6 coefficients for each triangle (are computed from alpha and beta)
// This is computed during each warp based on source landmarks
cv::Mat_<float> coefficients;
// matrix of (c,x,y) coeffs for alpha
cv::Mat_<float> alpha;
// matrix of (c,x,y) coeffs for alpha
cv::Mat_<float> beta;
// x-source of warped points
cv::Mat_<float> map_x;
// y-source of warped points
cv::Mat_<float> map_y;
// Default constructor
PAW(){;}
// Construct a warp from a destination shape and triangulation
PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation);
// The final optional argument allows for optimisation if the triangle indices from previous frame are known (for tracking in video)
PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation, float in_min_x, float in_min_y, float in_max_x, float in_max_y);
// Copy constructor
PAW(const PAW& other);
void Read(std::ifstream &s);
// The actual warping
void Warp(const cv::Mat& image_to_warp, cv::Mat& destination_image, const cv::Mat_<float>& landmarks_to_warp);
// Compute coefficients needed for warping
void CalcCoeff();
// Perform the actual warping
void WarpRegion(cv::Mat_<float>& map_x, cv::Mat_<float>& map_y);
inline int NumberOfLandmarks() const {return destination_landmarks.rows/2;} ;
inline int NumberOfTriangles() const {return triangulation.rows;} ;
// The width and height of the warped image
inline int constWidth() const {return pixel_mask.cols;}
inline int Height() const {return pixel_mask.rows;}
private:
// Helper functions for dealing with triangles
static bool sameSide(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
static bool pointInTriangle(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
static int findTriangle(const cv::Point_<float>& point, const std::vector<std::vector<float>>& control_points, int guess = -1);
};
//===========================================================================
}
#endif

View File

@@ -215,7 +215,7 @@ namespace FaceAnalysis
destination_landmarks = cv::Mat(destination_landmarks.t()).reshape(1, 1).t();
FaceAnalysis::PAW paw(destination_landmarks, triangulation, 0, 0, aligned_face.cols-1, aligned_face.rows-1);
LandmarkDetector::PAW paw(destination_landmarks, triangulation, 0, 0, aligned_face.cols-1, aligned_face.rows-1);
// Mask each of the channels (a bit of a roundabout way, but OpenCV 3.1 in debug mode doesn't seem to be able to handle a more direct way using split and merge)
vector<cv::Mat> aligned_face_channels(aligned_face.channels());

View File

@@ -1,514 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY
//
// BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT.
// IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE.
//
// License can be found in OpenFace-license.txt
//
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltru<72>aitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltru<72>aitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltru<72>aitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltru<72>aitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
#include "PAW.h"
// OpenCV includes
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
#include "Face_utils.h"
using namespace FaceAnalysis;
// Copy constructor
PAW::PAW(const PAW& other) : destination_landmarks(other.destination_landmarks.clone()), source_landmarks(other.source_landmarks.clone()), triangulation(other.triangulation.clone()),
triangle_id(other.triangle_id.clone()), pixel_mask(other.pixel_mask.clone()), coefficients(other.coefficients.clone()), alpha(other.alpha.clone()), beta(other.beta.clone()), map_x(other.map_x.clone()), map_y(other.map_y.clone())
{
this->number_of_pixels = other.number_of_pixels;
this->min_x = other.min_x;
this->min_y = other.min_y;
}
// A constructor from destination shape and triangulation
PAW::PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation)
{
// Initialise some variables directly
this->destination_landmarks = destination_shape;
this->triangulation = triangulation;
int num_points = destination_shape.rows/2;
int num_tris = triangulation.rows;
// Pre-compute the rest
alpha = cv::Mat_<float>(num_tris, 3);
beta = cv::Mat_<float>(num_tris, 3);
cv::Mat_<float> xs = destination_shape(cv::Rect(0, 0, 1, num_points));
cv::Mat_<float> ys = destination_shape(cv::Rect(0, num_points, 1, num_points));
// Create a vector representation of the control points
std::vector<std::vector<float>> destination_points;
for (int tri = 0; tri < num_tris; ++tri)
{
int j = triangulation.at<int>(tri, 0);
int k = triangulation.at<int>(tri, 1);
int l = triangulation.at<int>(tri, 2);
float c1 = ys.at<float>(l) - ys.at<float>(j);
float c2 = xs.at<float>(l) - xs.at<float>(j);
float c4 = ys.at<float>(k) - ys.at<float>(j);
float c3 = xs.at<float>(k) - xs.at<float>(j);
float c5 = c3*c1 - c2*c4;
alpha.at<float>(tri, 0) = (ys.at<float>(j) * c2 - xs.at<float>(j) * c1) / c5;
alpha.at<float>(tri, 1) = c1/c5;
alpha.at<float>(tri, 2) = -c2/c5;
beta.at<float>(tri, 0) = (xs.at<float>(j) * c4 - ys.at<float>(j) * c3)/c5;
beta.at<float>(tri, 1) = -c4/c5;
beta.at<float>(tri, 2) = c3/c5;
// Add points corresponding to triangles as optimisation
std::vector<float> triangle_points(10);
triangle_points[0] = xs.at<float>(j);
triangle_points[1] = ys.at<float>(j);
triangle_points[2] = xs.at<float>(k);
triangle_points[3] = ys.at<float>(k);
triangle_points[4] = xs.at<float>(l);
triangle_points[5] = ys.at<float>(l);
cv::Vec3f xs_three(triangle_points[0], triangle_points[2], triangle_points[4]);
cv::Vec3f ys_three(triangle_points[1], triangle_points[3], triangle_points[5]);
double min_x, max_x, min_y, max_y;
cv::minMaxIdx(xs_three, &min_x, &max_x);
cv::minMaxIdx(ys_three, &min_y, &max_y);
triangle_points[6] = (float) max_x;
triangle_points[7] = (float) max_y;
triangle_points[8] = (float) min_x;
triangle_points[9] = (float) min_y;
destination_points.push_back(triangle_points);
}
double max_x;
double max_y;
double min_x_d;
double min_y_d;
minMaxLoc(xs, &min_x_d, &max_x);
minMaxLoc(ys, &min_y_d, &max_y);
min_x = min_x_d;
min_y = min_y_d;
int w = (int)(max_x - min_x + 1.5);
int h = (int)(max_y - min_y + 1.5);
// Round the min_x and min_y for simplicity?
pixel_mask = cv::Mat_<uchar>(h, w, (uchar)0);
triangle_id = cv::Mat_<int>(h, w, -1);
int curr_tri = -1;
for(int y = 0; y < pixel_mask.rows; y++)
{
for(int x = 0; x < pixel_mask.cols; x++)
{
curr_tri = findTriangle(cv::Point_<float>(x + min_x, y + min_y), destination_points, curr_tri);
// If there is a triangle at this location
if(curr_tri != -1)
{
triangle_id.at<int>(y, x) = curr_tri;
pixel_mask.at<uchar>(y, x) = 1;
}
}
}
// Preallocate maps and coefficients
coefficients.create(num_tris, 6);
map_x.create(pixel_mask.rows,pixel_mask.cols);
map_y.create(pixel_mask.rows,pixel_mask.cols);
}
// Manually define min and max values
PAW::PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation, float in_min_x, float in_min_y, float in_max_x, float in_max_y)
{
// Initialise some variables directly
this->destination_landmarks = destination_shape;
this->triangulation = triangulation;
int num_points = destination_shape.rows/2;
int num_tris = triangulation.rows;
// Pre-compute the rest
alpha = cv::Mat_<float>(num_tris, 3);
beta = cv::Mat_<float>(num_tris, 3);
cv::Mat_<float> xs = destination_shape(cv::Rect(0, 0, 1, num_points));
cv::Mat_<float> ys = destination_shape(cv::Rect(0, num_points, 1, num_points));
// Create a vector representation of the control points
std::vector<std::vector<float>> destination_points;
for (int tri = 0; tri < num_tris; ++tri)
{
int j = triangulation.at<int>(tri, 0);
int k = triangulation.at<int>(tri, 1);
int l = triangulation.at<int>(tri, 2);
float c1 = ys.at<float>(l) - ys.at<float>(j);
float c2 = xs.at<float>(l) - xs.at<float>(j);
float c4 = ys.at<float>(k) - ys.at<float>(j);
float c3 = xs.at<float>(k) - xs.at<float>(j);
float c5 = c3*c1 - c2*c4;
alpha.at<float>(tri, 0) = (ys.at<float>(j) * c2 - xs.at<float>(j) * c1) / c5;
alpha.at<float>(tri, 1) = c1/c5;
alpha.at<float>(tri, 2) = -c2/c5;
beta.at<float>(tri, 0) = (xs.at<float>(j) * c4 - ys.at<float>(j) * c3)/c5;
beta.at<float>(tri, 1) = -c4/c5;
beta.at<float>(tri, 2) = c3/c5;
// Add points corresponding to triangles as optimisation
std::vector<float> triangle_points(10);
triangle_points[0] = xs.at<float>(j);
triangle_points[1] = ys.at<float>(j);
triangle_points[2] = xs.at<float>(k);
triangle_points[3] = ys.at<float>(k);
triangle_points[4] = xs.at<float>(l);
triangle_points[5] = ys.at<float>(l);
cv::Vec3f xs_three(triangle_points[0], triangle_points[2], triangle_points[4]);
cv::Vec3f ys_three(triangle_points[1], triangle_points[3], triangle_points[5]);
double min_x, max_x, min_y, max_y;
cv::minMaxIdx(xs_three, &min_x, &max_x);
cv::minMaxIdx(ys_three, &min_y, &max_y);
triangle_points[6] = (float)max_x;
triangle_points[7] = (float)max_y;
triangle_points[8] = (float)min_x;
triangle_points[9] = (float)min_y;
destination_points.push_back(triangle_points);
}
float max_x;
float max_y;
min_x = in_min_x;
min_y = in_min_y;
max_x = in_max_x;
max_y = in_max_y;
int w = (int)(max_x - min_x + 1.5);
int h = (int)(max_y - min_y + 1.5);
// Round the min_x and min_y for simplicity?
pixel_mask = cv::Mat_<uchar>(h, w, (uchar)0);
triangle_id = cv::Mat_<int>(h, w, -1);
int curr_tri = -1;
for(int y = 0; y < pixel_mask.rows; y++)
{
for(int x = 0; x < pixel_mask.cols; x++)
{
curr_tri = findTriangle(cv::Point_<float>(x + min_x, y + min_y), destination_points, curr_tri);
// If there is a triangle at this location
if(curr_tri != -1)
{
triangle_id.at<int>(y, x) = curr_tri;
pixel_mask.at<uchar>(y, x) = 1;
}
}
}
// Preallocate maps and coefficients
coefficients.create(num_tris, 6);
map_x.create(pixel_mask.rows,pixel_mask.cols);
map_y.create(pixel_mask.rows,pixel_mask.cols);
}
//===========================================================================
void PAW::Read(std::ifstream& stream)
{
stream.read ((char*)&number_of_pixels, 4);
double min_x_d, min_y_d;
stream.read ((char*)&min_x_d, 8);
stream.read ((char*)&min_y_d, 8);
min_x = (float)min_x_d;
min_y = (float)min_y_d;
cv::Mat_<double> destination_landmarks_d;
ReadMatBin(stream, destination_landmarks_d);
destination_landmarks_d.convertTo(destination_landmarks, CV_32F);
ReadMatBin(stream, triangulation);
ReadMatBin(stream, triangle_id);
cv::Mat tmpMask;
ReadMatBin(stream, tmpMask);
tmpMask.convertTo(pixel_mask, CV_8U);
cv::Mat_<double> alpha_d;
ReadMatBin(stream, alpha_d);
alpha_d.convertTo(alpha, CV_32F);
cv::Mat_<double> beta_d;
ReadMatBin(stream, beta_d);
beta_d.convertTo(beta, CV_32F);
map_x.create(pixel_mask.rows,pixel_mask.cols);
map_y.create(pixel_mask.rows,pixel_mask.cols);
coefficients.create(this->NumberOfTriangles(),6);
source_landmarks = destination_landmarks;
}
//=============================================================================
// cropping from the source image to the destination image using the shape in s, used to determine if shape fitting converged successfully
void PAW::Warp(const cv::Mat& image_to_warp, cv::Mat& destination_image, const cv::Mat_<float>& landmarks_to_warp)
{
// set the current shape
source_landmarks = landmarks_to_warp.clone();
// prepare the mapping coefficients using the current shape
this->CalcCoeff();
// Do the actual mapping computation (where to warp from)
this->WarpRegion(map_x, map_y);
// Do the actual warp (with bi-linear interpolation)
remap(image_to_warp, destination_image, map_x, map_y, CV_INTER_LINEAR);
}
//=============================================================================
// Calculate the warping coefficients
void PAW::CalcCoeff()
{
int p = this->NumberOfLandmarks();
for(int l = 0; l < this->NumberOfTriangles(); l++)
{
int i = triangulation.at<int>(l,0);
int j = triangulation.at<int>(l,1);
int k = triangulation.at<int>(l,2);
float c1 = source_landmarks.at<float>(i , 0);
float c2 = source_landmarks.at<float>(j , 0) - c1;
float c3 = source_landmarks.at<float>(k , 0) - c1;
float c4 = source_landmarks.at<float>(i + p, 0);
float c5 = source_landmarks.at<float>(j + p, 0) - c4;
float c6 = source_landmarks.at<float>(k + p, 0) - c4;
// Get a pointer to the coefficient we will be precomputing
float *coeff = coefficients.ptr<float>(l);
// Extract the relevant alphas and betas
float *c_alpha = alpha.ptr<float>(l);
float *c_beta = beta.ptr<float>(l);
coeff[0] = c1 + c2 * c_alpha[0] + c3 * c_beta[0];
coeff[1] = c2 * c_alpha[1] + c3 * c_beta[1];
coeff[2] = c2 * c_alpha[2] + c3 * c_beta[2];
coeff[3] = c4 + c5 * c_alpha[0] + c6 * c_beta[0];
coeff[4] = c5 * c_alpha[1] + c6 * c_beta[1];
coeff[5] = c5 * c_alpha[2] + c6 * c_beta[2];
}
}
//======================================================================
// Compute the mapping coefficients
void PAW::WarpRegion(cv::Mat_<float>& mapx, cv::Mat_<float>& mapy)
{
cv::MatIterator_<float> xp = mapx.begin();
cv::MatIterator_<float> yp = mapy.begin();
cv::MatIterator_<uchar> mp = pixel_mask.begin();
cv::MatIterator_<int> tp = triangle_id.begin();
// The coefficients corresponding to the current triangle
float * a;
// Current triangle being processed
int k=-1;
for(int y = 0; y < pixel_mask.rows; y++)
{
float yi = float(y) + min_y;
for(int x = 0; x < pixel_mask.cols; x++)
{
float xi = float(x) + min_x;
if(*mp == 0)
{
*xp = -1;
*yp = -1;
}
else
{
// triangle corresponding to the current pixel
int j = *tp;
// If it is different from the previous triangle point to new coefficients
// This will always be the case in the first iteration, hence a will not point to nothing
if(j != k)
{
// Update the coefficient pointer if a new triangle is being processed
a = coefficients.ptr<float>(j);
k = j;
}
//ap is now the pointer to the coefficients
float *ap = a;
//look at the first coefficient (and increment). first coefficient is an x offset
float xo = *ap++;
//second coefficient is an x scale as a function of x
xo += *ap++ * xi;
//third coefficient ap(2) is an x scale as a function of y
*xp = float(xo + *ap++ * yi);
//then fourth coefficient ap(3) is a y offset
float yo = *ap++;
//fifth coeff adds coeff[4]*x to y
yo += *ap++ * xi;
//final coeff adds coeff[5]*y to y
*yp = float(yo + *ap++ * yi);
}
mp++; tp++; xp++; yp++;
}
}
}
// ============================================================
// Helper functions to determine which point a triangle lies in
// ============================================================
// Is the point (x0,y0) on same side as a half-plane defined by (x1,y1), (x2, y2), and (x3, y3)
bool PAW::sameSide(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
float x = (x3-x2)*(y0-y2) - (x0-x2)*(y3-y2);
float y = (x3-x2)*(y1-y2) - (x1-x2)*(y3-y2);
return x*y >= 0;
}
// if point (x0, y0) is on same side for all three half-planes it is in a triangle
bool PAW::pointInTriangle(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
bool same_1 = sameSide(x0, y0, x1, y1, x2, y2, x3, y3);
bool same_2 = sameSide(x0, y0, x2, y2, x1, y1, x3, y3);
bool same_3 = sameSide(x0, y0, x3, y3, x1, y1, x2, y2);
return same_1 && same_2 && same_3;
}
// Find if a given point lies in the triangles
int PAW::findTriangle(const cv::Point_<float>& point, const std::vector<std::vector<float>>& control_points, int guess)
{
int num_tris = control_points.size();
int tri = -1;
float x0 = point.x;
float y0 = point.y;
// Allow a guess for speed (so as not to go through all triangles)
if(guess != -1)
{
bool in_triangle = pointInTriangle(x0, y0, control_points[guess][0], control_points[guess][1], control_points[guess][2], control_points[guess][3], control_points[guess][4], control_points[guess][5]);
if(in_triangle)
{
return guess;
}
}
for (int i = 0; i < num_tris; ++i)
{
float max_x = control_points[i][6];
float max_y = control_points[i][7];
float min_x = control_points[i][8];
float min_y = control_points[i][9];
// Skip the check if the point is outside the bounding box of the triangle
if( max_x < x0 || min_x > x0 || max_y < y0 || min_y > y0)
{
continue;
}
bool in_triangle = pointInTriangle(x0, y0,
control_points[i][0], control_points[i][1],
control_points[i][2], control_points[i][3],
control_points[i][4], control_points[i][5]);
if(in_triangle)
{
tri = i;
break;
}
}
return tri;
}

View File

@@ -50,86 +50,89 @@ namespace LandmarkDetector
The code is based on the CLM tracker by Jason Saragih et al.
*/
class PAW{
public:
// Number of pixels after the warping to neutral shape
int number_of_pixels;
class PAW {
public:
// Number of pixels after the warping to neutral shape
int number_of_pixels;
// Minimum x coordinate in destination
float min_x;
// Minimum x coordinate in destination
float min_x;
// minimum y coordinate in destination
float min_y;
// minimum y coordinate in destination
float min_y;
// Destination points (landmarks to be warped to)
cv::Mat_<float> destination_landmarks;
// Destination points (landmarks to be warped to)
cv::Mat_<float> destination_landmarks;
// Destination points (landmarks to be warped from)
cv::Mat_<float> source_landmarks;
// Destination points (landmarks to be warped from)
cv::Mat_<float> source_landmarks;
// Triangulation, each triangle is warped using an affine transform
cv::Mat_<int> triangulation;
// Triangulation, each triangle is warped using an affine transform
cv::Mat_<int> triangulation;
// Triangle index, indicating which triangle each of destination pixels lies in
cv::Mat_<int> triangle_id;
// Triangle index, indicating which triangle each of destination pixels lies in
cv::Mat_<int> triangle_id;
// Indicating if the destination warped pixels is valid (lies within a face)
cv::Mat_<uchar> pixel_mask;
// Indicating if the destination warped pixels is valid (lies within a face)
cv::Mat_<uchar> pixel_mask;
// A number of precomputed coefficients that are helpful for quick warping
// affine coefficients for all triangles (see Matthews and Baker 2004)
// 6 coefficients for each triangle (are computed from alpha and beta)
// This is computed during each warp based on source landmarks
cv::Mat_<float> coefficients;
// A number of precomputed coefficients that are helpful for quick warping
// matrix of (c,x,y) coeffs for alpha
cv::Mat_<float> alpha;
// affine coefficients for all triangles (see Matthews and Baker 2004)
// 6 coefficients for each triangle (are computed from alpha and beta)
// This is computed during each warp based on source landmarks
cv::Mat_<float> coefficients;
// matrix of (c,x,y) coeffs for alpha
cv::Mat_<float> beta;
// matrix of (c,x,y) coeffs for alpha
cv::Mat_<float> alpha;
// x-source of warped points
cv::Mat_<float> map_x;
// matrix of (c,x,y) coeffs for alpha
cv::Mat_<float> beta;
// y-source of warped points
cv::Mat_<float> map_y;
// x-source of warped points
cv::Mat_<float> map_x;
// Default constructor
PAW(){;}
// y-source of warped points
cv::Mat_<float> map_y;
// Construct a warp from a destination shape and triangulation
PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation);
// Default constructor
PAW() { ; }
// The final optional argument allows for optimisation if the triangle indices from previous frame are known (for tracking in video)
PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation, float in_min_x, float in_min_y, float in_max_x, float in_max_y);
// Construct a warp from a destination shape and triangulation
PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation);
// Copy constructor
PAW(const PAW& other);
// The final optional argument allows for optimisation if the triangle indices from previous frame are known (for tracking in video)
PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation, float in_min_x, float in_min_y, float in_max_x, float in_max_y);
void Read(std::ifstream &s);
// Copy constructor
PAW(const PAW& other);
// The actual warping
void Warp(const cv::Mat& image_to_warp, cv::Mat& destination_image, const cv::Mat_<float>& landmarks_to_warp);
// Compute coefficients needed for warping
void CalcCoeff();
void Read(std::ifstream &s);
// Perform the actual warping
void WarpRegion(cv::Mat_<float>& map_x, cv::Mat_<float>& map_y);
// The actual warping
void Warp(const cv::Mat& image_to_warp, cv::Mat& destination_image, const cv::Mat_<float>& landmarks_to_warp);
inline int NumberOfLandmarks() const {return destination_landmarks.rows/2;} ;
inline int NumberOfTriangles() const {return triangulation.rows;} ;
// Compute coefficients needed for warping
void CalcCoeff();
// The width and height of the warped image
inline int constWidth() const {return pixel_mask.cols;}
inline int Height() const {return pixel_mask.rows;}
private:
// Perform the actual warping
void WarpRegion(cv::Mat_<float>& map_x, cv::Mat_<float>& map_y);
int findTriangle(const cv::Point_<float>& point, const std::vector<std::vector<float>>& control_points, int guess = -1) const;
inline int NumberOfLandmarks() const { return destination_landmarks.rows / 2; };
inline int NumberOfTriangles() const { return triangulation.rows; };
};
//===========================================================================
// The width and height of the warped image
inline int constWidth() const { return pixel_mask.cols; }
inline int Height() const { return pixel_mask.rows; }
private:
// Helper functions for dealing with triangles
static bool sameSide(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
static bool pointInTriangle(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
static int findTriangle(const cv::Point_<float>& point, const std::vector<std::vector<float>>& control_points, int guess = -1);
};
//===========================================================================
}
#endif

View File

@@ -165,7 +165,6 @@ PAW::PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangul
}
// Manually define min and max values
PAW::PAW(const cv::Mat_<float>& destination_shape, const cv::Mat_<int>& triangulation, float in_min_x, float in_min_y, float in_max_x, float in_max_y)
{
@@ -287,23 +286,23 @@ void PAW::Read(std::ifstream& stream)
min_y = (float)min_y_d;
cv::Mat_<double> destination_landmarks_d;
LandmarkDetector::ReadMatBin(stream, destination_landmarks_d);
ReadMatBin(stream, destination_landmarks_d);
destination_landmarks_d.convertTo(destination_landmarks, CV_32F);
LandmarkDetector::ReadMatBin(stream, triangulation);
ReadMatBin(stream, triangulation);
LandmarkDetector::ReadMatBin(stream, triangle_id);
ReadMatBin(stream, triangle_id);
cv::Mat tmpMask;
LandmarkDetector::ReadMatBin(stream, tmpMask);
ReadMatBin(stream, tmpMask);
tmpMask.convertTo(pixel_mask, CV_8U);
cv::Mat_<double> alpha_d;
LandmarkDetector::ReadMatBin(stream, alpha_d);
ReadMatBin(stream, alpha_d);
alpha_d.convertTo(alpha, CV_32F);
cv::Mat_<double> beta_d;
LandmarkDetector::ReadMatBin(stream, beta_d);
ReadMatBin(stream, beta_d);
beta_d.convertTo(beta, CV_32F);
map_x.create(pixel_mask.rows, pixel_mask.cols);
@@ -441,18 +440,18 @@ void PAW::WarpRegion(cv::Mat_<float>& mapx, cv::Mat_<float>& mapy)
// ============================================================
// Is the point (x0,y0) on same side as a half-plane defined by (x1,y1), (x2, y2), and (x3, y3)
bool sameSide(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
bool PAW::sameSide(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
float x = (x3-x2)*(y0-y2) - (x0-x2)*(y3-y2);
float y = (x3-x2)*(y1-y2) - (x1-x2)*(y3-y2);
return x*y >= 0;
float x = (x3 - x2)*(y0 - y2) - (x0 - x2)*(y3 - y2);
float y = (x3 - x2)*(y1 - y2) - (x1 - x2)*(y3 - y2);
return x*y >= 0;
}
// if point (x0, y0) is on same side for all three half-planes it is in a triangle
bool pointInTriangle(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
bool PAW::pointInTriangle(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
bool same_1 = sameSide(x0, y0, x1, y1, x2, y2, x3, y3);
bool same_2 = sameSide(x0, y0, x2, y2, x1, y1, x3, y3);
@@ -463,7 +462,7 @@ bool pointInTriangle(float x0, float y0, float x1, float y1, float x2, float y2,
}
// Find if a given point lies in the triangles
int PAW::findTriangle(const cv::Point_<float>& point, const std::vector<std::vector<float>>& control_points, int guess) const
int PAW::findTriangle(const cv::Point_<float>& point, const std::vector<std::vector<float>>& control_points, int guess)
{
int num_tris = control_points.size();

View File

@@ -40,7 +40,7 @@ verbose = true;
for img=1:numel(images)
image_orig = imread([root_dir images(img).name]);
% Face detectiopn
% Face detection
[bboxs] = detect_faces(image_orig, 'mtcnn');
% If MTCNN detector not available, can use the cascaded regression one

View File

@@ -14,17 +14,14 @@ verbose = true;
record = true;
%% loading the patch experts
[clmParams, pdm] = Load_CLM_params_vid();
% Default OpenFace landmark model, using CE-CLM patch experts
[patches, pdm, clmParams, early_term_params] = Load_CECLM_general();
% An accurate CCNF (or CLNF) model
[patches] = Load_Patch_Experts( '../models/general/', 'ccnf_patches_*_general.mat', [], [], clmParams);
% A simpler (but less accurate SVR)
% [patches] = Load_Patch_Experts( '../models/wild/', 'svr_patches_*_wild.mat', [], [], clmParams);
% faster but less accurate
%[patches, pdm, clmParams] = Load_CLNF_general();
% A general SVR
% [patches] = Load_Patch_Experts( '../models/general/', 'svr_patches_*_general.mat', [], [], clmParams);
clmParams.multi_modal_types = patches(1).multi_modal_types;
% even faster but even less accurate
%[patches, pdm, clmParams] = Load_CLM_general();
% load the face validator and add its dependency
load('../face_validation/trained/faceCheckers.mat', 'faceCheckers');
@@ -72,12 +69,11 @@ for v=1:numel(vids)
image_orig = read(vr, i);
if((~det && mod(i,4) == 0) || ~initialised)
[bboxs, det_shapes, confidences] = detect_face_mtcnn(image_orig);
% First attempt to use the Matlab one (fastest but not as accurate, if not present use yu et al.)
% [bboxs, det_shapes] = detect_faces(image_orig, {'cascade', 'yu'});
% Zhu and Ramanan and Yu et al. are slower, but also more accurate
% and can be used when vision toolbox is unavailable
% [bboxs, det_shapes] = detect_faces(image_orig, {'yu', 'zhu'});
% Face detection
[bboxs] = detect_faces(image_orig, 'mtcnn');
% If MTCNN detector not available, can use the cascaded regression one
% [bboxs] = detect_faces(image_orig, 'cascade');
if(~isempty(bboxs))

View File

@@ -1,8 +1,8 @@
function setup(varargin)
run vlfeat-0.9.20/toolbox/vl_setup ;
run D:\soft\matconvnet-master\matconvnet-master\matlab/vl_setupnn ;
addpath D:\soft\matconvnet-master\matconvnet-master\examples ;
%run vlfeat-0.9.20/toolbox/vl_setup ;
run C:\matconvnet\matconvnet-1.0-beta25\matlab/vl_setupnn ;
addpath C:\matconvnet\matconvnet-1.0-beta25\examples ;
opts.useGpu = false ;
opts.verbose = false ;