Merge branch 'master' into fmegen/aarch64/mpi
# Conflicts: # Source/1BitSGD # Source/Common/Include/MPIWrapper.h # Source/Common/MPIWrapper.cpp # configure
This commit is contained in:
Коммит
82ec273df3
|
@ -1,6 +1,3 @@
|
|||
Dockerfile-CPU text
|
||||
Dockerfile-GPU text
|
||||
|
||||
*.ini text
|
||||
*.simple text
|
||||
*.counts text
|
||||
|
@ -24,11 +21,14 @@ Dockerfile-GPU text
|
|||
*.html text
|
||||
*.lyx text
|
||||
*.bib text
|
||||
.gitkeep text
|
||||
KaldiReaderReadme text
|
||||
Readme text
|
||||
|
||||
*.bat text
|
||||
*.cmd text
|
||||
*.py text
|
||||
*.ipynb text
|
||||
*.pl text
|
||||
*.ps1 text
|
||||
*.ps text
|
||||
|
@ -53,6 +53,7 @@ Tests/UnitTests/ReaderTests/Data/CNTKTextFormatReader/invalid_inputs.txt eol=lf
|
|||
|
||||
Makefile text
|
||||
*.sln text
|
||||
*.pyproj text
|
||||
*.vcxproj text
|
||||
*.vcxproj.filters text
|
||||
*.vssettings text
|
||||
|
@ -65,10 +66,12 @@ Makefile text
|
|||
*.cc text
|
||||
*.cu text
|
||||
*.cuh text
|
||||
*.proto text
|
||||
|
||||
*.cs text
|
||||
|
||||
*.yml text
|
||||
*.yml.bak text
|
||||
|
||||
*.config text
|
||||
*.cntk text
|
||||
|
@ -83,7 +86,7 @@ Makefile text
|
|||
|
||||
*.log text
|
||||
|
||||
Dockerfile. text
|
||||
Dockerfile* text
|
||||
|
||||
# Speech data
|
||||
mean.363 text
|
||||
|
@ -117,14 +120,21 @@ TIMIT*.tfsa text
|
|||
TIMIT*.transitions text
|
||||
|
||||
Examples/Text/ATIS/Data/ATIS.* text
|
||||
Examples/Text/ATIS/*.wl text
|
||||
|
||||
Examples/SequenceToSequence/CMUDict/Data/cmudict-0.7b* text
|
||||
|
||||
# Binary extensions:
|
||||
*.vsdm binary
|
||||
*.ark binary
|
||||
*.chunk binary
|
||||
*.cmf binary
|
||||
*.docx binary
|
||||
*.jpg binary
|
||||
*.pdf binary
|
||||
*.png binary
|
||||
*.docx binary
|
||||
*.chunk binary
|
||||
*.pptx binary
|
||||
*.snk binary
|
||||
*.vsdm binary
|
||||
*.zip binary
|
||||
*.dnn binary
|
||||
Examples/Image/Detection/FastRCNN/fastRCNN/*/*.pyd binary
|
||||
|
|
|
@ -23,6 +23,11 @@ build/
|
|||
.run-*
|
||||
lib/
|
||||
bin/
|
||||
Examples/Image/DataSets/Pascal/VOC*
|
||||
Examples/Image/DataSets/Pascal/selective_search_data*
|
||||
Examples/Image/Detection/FastRCNN/proc/
|
||||
|
||||
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
!packages/*/build/
|
||||
|
@ -196,6 +201,8 @@ Tests/EndToEndTests/UnitTests/MathTests/MCPU.txt
|
|||
Tests/EndToEndTests/UnitTests/MathTests/MGPU.txt
|
||||
Tests/EndToEndTests/UnitTests/MathTests/MS.txt
|
||||
|
||||
Tests/Install/linux/BinaryDrops.tar.gz
|
||||
|
||||
Dependencies/CNTKCustomMKL/Publish
|
||||
Dependencies/CNTKCustomMKL/CNTKCustomMKL-Linux-*.tgz
|
||||
Dependencies/CNTKCustomMKL/CNTKCustomMKL-Windows-*.zip
|
||||
|
@ -208,3 +215,11 @@ bindings/python/cntk/libs/
|
|||
bindings/python/cntk/cntk_py_wrap.cpp
|
||||
bindings/python/cntk/cntk_py_wrap.h
|
||||
bindings/python/dist/
|
||||
|
||||
# Auto-generated sources from CNTK.proto
|
||||
Source/CNTKv2LibraryDll/proto/CNTK.pb.cc
|
||||
Source/CNTKv2LibraryDll/proto/CNTK.pb.h
|
||||
|
||||
bindings/python/cntk/c_plus_c.mod
|
||||
bindings/python/cntk/i_plus_c_0.mod
|
||||
bindings/python/cntk/i_plus_i_0.mod
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
<CpuOnlyBuild>true</CpuOnlyBuild>
|
||||
<CpuOnlyBuild Condition="$(GpuBuild)">false</CpuOnlyBuild>
|
||||
|
||||
<NoOptBuild>false</NoOptBuild>
|
||||
<NoOptBuild Condition="$(Configuration.Contains('NoOpt'))">true</NoOptBuild>
|
||||
|
||||
<NvmlInclude>"c:\Program Files\NVIDIA Corporation\GDK\gdk_win7_amd64_release\nvml\include"</NvmlInclude>
|
||||
<NvmlLibPath>"c:\Program Files\NVIDIA Corporation\GDK\gdk_win7_amd64_release\nvml\lib"</NvmlLibPath>
|
||||
|
||||
|
@ -30,8 +33,11 @@
|
|||
|
||||
<HasOpenCv>false</HasOpenCv>
|
||||
<HasOpenCv Condition="Exists('$(OPENCV_PATH)') Or Exists('$(OPENCV_PATH_V31)')">true</HasOpenCv>
|
||||
|
||||
<HasBoost>false</HasBoost>
|
||||
|
||||
<HasProtobuf>false</HasProtobuf>
|
||||
<HasProtobuf Condition="Exists('$(PROTOBUF_PATH)')">true</HasProtobuf>
|
||||
|
||||
<HasBoost>false</HasBoost>
|
||||
<HasBoost Condition="Exists('$(BOOST_INCLUDE_PATH)') And Exists('$(BOOST_LIB_PATH)')">true</HasBoost>
|
||||
|
||||
<UseZip>false</UseZip>
|
||||
|
@ -88,6 +94,13 @@
|
|||
<OpenCvBinPath>$(OpenCvPath)\x64\vc12\bin</OpenCvBinPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="$(HasProtobuf)">
|
||||
<ProtobufInclude>$(PROTOBUF_PATH)\include;</ProtobufInclude>
|
||||
<ProtobufLibPath>$(PROTOBUF_PATH)\lib;</ProtobufLibPath>
|
||||
<ProtobufLib Condition="$(ReleaseBuild)">libprotobuf.lib</ProtobufLib>
|
||||
<ProtobufLib Condition="$(DebugBuild)">libprotobufd.lib</ProtobufLib>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(CudaVersion)' == '8.0'">
|
||||
<CudaPath>$(CUDA_PATH_V8_0)</CudaPath>
|
||||
<CudaRuntimeDll>cudart64_80.dll</CudaRuntimeDll>
|
||||
|
@ -151,7 +164,7 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(ConfigurationType)' == 'StaticLibrary' And $(ReleaseBuild)">
|
||||
<ItemDefinitionGroup Condition="'$(ConfigurationType)' == 'StaticLibrary' And $(ReleaseBuild) And !$(NoOptBuild)">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
|
@ -166,4 +179,15 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition="$(NoOptBuild)">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OptimizeReferences>false</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
</Project>
|
||||
|
|
326
CNTK.sln
326
CNTK.sln
|
@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CNTK", "Source\CNTK\CNTK.vc
|
|||
{EB2BE26F-6BD4-4274-971F-86D080779DD1} = {EB2BE26F-6BD4-4274-971F-86D080779DD1}
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602} = {F0A9637C-20DA-42F0-83D4-23B4704DE602}
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B} = {EAD17188-072C-4726-B840-A769C36DAD1B}
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937} = {DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
@ -278,6 +279,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MathTests", "Tests\UnitTest
|
|||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ActionsLib", "Source\ActionsLib\ActionsLib.vcxproj", "{EB2BE26F-6BD4-4274-971F-86D080779DD1}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SequenceTraining", "SequenceTraining", "{BB8B9FC5-C4B3-477F-80E2-665DC8E431BD}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -455,11 +459,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MNIST", "MNIST", "{FA33A61E
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Miscellaneous", "Miscellaneous", "{F99E1E80-50D8-421C-AD94-8ED0DF08C355}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdditionalFiles", "AdditionalFiles", "{ED57E827-B28F-4BEE-BFB7-398EF8D83357}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Examples\Image\MNIST\AdditionalFiles\mnist_convert.py = Examples\Image\MNIST\AdditionalFiles\mnist_convert.py
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{6E5A252C-ACCE-42E0-9819-FF4DEF6D739E}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Examples\Image\MNIST\Config\01_OneHidden.ndl = Examples\Image\MNIST\Config\01_OneHidden.ndl
|
||||
|
@ -486,10 +485,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CIFAR-10", "CIFAR-10", "{77
|
|||
Examples\Image\Miscellaneous\CIFAR-10\04_ResNet_56_ndl_deprecated.cntk = Examples\Image\Miscellaneous\CIFAR-10\04_ResNet_56_ndl_deprecated.cntk
|
||||
Examples\Image\Miscellaneous\CIFAR-10\16to32.txt = Examples\Image\Miscellaneous\CIFAR-10\16to32.txt
|
||||
Examples\Image\Miscellaneous\CIFAR-10\32to64.txt = Examples\Image\Miscellaneous\CIFAR-10\32to64.txt
|
||||
Examples\Image\Miscellaneous\CIFAR-10\CifarConverter.py = Examples\Image\Miscellaneous\CIFAR-10\CifarConverter.py
|
||||
Examples\Image\Miscellaneous\CIFAR-10\CifarConverter_py3.py = Examples\Image\Miscellaneous\CIFAR-10\CifarConverter_py3.py
|
||||
Examples\Image\Miscellaneous\CIFAR-10\CifarDownload.py = Examples\Image\Miscellaneous\CIFAR-10\CifarDownload.py
|
||||
Examples\Image\Miscellaneous\CIFAR-10\CifarDownload_py3.py = Examples\Image\Miscellaneous\CIFAR-10\CifarDownload_py3.py
|
||||
Examples\Image\Miscellaneous\CIFAR-10\labelsmap.txt = Examples\Image\Miscellaneous\CIFAR-10\labelsmap.txt
|
||||
Examples\Image\Miscellaneous\CIFAR-10\Macros.ndl = Examples\Image\Miscellaneous\CIFAR-10\Macros.ndl
|
||||
Examples\Image\Miscellaneous\CIFAR-10\readme.txt = Examples\Image\Miscellaneous\CIFAR-10\readme.txt
|
||||
|
@ -1123,7 +1118,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CNTKv2LibraryDll", "Source\
|
|||
{86883653-8A61-4038-81A0-2379FAE4200A} = {86883653-8A61-4038-81A0-2379FAE4200A}
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602} = {F0A9637C-20DA-42F0-83D4-23B4704DE602}
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B} = {EAD17188-072C-4726-B840-A769C36DAD1B}
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937} = {DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V2LibraryTests", "Tests\UnitTests\V2LibraryTests\V2LibraryTests.vcxproj", "{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}"
|
||||
|
@ -1152,56 +1146,52 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tutorials", "Tutorials", "{
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ImageHandsOn", "ImageHandsOn", "{2230BF3D-4317-4A3F-A743-DDD6160503F8}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\ImageHandsOn\ImageHandsOn.cntk = Tutorials\ImageHandsOn\ImageHandsOn.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn.cntk
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SLUHandsOn", "SLUHandsOn", "{CC143D08-567D-4DAC-9E14-264749C19039}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\SLUHandsOn\SLUHandsOn.cntk = Tutorials\SLUHandsOn\SLUHandsOn.cntk
|
||||
Examples\Tutorials\SLUHandsOn\SLUHandsOn.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn.cntk
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pretrained Models", "Pretrained Models", "{0ED2EE97-0A26-4865-871F-11033867BA34}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\ImageHandsOn\cifar10.pretrained.cmf = Tutorials\ImageHandsOn\cifar10.pretrained.cmf
|
||||
Tutorials\ImageHandsOn\cifar10.ResNet.cmf = Tutorials\ImageHandsOn\cifar10.ResNet.cmf
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solutions", "Solutions", "{A2A4893C-0D5B-42E2-BFAD-C123AE7FDAFD}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk
|
||||
Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk
|
||||
Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk
|
||||
Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk
|
||||
Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk
|
||||
Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk
|
||||
Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk = Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution1.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution2.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution3.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution4.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Solution5.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task4_Start.cntk
|
||||
Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk = Examples\Tutorials\ImageHandsOn\ImageHandsOn_Task6.cntk
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{8CFBD0DB-5F16-48E6-984C-4401317FA10E}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\SLUHandsOn\atis.test.ctf = Tutorials\SLUHandsOn\atis.test.ctf
|
||||
Tutorials\SLUHandsOn\atis.train.ctf = Tutorials\SLUHandsOn\atis.train.ctf
|
||||
Examples\Tutorials\SLUHandsOn\atis.test.ctf = Examples\Tutorials\SLUHandsOn\atis.test.ctf
|
||||
Examples\Tutorials\SLUHandsOn\atis.train.ctf = Examples\Tutorials\SLUHandsOn\atis.train.ctf
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solutions", "Solutions", "{BD7FF8C0-EC3A-49CD-9D81-4A8A29B8AD8E}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk
|
||||
Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk
|
||||
Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk
|
||||
Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk = Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk
|
||||
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution1.cntk
|
||||
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution2.cntk
|
||||
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution3.cntk
|
||||
Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk = Examples\Tutorials\SLUHandsOn\SLUHandsOn_Solution4.cntk
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pretrained Models", "Pretrained Models", "{4727594B-A052-4834-B0E8-57DBB9ADEF13}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\SLUHandsOn\slu.forward.backward.cmf = Tutorials\SLUHandsOn\slu.forward.backward.cmf
|
||||
Tutorials\SLUHandsOn\slu.forward.cmf = Tutorials\SLUHandsOn\slu.forward.cmf
|
||||
Tutorials\SLUHandsOn\slu.forward.lookahead.cmf = Tutorials\SLUHandsOn\slu.forward.lookahead.cmf
|
||||
Tutorials\SLUHandsOn\slu.forward.nobn.cmf = Tutorials\SLUHandsOn\slu.forward.nobn.cmf
|
||||
Examples\Tutorials\SLUHandsOn\slu.forward.backward.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.backward.cmf
|
||||
Examples\Tutorials\SLUHandsOn\slu.forward.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.cmf
|
||||
Examples\Tutorials\SLUHandsOn\slu.forward.lookahead.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.lookahead.cmf
|
||||
Examples\Tutorials\SLUHandsOn\slu.forward.nobn.cmf = Examples\Tutorials\SLUHandsOn\slu.forward.nobn.cmf
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{4A59163B-1EDE-4439-9E7D-40A30B82A3A0}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tutorials\ImageHandsOn\CifarConverter.py = Tutorials\ImageHandsOn\CifarConverter.py
|
||||
Examples\Tutorials\ImageHandsOn\CifarConverter.py = Examples\Tutorials\ImageHandsOn\CifarConverter.py
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TIMIT", "TIMIT", "{B586AA4C-0BB9-4629-9EDA-25FF2618AC9F}"
|
||||
|
@ -1261,6 +1251,40 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSEvalClientTest", "Tests\E
|
|||
EndProject
|
||||
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "CNTKv2", "bindings\python\examples\CNTKv2.pyproj", "{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IRMetric", "IRMetric", "{E844AB9A-A48F-4A99-9625-F528C5C46D83}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Tests\EndToEndTests\Text\IRMetric\baseline.linux.txt = Tests\EndToEndTests\Text\IRMetric\baseline.linux.txt
|
||||
Tests\EndToEndTests\Text\IRMetric\baseline.windows.txt = Tests\EndToEndTests\Text\IRMetric\baseline.windows.txt
|
||||
Tests\EndToEndTests\Text\IRMetric\ir.cntk = Tests\EndToEndTests\Text\IRMetric\ir.cntk
|
||||
Tests\EndToEndTests\Text\IRMetric\run-test = Tests\EndToEndTests\Text\IRMetric\run-test
|
||||
Tests\EndToEndTests\Text\IRMetric\testcases.yml = Tests\EndToEndTests\Text\IRMetric\testcases.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PythonBindings", "bindings\python\PythonBindings.vcxproj", "{CD721536-CFD3-413E-A3D7-FB0FAF989635}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB} = {9BD0A711-0BBD-45B6-B81C-053F03C26CFB}
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5} = {33D2FD22-DEF2-4507-A58A-368F641AEBE5}
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2} = {D667AF32-028A-4A5D-BE19-F46776F0F6B2}
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120} = {7B7A563D-AA8E-4660-A805-D50235A02120}
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68} = {9A2F2441-5972-4EA8-9215-4119FCE0FB68}
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5} = {60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715} = {91973E60-A7BE-4C86-8FDB-59C88A0B3715}
|
||||
{014DA766-B37B-4581-BC26-963EA5507931} = {014DA766-B37B-4581-BC26-963EA5507931}
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B} = {CE429AA2-3778-4619-8FD1-49BA3B81197B}
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340} = {EF766CAE-9CB1-494C-9153-0030631A6340}
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6} = {62836DC1-DF77-4B98-BF2D-45C943B7DDC6}
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9} = {482999D1-B7E2-466E-9F8D-2119F93EAFD9}
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A} = {1D5787D4-52E4-45DB-951B-82F220EE0C6A}
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120} = {7B7A51ED-AA8E-4660-A805-D50235A02120}
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1} = {E6646FFE-3588-4276-8A15-8D65C22711C1}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "V2LibraryDistributionTests", "Tests\UnitTests\V2LibraryDistributionTests\V2LibraryDistributionTests.vcxproj", "{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF} = {E5606ECE-48CA-4464-BB12-09D81D02B9EF}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug_CpuOnly|Any CPU = Debug_CpuOnly|Any CPU
|
||||
|
@ -1272,6 +1296,9 @@ Global
|
|||
Release_CpuOnly|Any CPU = Release_CpuOnly|Any CPU
|
||||
Release_CpuOnly|Mixed Platforms = Release_CpuOnly|Mixed Platforms
|
||||
Release_CpuOnly|x64 = Release_CpuOnly|x64
|
||||
Release_NoOpt|Any CPU = Release_NoOpt|Any CPU
|
||||
Release_NoOpt|Mixed Platforms = Release_NoOpt|Mixed Platforms
|
||||
Release_NoOpt|x64 = Release_NoOpt|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|x64 = Release|x64
|
||||
|
@ -1292,6 +1319,11 @@ Global
|
|||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{E6F26F9A-FF64-4F0A-B749-CD309EE357EE}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1312,6 +1344,11 @@ Global
|
|||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{928ABD1B-4D3B-4017-AEF1-0FA1B4467513}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1332,6 +1369,11 @@ Global
|
|||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{DE3C54E5-D7D0-47AF-A783-DFDCE59E7937}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1352,6 +1394,11 @@ Global
|
|||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{EAD17188-072C-4726-B840-A769C36DAD1B}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1372,6 +1419,11 @@ Global
|
|||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{4701E678-5E6F-470D-B348-9CD1A2C095D1}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1392,6 +1444,11 @@ Global
|
|||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{EB2BE26F-6BD4-4274-971F-86D080779DD1}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1412,6 +1469,11 @@ Global
|
|||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{A4FC3467-4787-43E8-BBC0-D79AE56B468D}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1432,6 +1494,11 @@ Global
|
|||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{482999D1-B7E2-466E-9F8D-2119F93EAFD9}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1452,6 +1519,11 @@ Global
|
|||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{60BDB847-D0C4-4FD3-A947-0C15C08BCDB5}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1470,6 +1542,11 @@ Global
|
|||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_CpuOnly|Mixed Platforms.Build.0 = Release|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_CpuOnly|x64.ActiveCfg = Release|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{B3DD765E-694E-4494-BAD7-37BBF2942517}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1490,6 +1567,11 @@ Global
|
|||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{D667AF32-028A-4A5D-BE19-F46776F0F6B2}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1510,6 +1592,11 @@ Global
|
|||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{1D5787D4-52E4-45DB-951B-82F220EE0C6A}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1530,6 +1617,11 @@ Global
|
|||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{014DA766-B37B-4581-BC26-963EA5507931}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1550,6 +1642,11 @@ Global
|
|||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{33D2FD22-DEF2-4507-A58A-368F641AEBE5}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1570,6 +1667,11 @@ Global
|
|||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{9A2F2441-5972-4EA8-9215-4119FCE0FB68}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1590,6 +1692,11 @@ Global
|
|||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{62836DC1-DF77-4B98-BF2D-45C943B7DDC6}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1610,6 +1717,11 @@ Global
|
|||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{CE429AA2-3778-4619-8FD1-49BA3B81197B}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1630,6 +1742,11 @@ Global
|
|||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{E6646FFE-3588-4276-8A15-8D65C22711C1}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1650,6 +1767,11 @@ Global
|
|||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{668BEED5-AC07-4F35-B3AE-EE65A7F9C976}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1670,6 +1792,11 @@ Global
|
|||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{EF766CAE-9CB1-494C-9153-0030631A6340}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1690,6 +1817,11 @@ Global
|
|||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{F0A9637C-20DA-42F0-83D4-23B4704DE602}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1710,6 +1842,11 @@ Global
|
|||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{91973E60-A7BE-4C86-8FDB-59C88A0B3715}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1730,6 +1867,11 @@ Global
|
|||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{7B7A51ED-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1750,6 +1892,11 @@ Global
|
|||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{9BD0A711-0BBD-45B6-B81C-053F03C26CFB}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1770,6 +1917,11 @@ Global
|
|||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{CDA96AA3-3252-4978-A0BF-2ACD670823CB}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1790,6 +1942,11 @@ Global
|
|||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{86883653-8A61-4038-81A0-2379FAE4200A}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1810,6 +1967,11 @@ Global
|
|||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{7B7A563D-AA8E-4660-A805-D50235A02120}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1830,6 +1992,11 @@ Global
|
|||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{82125DA1-1CD7-45B5-9281-E6AE7C287CB7}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1850,6 +2017,11 @@ Global
|
|||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{731312A8-6DA3-4841-AFCD-57520BA1BF8E}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1870,6 +2042,11 @@ Global
|
|||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{E5606ECE-48CA-4464-BB12-09D81D02B9EF}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1890,6 +2067,11 @@ Global
|
|||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1910,6 +2092,11 @@ Global
|
|||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1930,6 +2117,11 @@ Global
|
|||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1950,6 +2142,11 @@ Global
|
|||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1970,6 +2167,11 @@ Global
|
|||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
|
@ -1984,9 +2186,60 @@ Global
|
|||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_CpuOnly|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_CpuOnly|x64.ActiveCfg = Release|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|Any CPU.ActiveCfg = Debug_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|Mixed Platforms.ActiveCfg = Debug_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|Mixed Platforms.Build.0 = Debug_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|x64.ActiveCfg = Debug_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug_CpuOnly|x64.Build.0 = Debug_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|Mixed Platforms.Build.0 = Debug|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Debug|x64.Build.0 = Debug|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|Any CPU.ActiveCfg = Release_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|Any CPU.ActiveCfg = Release_NoOpt|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_NoOpt|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|Mixed Platforms.Build.0 = Release_NoOpt|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|x64.ActiveCfg = Release_NoOpt|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release_NoOpt|x64.Build.0 = Release_NoOpt|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|x64.ActiveCfg = Release|x64
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635}.Release|x64.Build.0 = Release|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|Any CPU.ActiveCfg = Debug_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|Mixed Platforms.ActiveCfg = Debug_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|Mixed Platforms.Build.0 = Debug_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|x64.ActiveCfg = Debug_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug_CpuOnly|x64.Build.0 = Debug_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|Mixed Platforms.Build.0 = Debug|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Debug|x64.Build.0 = Debug|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Any CPU.ActiveCfg = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Mixed Platforms.ActiveCfg = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|Mixed Platforms.Build.0 = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_CpuOnly|x64.Build.0 = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Any CPU.ActiveCfg = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|Mixed Platforms.ActiveCfg = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release_NoOpt|x64.ActiveCfg = Release_CpuOnly|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.ActiveCfg = Release|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|Mixed Platforms.Build.0 = Release|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|x64.ActiveCfg = Release|x64
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -2051,7 +2304,6 @@ Global
|
|||
{2A1F0FB0-2304-4F35-87B3-66230C6E58F0} = {811924DE-2F12-4EA0-BE58-E57BEF3B74D1}
|
||||
{FA33A61E-95C7-4049-8111-22058CE361A3} = {9BDFA4BE-790E-408F-915B-5979BB5078C6}
|
||||
{F99E1E80-50D8-421C-AD94-8ED0DF08C355} = {9BDFA4BE-790E-408F-915B-5979BB5078C6}
|
||||
{ED57E827-B28F-4BEE-BFB7-398EF8D83357} = {FA33A61E-95C7-4049-8111-22058CE361A3}
|
||||
{6E5A252C-ACCE-42E0-9819-FF4DEF6D739E} = {FA33A61E-95C7-4049-8111-22058CE361A3}
|
||||
{77125562-3BF2-45D2-9B73-72CA8E03C78C} = {F99E1E80-50D8-421C-AD94-8ED0DF08C355}
|
||||
{EF710C5A-E616-442A-889D-C997D39AF2E1} = {F99E1E80-50D8-421C-AD94-8ED0DF08C355}
|
||||
|
@ -2143,6 +2395,7 @@ Global
|
|||
{F4CC3AB2-0DB2-4281-929A-2E68E30F0F6E} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
|
||||
{CC8DDDCB-D53A-4B30-8596-AEF1C493DB31} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
|
||||
{9F999212-AFC5-4EAC-AA78-F7247D46C456} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
|
||||
{8BE0642A-A3AA-4A64-95D0-C78FB285B2A4} = {47755F2E-D674-4175-9E38-8EA053455072}
|
||||
{2230BF3D-4317-4A3F-A743-DDD6160503F8} = {8BE0642A-A3AA-4A64-95D0-C78FB285B2A4}
|
||||
{CC143D08-567D-4DAC-9E14-264749C19039} = {8BE0642A-A3AA-4A64-95D0-C78FB285B2A4}
|
||||
{0ED2EE97-0A26-4865-871F-11033867BA34} = {2230BF3D-4317-4A3F-A743-DDD6160503F8}
|
||||
|
@ -2161,5 +2414,8 @@ Global
|
|||
{CCC07E8E-F33A-4AF7-9F60-93E2AA61C75E} = {05E45AF7-C069-4057-BC16-0A532D068CE4}
|
||||
{1C6E6C53-1AA7-4B69-913E-B97BB5A872CF} = {05E45AF7-C069-4057-BC16-0A532D068CE4}
|
||||
{1A078FC2-21C0-4F42-9A5B-0E84E944BC74} = {47755F2E-D674-4175-9E38-8EA053455072}
|
||||
{E844AB9A-A48F-4A99-9625-F528C5C46D83} = {8656B71D-E24C-4AC2-8BE4-C07B415A3E15}
|
||||
{CD721536-CFD3-413E-A3D7-FB0FAF989635} = {DD043083-71A4-409A-AA91-F9C548DCF7EC}
|
||||
{F4CCAAB2-0DB2-4281-929A-2E68E30F0F6E} = {6F19321A-65E7-4829-B00C-3886CD6C6EDE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1,156 +1,156 @@
|
|||
@echo off
|
||||
REM
|
||||
REM Copyright (c) Microsoft. All rights reserved.
|
||||
REM
|
||||
REM Licensed under the MIT license. See LICENSE.md file in the project root
|
||||
REM for full license information.
|
||||
REM ==============================================================================
|
||||
REM
|
||||
echo.
|
||||
echo This batch file will build a custom MKL dynamic link library for usage by CNTK.
|
||||
echo.
|
||||
echo Requirements:
|
||||
echo - Intel MKL SDK installed on the machine
|
||||
echo - MKLROOT environment variable is set to the MKL directory inside the Intel MKL SDK
|
||||
echo - Visual Studio 2013 installed and included in the path
|
||||
echo.
|
||||
|
||||
setlocal enableextensions enabledelayedexpansion
|
||||
|
||||
pushd "%~dp0"
|
||||
if errorlevel 1 (
|
||||
echo Could not change directory to script location.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not defined MKLROOT (
|
||||
echo Error: Environment variable MKLROOT is undefined.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "%MKLROOT%" (
|
||||
echo Error: Directory doesn't exist: "%MKLROOT%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set MKLBUILDERROOT=%MKLROOT%\tools\builder
|
||||
|
||||
if not exist "%MKLBUILDERROOT%" (
|
||||
echo Error: Directory doesn't exist: "%MKLBUILDERROOT%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
where /q nmake.exe
|
||||
if errorlevel 1 (
|
||||
echo Error: NMAKE.EXE not in path.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
where /q link.exe
|
||||
if errorlevel 1 (
|
||||
echo Error: LINK.EXE not in path.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set /p CNTKCUSTOMMKLVERSION=<version.txt
|
||||
if not defined CNTKCUSTOMMKLVERSION (
|
||||
echo Cannot determine CNTK custom MKL version.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if exist lib rmdir /s /q lib
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
if exist Publish rmdir /s /q Publish
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64
|
||||
|
||||
echo.
|
||||
echo Copying "%MKLBUILDERROOT%\lib".
|
||||
|
||||
xcopy /s /e /y /i "%MKLBUILDERROOT%\lib" lib
|
||||
if errorlevel 1 (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Compiling and copying libraries.
|
||||
|
||||
for %%t in (
|
||||
parallel
|
||||
sequential
|
||||
) do (
|
||||
|
||||
set TFIRSTCHAR=%%t
|
||||
set TFIRSTCHAR=!TFIRSTCHAR:~0,1!
|
||||
set LIBBASENAME=mkl_cntk_!TFIRSTCHAR!
|
||||
|
||||
echo.
|
||||
echo Calling NMAKE libintel64 export=functions.txt threading=%%t name=!LIBBASENAME! MKLROOT="%MKLROOT%".
|
||||
NMAKE /f "%MKLBUILDERROOT%\makefile" ^
|
||||
libintel64 ^
|
||||
export=functions.txt ^
|
||||
threading=%%t ^
|
||||
name=!LIBBASENAME! ^
|
||||
MKLROOT="%MKLROOT%"
|
||||
|
||||
if errorlevel 1 (
|
||||
echo Error: NMAKE.exe for threading=%%t failed.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
move !LIBBASENAME!.dll Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
move !LIBBASENAME!.lib Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
del !LIBBASENAME!*
|
||||
if errorlevel 1 exit /b 1
|
||||
@REM TODO manifest?
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Copying libiomp5md.dll.
|
||||
|
||||
copy "%MKLROOT%\..\redist\intel64_win\compiler\libiomp5md.dll" Publish\%CNTKCUSTOMMKLVERSION%\x64\parallel
|
||||
if errorlevel 1 (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Removing LIB directory.
|
||||
|
||||
rmdir /s /q lib
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Copying include files to Publish\%CNTKCUSTOMMKLVERSION%\include.
|
||||
|
||||
mkdir Publish\%CNTKCUSTOMMKLVERSION%\include
|
||||
|
||||
for /f %%h in (headers.txt) do (
|
||||
copy "%MKLROOT%\include\%%h" Publish\%CNTKCUSTOMMKLVERSION%\include
|
||||
if errorlevel 1 (
|
||||
echo Failed to copy "%MKLROOT%\include\%%h".
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
copy README-for-redistributable.txt Publish\%CNTKCUSTOMMKLVERSION%\README.txt
|
||||
if errorlevel 1 (
|
||||
echo Failed to copy README.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
copy ..\..\LICENSE.md Publish\%CNTKCUSTOMMKLVERSION%
|
||||
if errorlevel 1 (
|
||||
echo Failed to copy LICENSE.md.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
popd
|
||||
@echo off
|
||||
REM
|
||||
REM Copyright (c) Microsoft. All rights reserved.
|
||||
REM
|
||||
REM Licensed under the MIT license. See LICENSE.md file in the project root
|
||||
REM for full license information.
|
||||
REM ==============================================================================
|
||||
REM
|
||||
echo.
|
||||
echo This batch file will build a custom MKL dynamic link library for usage by CNTK.
|
||||
echo.
|
||||
echo Requirements:
|
||||
echo - Intel MKL SDK installed on the machine
|
||||
echo - MKLROOT environment variable is set to the MKL directory inside the Intel MKL SDK
|
||||
echo - Visual Studio 2013 installed and included in the path
|
||||
echo.
|
||||
|
||||
setlocal enableextensions enabledelayedexpansion
|
||||
|
||||
pushd "%~dp0"
|
||||
if errorlevel 1 (
|
||||
echo Could not change directory to script location.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not defined MKLROOT (
|
||||
echo Error: Environment variable MKLROOT is undefined.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "%MKLROOT%" (
|
||||
echo Error: Directory doesn't exist: "%MKLROOT%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set MKLBUILDERROOT=%MKLROOT%\tools\builder
|
||||
|
||||
if not exist "%MKLBUILDERROOT%" (
|
||||
echo Error: Directory doesn't exist: "%MKLBUILDERROOT%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
where /q nmake.exe
|
||||
if errorlevel 1 (
|
||||
echo Error: NMAKE.EXE not in path.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
where /q link.exe
|
||||
if errorlevel 1 (
|
||||
echo Error: LINK.EXE not in path.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set /p CNTKCUSTOMMKLVERSION=<version.txt
|
||||
if not defined CNTKCUSTOMMKLVERSION (
|
||||
echo Cannot determine CNTK custom MKL version.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if exist lib rmdir /s /q lib
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
if exist Publish rmdir /s /q Publish
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64
|
||||
|
||||
echo.
|
||||
echo Copying "%MKLBUILDERROOT%\lib".
|
||||
|
||||
xcopy /s /e /y /i "%MKLBUILDERROOT%\lib" lib
|
||||
if errorlevel 1 (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Compiling and copying libraries.
|
||||
|
||||
for %%t in (
|
||||
parallel
|
||||
sequential
|
||||
) do (
|
||||
|
||||
set TFIRSTCHAR=%%t
|
||||
set TFIRSTCHAR=!TFIRSTCHAR:~0,1!
|
||||
set LIBBASENAME=mkl_cntk_!TFIRSTCHAR!
|
||||
|
||||
echo.
|
||||
echo Calling NMAKE libintel64 export=functions.txt threading=%%t name=!LIBBASENAME! MKLROOT="%MKLROOT%".
|
||||
NMAKE /f "%MKLBUILDERROOT%\makefile" ^
|
||||
libintel64 ^
|
||||
export=functions.txt ^
|
||||
threading=%%t ^
|
||||
name=!LIBBASENAME! ^
|
||||
MKLROOT="%MKLROOT%"
|
||||
|
||||
if errorlevel 1 (
|
||||
echo Error: NMAKE.exe for threading=%%t failed.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
mkdir Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
move !LIBBASENAME!.dll Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
move !LIBBASENAME!.lib Publish\%CNTKCUSTOMMKLVERSION%\x64\%%t
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
del !LIBBASENAME!*
|
||||
if errorlevel 1 exit /b 1
|
||||
@REM TODO manifest?
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Copying libiomp5md.dll.
|
||||
|
||||
copy "%MKLROOT%\..\redist\intel64_win\compiler\libiomp5md.dll" Publish\%CNTKCUSTOMMKLVERSION%\x64\parallel
|
||||
if errorlevel 1 (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Removing LIB directory.
|
||||
|
||||
rmdir /s /q lib
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Copying include files to Publish\%CNTKCUSTOMMKLVERSION%\include.
|
||||
|
||||
mkdir Publish\%CNTKCUSTOMMKLVERSION%\include
|
||||
|
||||
for /f %%h in (headers.txt) do (
|
||||
copy "%MKLROOT%\include\%%h" Publish\%CNTKCUSTOMMKLVERSION%\include
|
||||
if errorlevel 1 (
|
||||
echo Failed to copy "%MKLROOT%\include\%%h".
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
copy README-for-redistributable.txt Publish\%CNTKCUSTOMMKLVERSION%\README.txt
|
||||
if errorlevel 1 (
|
||||
echo Failed to copy README.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
copy ..\..\LICENSE.md Publish\%CNTKCUSTOMMKLVERSION%
|
||||
if errorlevel 1 (
|
||||
echo Failed to copy LICENSE.md.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
popd
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
|
||||
//
|
||||
// CPPEvalV2Client.cpp : Sample application shows how to evaluate a model using CNTK V2 API.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// define GPU_AVAILABLE, if you want to run evaluation on a GPU device. You also need CNTK GPU binaries.
|
||||
// undefine GPU_AVAILABLE, if you want to run evaluation on a CPU device.
|
||||
// #define GPU_AVAILABLE
|
||||
|
||||
void MultiThreadsEvaluation(bool);
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
#ifdef GPU_AVAILABLE
|
||||
fprintf(stderr, "\n##### Run eval on GPU device. #####\n");
|
||||
MultiThreadsEvaluation(true);
|
||||
#else
|
||||
fprintf(stderr, "\n##### Run eval on CPU device. #####\n");
|
||||
MultiThreadsEvaluation(false);
|
||||
#endif
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CPPEvalV2Client.cpp" />
|
||||
<ClCompile Include="EvalMultithreads.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D771A06D-CC25-4582-B5CD-D2A4782BB005}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>CPPEvalV2Client</RootNamespace>
|
||||
<ProjectName>CPPEvalV2Client</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)..\..\$(Platform)\$(ProjectName).$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>WIN32;_CONSOLE;UNICODE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\..\Include</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\..\..\cntk</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>CNTKLibrary-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
|
||||
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CPPEvalV2Client.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EvalMultithreads.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -95,7 +95,7 @@ void MultiThreadsEvaluationWithClone(const DeviceDescriptor& device, const int t
|
|||
}
|
||||
|
||||
auto outputTimesParam = Parameter(NDArrayView::RandomUniform<float>({numOutputClasses, hiddenLayersDim}, -0.5, 0.5, 1, device));
|
||||
auto classifierFunc = Times(outputTimesParam, classifierRoot, 1, L"classifierOutput");
|
||||
auto classifierFunc = Times(outputTimesParam, classifierRoot, L"classifierOutput");
|
||||
|
||||
// Now test the structure
|
||||
if (classifierFunc->Parameters().size() != ((numHiddenLayers * 2) + 1))
|
||||
|
@ -128,11 +128,14 @@ void MultiThreadsEvaluationWithClone(const DeviceDescriptor& device, const int t
|
|||
/// It first loads a model, then spawns multi threads. Each thread uses Clone() to create a new
|
||||
/// instance of function and then use this instance to do evaluation.
|
||||
/// All cloned functions share the same parameters.
|
||||
/// Note: It uses the model trained by Examples\Image\GettingStarted\01_OneHidden.cntk as example. Instructions
|
||||
/// to train the model is described in Examples\Image\GettingStarted\README.md.
|
||||
/// The pre-trained model file 01_OneHidden needs to be in the current directory.
|
||||
/// </description>
|
||||
void MultiThreadsEvaluationWithLoadModel(const DeviceDescriptor& device, const int threadCount)
|
||||
{
|
||||
// The model file will be trained and copied to the current runtime directory first.
|
||||
auto modelFuncPtr = CNTK::LoadLegacyModel(DataType::Float, L"01_OneHidden", device);
|
||||
auto modelFuncPtr = CNTK::Function::LoadModel(DataType::Float, L"01_OneHidden", device);
|
||||
|
||||
|
||||
OutputFunctionInfo(modelFuncPtr);
|
||||
|
@ -287,13 +290,13 @@ inline FunctionPtr SetupFullyConnectedDNNLayer(Variable input, size_t outputDim,
|
|||
void OutputFunctionInfo(FunctionPtr func)
|
||||
{
|
||||
auto inputVariables = func->Arguments();
|
||||
fprintf(stderr, "Function %S: Input Variables (count=%lu)\n", func->Name().c_str(), inputVariables.size());
|
||||
fprintf(stderr, "Function '%S': Input Variables (count=%lu)\n", func->Name().c_str(), inputVariables.size());
|
||||
for_each(inputVariables.begin(), inputVariables.end(), [](const Variable v) {
|
||||
fprintf(stderr, " name=%S, kind=%d\n", v.Name().c_str(), static_cast<int>(v.Kind()));
|
||||
});
|
||||
|
||||
auto outputVariables = func->Outputs();
|
||||
fprintf(stderr, "Function %S: Output Variables (count=%lu)\n", func->Name().c_str(), outputVariables.size());
|
||||
fprintf(stderr, "Function '%S': Output Variables (count=%lu)\n", func->Name().c_str(), outputVariables.size());
|
||||
for_each(outputVariables.begin(), outputVariables.end(), [](const Variable v) {
|
||||
fprintf(stderr, " name=%S, kind=%d\n", v.Name().c_str(), static_cast<int>(v.Kind()));
|
||||
});
|
||||
|
@ -454,46 +457,37 @@ void RunEvaluationOneHidden(FunctionPtr evalFunc, const DeviceDescriptor& device
|
|||
|
||||
void MultiThreadsEvaluation(bool isGPUAvailable)
|
||||
{
|
||||
#ifndef CPUONLY
|
||||
if (isGPUAvailable)
|
||||
{
|
||||
fprintf(stderr, "Run evaluation on GPU device using GPU build.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Run evaluation on CPU device using GPU build.\n");
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "Run evaluation using CPU-only build.\n");
|
||||
#endif
|
||||
// The number of threads running evaluation in parallel.
|
||||
const int numOfThreads = 2;
|
||||
|
||||
fprintf(stderr, "\n##### Run evaluation on %s device with %d parallel evaluation thread(s). #####\n", isGPUAvailable ? "GPU" : "CPU", numOfThreads);
|
||||
|
||||
// Test multi-threads evaluation with new function
|
||||
fprintf(stderr, "Test multi-threaded evaluation with new function on CPU.\n");
|
||||
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::CPUDevice(), 2);
|
||||
fprintf(stderr, "\n##### Run evaluation using new function on CPU. #####\n");
|
||||
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::CPUDevice(), numOfThreads);
|
||||
if (isGPUAvailable)
|
||||
{
|
||||
fprintf(stderr, "Test multi-threaded evaluation with new function on GPU\n");
|
||||
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::GPUDevice(0), 2);
|
||||
fprintf(stderr, "\n##### Run evaluation using new function on GPU. #####\n");;
|
||||
MultiThreadsEvaluationWithNewFunction(DeviceDescriptor::GPUDevice(0), numOfThreads);
|
||||
}
|
||||
|
||||
// Test multi-threads evaluation using clone.
|
||||
fprintf(stderr, "Test multi-threaded evaluation using clone on CPU.\n");
|
||||
MultiThreadsEvaluationWithClone(DeviceDescriptor::CPUDevice(), 2);
|
||||
fprintf(stderr, "\n##### Run evaluation using clone function on CPU. #####\n");
|
||||
MultiThreadsEvaluationWithClone(DeviceDescriptor::CPUDevice(), numOfThreads);
|
||||
if (isGPUAvailable)
|
||||
{
|
||||
fprintf(stderr, "Test multi-threaded evaluation using clone on GPU.\n");
|
||||
MultiThreadsEvaluationWithClone(DeviceDescriptor::GPUDevice(0), 2);
|
||||
fprintf(stderr, "\n##### Run evaluation using clone function on GPU. #####\n");
|
||||
MultiThreadsEvaluationWithClone(DeviceDescriptor::GPUDevice(0), numOfThreads);
|
||||
}
|
||||
|
||||
// test multi-threads evaluation with loading existing models
|
||||
fprintf(stderr, "Test multi-threaded evaluation with loading existing models on CPU.\n");
|
||||
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::CPUDevice(), 2);
|
||||
fprintf(stderr, "\n##### Run evaluation using pre-trained model on CPU. #####\n");
|
||||
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::CPUDevice(), numOfThreads);
|
||||
if (isGPUAvailable)
|
||||
{
|
||||
fprintf(stderr, "Test multi-threaded evaluation with loading existing models on GPU.\n");
|
||||
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::GPUDevice(0), 2);
|
||||
fprintf(stderr, "\n##### Run evaluation using pre-trained model on GPU. #####\n");
|
||||
MultiThreadsEvaluationWithLoadModel(DeviceDescriptor::GPUDevice(0), numOfThreads);
|
||||
}
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPPEvalClient", "CPPEvalCli
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSEvalClient", "CSEvalClient\CSEvalClient.csproj", "{92CCF4B9-BFED-4914-901A-CF1327B1A02D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPPEvalV2Client", "CPPEvalV2Client\CPPEvalV2Client.vcxproj", "{D771A06D-CC25-4582-B5CD-D2A4782BB005}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
|
@ -20,6 +22,9 @@ Global
|
|||
{92CCF4B9-BFED-4914-901A-CF1327B1A02D}.Debug|x64.Build.0 = Debug|x64
|
||||
{92CCF4B9-BFED-4914-901A-CF1327B1A02D}.Release|x64.ActiveCfg = Release|x64
|
||||
{92CCF4B9-BFED-4914-901A-CF1327B1A02D}.Release|x64.Build.0 = Release|x64
|
||||
{D771A06D-CC25-4582-B5CD-D2A4782BB005}.Debug|x64.ActiveCfg = Release|x64
|
||||
{D771A06D-CC25-4582-B5CD-D2A4782BB005}.Release|x64.ActiveCfg = Release|x64
|
||||
{D771A06D-CC25-4582-B5CD-D2A4782BB005}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
m1=LoadModel($CurModel$, format=cntk)
|
||||
SetDefaultModel(m1)
|
||||
|
||||
# Add top-5 error prediction node.
|
||||
ErrTop5 = ClassificationError(labels, OutputNodes.z, Const(5), tag = Eval)
|
||||
|
||||
SaveModel(m1, $NewModel$, format=cntk)
|
|
@ -73,8 +73,8 @@ ResNetBottleneckInc {outChannels, interOutChannels, stride1x1, stride3x3, bnTime
|
|||
ConvBNLayer {outChannels, (1:1), (1:1), bnTimeConst}) (x)
|
||||
|
||||
# Shortcut
|
||||
stride = stride1x1.*stride3x3
|
||||
s = ConvBNReLULayer {outChannels, (1:1), stride, bnTimeConst} (x)
|
||||
stride[i:0..Length(stride1x1)-1] = stride1x1[i] * stride3x3[i]
|
||||
s = ConvBNLayer {outChannels, (1:1), stride, bnTimeConst} (x)
|
||||
|
||||
p = Plus(b, s)
|
||||
r = ReLU(p)
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
Conv(W, inp, outMap, kW, kH, hStride, vStride)
|
||||
[
|
||||
c = Convolution(W, inp, kW, kH, outMap, hStride, vStride, zeroPadding = true, imageLayout = "cudnn")
|
||||
]
|
||||
|
||||
BN(inp, mapCount, bValue, scValue, bnTimeConst)
|
||||
[
|
||||
b = Parameter(mapCount, 1, init = fixedValue, value = bValue)
|
||||
sc = Parameter(mapCount, 1, init = fixedValue, value = scValue)
|
||||
m = Parameter(mapCount, 1, init = fixedValue, value = 0, learningRateMultiplier = 0)
|
||||
v = Parameter(mapCount, 1, init = fixedValue, value = 0, learningRateMultiplier = 0)
|
||||
|
||||
y = BatchNormalization(inp, sc, b, m, v, spatial = true, normalizationTimeConstant = bnTimeConst, epsilon = 0.000000001, imageLayout = "cudnn", engine = "cudnn")
|
||||
]
|
||||
|
||||
ConvBNLayerW(W, inp, outMap, kW, kH, hStride, vStride, bValue, scValue, bnTimeConst)
|
||||
[
|
||||
c = Conv(W, inp, outMap, kW, kH, hStride, vStride)
|
||||
y = BN(c, outMap, bValue, scValue, bnTimeConst)
|
||||
]
|
||||
|
||||
ConvBNLayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
|
||||
[
|
||||
W = Parameter(outMap, inWCount, init = Gaussian, initValueScale = wScale)
|
||||
c = Conv(W, inp, outMap, kW, kH, hStride, vStride)
|
||||
y = BN(c, outMap, bValue, scValue, bnTimeConst)
|
||||
]
|
||||
|
||||
ConvBNReLULayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
|
||||
[
|
||||
c = ConvBNLayer(inp, outMap, inWCount, kW, kH, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
|
||||
y = RectifiedLinear(c)
|
||||
]
|
||||
|
||||
Conv1x1(inp, outMap, inMap, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
|
||||
[
|
||||
W = Parameter(outMap, inMap, init = Gaussian, initValueScale = wScale)
|
||||
c = Convolution(W, inp, 1, 1, outMap, hStride, vStride, zeroPadding = false, imageLayout = "cudnn")
|
||||
y = BN(c, outMap, bValue, scValue, bnTimeConst)
|
||||
]
|
||||
|
||||
Conv1x1ReLU(inp, outMap, inMap, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
|
||||
[
|
||||
c = Conv1x1(inp, outMap, inMap, hStride, vStride, wScale, bValue, scValue, bnTimeConst)
|
||||
y = RectifiedLinear(c)
|
||||
]
|
||||
|
||||
# Standard building block for ResNet with identity shortcut (option A).
|
||||
ResNetNode2A(inp, outMap, inWCount, kW, kH, wScale, bValue, scValue)
|
||||
[
|
||||
# First convolution layer.
|
||||
c1 = ConvBNReLULayer(inp, outMap, inWCount, kW, kH, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
# Second convolution layer, no ReLU.
|
||||
c2 = ConvBNLayer(c1, outMap, inWCount, kW, kH, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
# Identity shortcut.
|
||||
p = Plus(c2, inp)
|
||||
y = RectifiedLinear(p)
|
||||
]
|
||||
|
||||
# Standard building block for ResNet with padding (option A).
|
||||
ResNetNode2AInc(inp, outMap, inWCount, wCount, kW, kH, wScale, bValue, scValue, bnTimeConst, Wproj)
|
||||
[
|
||||
# First convolution layer.
|
||||
c1 = ConvBNReLULayer(inp, outMap, inWCount, kW, kH, 2, 2, wScale, bValue, scValue, bnTimeConst)
|
||||
# Second convolution layer, no ReLU.
|
||||
c2 = ConvBNLayer(c1, outMap, wCount, kW, kH, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
|
||||
# Projection convolution layer.
|
||||
c_proj = ConvBNLayerW(Wproj, inp, outMap, 1, 1, 2, 2, bValue, scValue, bnTimeConst)
|
||||
|
||||
p = Plus(c2, c_proj)
|
||||
y2 = RectifiedLinear(p)
|
||||
]
|
||||
|
||||
# Standard building block for ResNet with padding (option B).
|
||||
ResNetNode2BInc(inp, outMap, inMap, inWCount, wCount, kW, kH, wScale, bValue, scValue, bnTimeConst, stride1x1, stride3x3)
|
||||
[
|
||||
# First convolution layer.
|
||||
c1 = ConvBNReLULayer(inp, outMap, inWCount, kW, kH, stride1x1, stride1x1, wScale, bValue, scValue, bnTimeConst)
|
||||
# Second convolution layer, no ReLU.
|
||||
c2 = ConvBNLayer(c1, outMap, wCount, kW, kH, stride3x3, stride3x3, wScale, bValue, scValue, bnTimeConst)
|
||||
|
||||
# Projection convolution layer.
|
||||
c_proj = Conv1x1(inp, outMap, inMap, 2, 2, wScale, bValue, scValue, bnTimeConst)
|
||||
|
||||
p = Plus(c2, c_proj)
|
||||
y2 = RectifiedLinear(p)
|
||||
]
|
||||
|
||||
# Bottleneck building block for ResNet.
|
||||
ResNetNode3A(inp, inMap, convMap, outMap, convWCount, wScale, bValue, scValue, bnTimeConst)
|
||||
[
|
||||
# 1x1 reducing convolution.
|
||||
c1 = Conv1x1ReLU(inp, convMap, inMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
# 3x3 convolution.
|
||||
c2 = ConvBNReLULayer(c1, convMap, convWCount, 3, 3, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
# 1x1 expanding convolution, no ReLU.
|
||||
c3 = Conv1x1(c2, outMap, convMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
|
||||
p = Plus(c3, inp)
|
||||
y = RectifiedLinear(p)
|
||||
]
|
||||
|
||||
ResNetNode3AInc(inp, inMap, convMap, outMap, convWCount, wScale, bValue, scValue, bnTimeConst, wProj, projStride)
|
||||
[
|
||||
# 1x1 reducing convolution.
|
||||
c1 = Conv1x1ReLU(inp, convMap, inMap, projStride, projStride, wScale, bValue, scValue, bnTimeConst)
|
||||
# 3x3 convolution.
|
||||
c2 = ConvBNReLULayer(c1, convMap, convWCount, 3, 3, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
# 1x1 expanding convolution, no ReLU.
|
||||
c3 = Conv1x1(c2, outMap, convMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
# Input-to-output mapping convolution.
|
||||
c_proj = ConvBNLayerW(wProj, inp, outMap, 1, 1, projStride, projStride, wScale, bValue, scValue, bnTimeConst)
|
||||
|
||||
p = Plus(c3, c_proj)
|
||||
y = RectifiedLinear(p)
|
||||
]
|
||||
|
||||
ResNetNode3BInc(inp, inMap, convMap, outMap, convWCount, wScale, bValue, scValue, bnTimeConst, projStride, stride1x1, stride3x3)
|
||||
[
|
||||
# 1x1 reducing convolution.
|
||||
c1 = Conv1x1ReLU(inp, convMap, inMap, stride1x1, stride1x1, wScale, bValue, scValue, bnTimeConst)
|
||||
# 3x3 convolution.
|
||||
c2 = ConvBNReLULayer(c1, convMap, convWCount, 3, 3, stride3x3, stride3x3, wScale, bValue, scValue, bnTimeConst)
|
||||
# 1x1 expanding convolution, no ReLU.
|
||||
c3 = Conv1x1(c2, outMap, convMap, 1, 1, wScale, bValue, scValue, bnTimeConst)
|
||||
# Input-to-output mapping convolution.
|
||||
c_proj = Conv1x1(inp, outMap, inMap, projStride, projStride, wScale, bValue, scValue, bnTimeConst)
|
||||
|
||||
p = Plus(c3, c_proj)
|
||||
y = RectifiedLinear(p)
|
||||
]
|
||||
|
||||
DnnLayer(hiddenDim, labelDim, x, wScale, bValue)
|
||||
[
|
||||
W = Parameter(labelDim, hiddenDim, init = Gaussian, initValueScale = wScale)
|
||||
b = Parameter(labelDim, init = fixedValue, value = bValue)
|
||||
t = Times(W, x)
|
||||
z = Plus(t, b)
|
||||
]
|
||||
|
||||
MaxNDPooling(inp, kW, kH, hStride, vStride)
|
||||
[
|
||||
p = Pooling(inp, "max", {kW, kH, 1}, stride = {hStride, vStride, 1}, autoPadding = {true, true, false}, imageLayout = "cudnn")
|
||||
]
|
|
@ -1,12 +0,0 @@
|
|||
import sys
|
||||
import numpy as np
|
||||
|
||||
def writeConvWeights(fname, cmapIn, cmapOut):
|
||||
w = np.eye(cmapOut, cmapIn)
|
||||
np.savetxt(fname, w, fmt = '%d', delimiter = ' ')
|
||||
|
||||
if __name__ == "__main__":
|
||||
cmapIn = int(sys.argv[1])
|
||||
cmapOut = int(sys.argv[2])
|
||||
fname = sys.argv[3]
|
||||
writeConvWeights(fname, cmapIn, cmapOut)
|
|
@ -1,5 +1,7 @@
|
|||
# CNTK Examples: Image/Classification/ResNet
|
||||
|
||||
The recipes above are in BrainScript. [For Python click here](https://github.com/Microsoft/CNTK/blob/v2.0.beta1.0/bindings/python/tutorials/CNTK_201A_CIFAR-10_DataLoader.ipynb).
|
||||
|
||||
## Overview
|
||||
|
||||
|Data: |The CIFAR-10 dataset (http://www.cs.toronto.edu/~kriz/cifar.html) and the ILSVRC2012 dataset (http://www.image-net.org/challenges/LSVRC/2012/) for image classification.
|
||||
|
@ -12,7 +14,7 @@
|
|||
## Running the example
|
||||
|
||||
### Getting the data
|
||||
We use the CIFAR-10 and ILSVRC2012 datasets to demonstrate how to train a deep convolutional residual network (ResNet). ResNet was invented by Researchers at [Microsoft Research](https://www.microsoft.com/en-us/research/), and it won first place in both [ILSVRC](http://www.image-net.org/challenges/LSVRC/) and [MS COCO](http://mscoco.org/) competitions in the year of 2015.
|
||||
We use the CIFAR-10 and ILSVRC2012 datasets to demonstrate how to train a deep convolutional residual network (ResNet). ResNet was invented by Researchers at [Microsoft Research](https://www.microsoft.com/en-us/research/), and it won first place in both [ILSVRC](http://www.image-net.org/challenges/LSVRC/) and [MS COCO](http://mscoco.org/) competitions in the year of 2015. The original implementation of ResNet was on Caffe (https://github.com/KaimingHe/deep-residual-networks).
|
||||
|
||||
CIFAR-10 and ILSVRC2012 datasets are not included in the CNTK distribution. The CIFAR-10 datasets can be downloaded and converted by following the instructions in [DataSets/CIFAR-10](../../DataSets/CIFAR-10). We recommend you to keep the downloaded data in the respective folder while downloading, as the configuration files in this folder assumes that by default. For ILSVRC2012 datasets, you may obtain it through http://image-net.org.
|
||||
|
||||
|
@ -39,16 +41,22 @@ In this example we increase the depth of the ResNet to 110 layers. That is, we s
|
|||
|
||||
The network achieves an error rate of about `6.2-6.5%`.
|
||||
|
||||
### ImageNet
|
||||
### ResNet50_ImageNet1K.cntk
|
||||
|
||||
The BrainScript configuration files for ImageNet will be available soon. For now only a few deprecated ndl files are available here. The following table contains results as well as links to pre-trained models that can be used in various applications.
|
||||
This is an example using a 50-layer ResNet to train on ILSVRC2012 datasets. Compared with the CIFAR-10 examples, we introduced bottleneck blocks to reduce the amount of computation by replacing the two `3x3` convolutions by a `1x1` convolution, bottlenecked to 1/4 of feature maps, followed by a `3x3` convolution, and then a `1x1` convolution again, with the same number feature maps as input.
|
||||
|
||||
| Network | Top-1 error | Top-5 error | Model
|
||||
| ------------- | ----------- | ----------- | ----------
|
||||
| ResNet-18 | 29.57 | 10.41 | [Download](https://www.cntk.ai/resnet/ResNet_18.model)
|
||||
| ResNet-34 | 27.31 | 8.97 | [Download](https://www.cntk.ai/resnet/ResNet_34.model)
|
||||
| ResNet-50 | 24.56 | 7.47 |
|
||||
| ResNet-152 | 22.57 | 6.44 | [Download](https://www.cntk.ai/resnet/ResNet_152.model)
|
||||
Run the example from the current folder using:
|
||||
|
||||
## Notes
|
||||
This work is an implementation of ResNets in CNTK. If you are interested in the original implementation of ResNet, follow [this link](https://github.com/KaimingHe/deep-residual-networks).
|
||||
`cntk configFile=ResNet50_ImageNet1K.cntk`
|
||||
|
||||
### ResNet101_ImageNet1K.cntk
|
||||
|
||||
Increase the depth of the ResNet to 101 layers:
|
||||
|
||||
`cntk configFile=ResNet101_ImageNet1K.cntk`
|
||||
|
||||
### ResNet152_ImageNet1K.cntk
|
||||
|
||||
Further increase the depth of the ResNet to 152 layers:
|
||||
|
||||
`cntk configFile=ResNet152_ImageNet1K.cntk`
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
# Node: ResNet-50 with ImageNet -- 101 layers bottleneck ResNet for image classification
|
||||
# Reference: "Deep Residual Learning for Image Recognition" https://arxiv.org/abs/1512.03385
|
||||
|
||||
command = TrainNetwork:BNStatistics:Eval
|
||||
|
||||
precision = "float"; traceLevel = 1 ; deviceId = "auto"
|
||||
|
||||
rootDir = "." ; configDir = "$RootDir$" ; dataDir = "$RootDir$" ;
|
||||
outputDir = "$rootDir$/Output" ;
|
||||
|
||||
modelPath = "$outputDir$/Models/ResNet_101"
|
||||
stderr = "$outputDir$/ResNet_101_BS_out"
|
||||
|
||||
parallelTrain = true
|
||||
|
||||
TrainNetwork = {
|
||||
action = "train"
|
||||
|
||||
BrainScriptNetworkBuilder = {
|
||||
include "$configDir$/Macros.bs"
|
||||
|
||||
imageShape = 224:224:3 # image dimensions
|
||||
labelDim = 1000 # number of distinct labels
|
||||
|
||||
cMap = 64:128:256:512:1024:2048
|
||||
numLayers = 2:3:22:2
|
||||
bnTimeConst = 0
|
||||
|
||||
# stride in BottleneckInc
|
||||
stride1x1 = (2:2)
|
||||
stride3x3 = (1:1)
|
||||
|
||||
model = Sequential(
|
||||
# conv1 and max pooling
|
||||
ConvBNReLULayer {cMap[0], (7:7), (2:2), bnTimeConst} :
|
||||
MaxPoolingLayer {(3:3), stride = 2, pad = true} :
|
||||
|
||||
# conv2_x
|
||||
ResNetBottleneckInc {cMap[2], cMap[0], (1:1), (1:1), bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[0], cMap[2], cMap[0], bnTimeConst} :
|
||||
|
||||
# conv3_x
|
||||
ResNetBottleneckInc {cMap[3], cMap[1], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[1], cMap[3], cMap[1], bnTimeConst} :
|
||||
|
||||
# conv4_x
|
||||
ResNetBottleneckInc {cMap[4], cMap[2], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[2], cMap[4], cMap[2], bnTimeConst} :
|
||||
|
||||
# conv5_x
|
||||
ResNetBottleneckInc {cMap[5], cMap[3], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[3], cMap[5], cMap[3], bnTimeConst} :
|
||||
|
||||
# avg pooling
|
||||
AveragePoolingLayer {(7: 7), stride = 1} :
|
||||
|
||||
# FC
|
||||
LinearLayer {labelDim, init= 'uniform'}
|
||||
)
|
||||
|
||||
# inputs
|
||||
features = Input {imageShape}
|
||||
labels = Input {labelDim}
|
||||
|
||||
# apply model to features
|
||||
ol = model (features)
|
||||
|
||||
# loss and error computation
|
||||
ce = CrossEntropyWithSoftmax (labels, ol)
|
||||
errs = ClassificationError (labels, ol)
|
||||
top5Errs = ClassificationError (labels, ol, topN = 5)
|
||||
|
||||
# declare special nodes
|
||||
featureNodes = (features)
|
||||
labelNodes = (labels)
|
||||
criterionNodes = (ce)
|
||||
evaluationNodes = (errs) # top5Errs only used in Eval
|
||||
outputNodes = (ol)
|
||||
}
|
||||
|
||||
SGD = {
|
||||
epochSize = 0
|
||||
minibatchSize = 256
|
||||
maxEpochs = 120
|
||||
learningRatesPerMB = 1*30: 0.1*30: 0.01*30: 0.001
|
||||
momentumPerMB = 0.9
|
||||
gradUpdateType = "None"
|
||||
L2RegWeight = 0.0001
|
||||
dropoutRate = 0
|
||||
numMBsToShowResult = 500
|
||||
|
||||
disableRegInBatchNormalization = true
|
||||
|
||||
ParallelTrain = {
|
||||
parallelizationMethod = "DataParallelSGD"
|
||||
distributedMBReading = true
|
||||
parallelizationStartEpoch = 1
|
||||
DataParallelSGD = {
|
||||
gradientBits = 32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/train_map.txt"
|
||||
randomize = "Auto"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Random"
|
||||
jitterType = "UniRatio"
|
||||
cropRatio = 0.46666:0.875
|
||||
hflip = true
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
|
||||
cvReader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/val_map.txt"
|
||||
randomize = "None"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Center"
|
||||
cropRatio = 0.875
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BNStatistics = {
|
||||
action = "bnstat"
|
||||
modelPath = "$modelPath$"
|
||||
minibatchSize = 256
|
||||
itersPerNode = 30
|
||||
enableDistributedMBReading = true
|
||||
|
||||
reader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/train_map.txt"
|
||||
randomize = "Auto"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Random"
|
||||
hflip = true
|
||||
cropRatio = 0.46666:0.875
|
||||
jitterType = "UniRatio"
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Eval = {
|
||||
action = "test"
|
||||
modelPath = "$modelPath$.PBN"
|
||||
minibatchSize = 200
|
||||
evalNodeNames = errs:top5Errs
|
||||
|
||||
reader={
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/val_map.txt"
|
||||
randomize = "None"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Center"
|
||||
cropRatio = 0.875
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
# Node: ResNet-50 with ImageNet -- 152 layers bottleneck ResNet for image classification
|
||||
# Reference: "Deep Residual Learning for Image Recognition" https://arxiv.org/abs/1512.03385
|
||||
|
||||
command = TrainNetwork:BNStatistics:Eval
|
||||
|
||||
precision = "float"; traceLevel = 1 ; deviceId = "auto"
|
||||
|
||||
rootDir = "." ; configDir = "$RootDir$" ; dataDir = "$RootDir$" ;
|
||||
outputDir = "$rootDir$/Output" ;
|
||||
|
||||
modelPath = "$outputDir$/Models/ResNet_152"
|
||||
stderr = "$outputDir$/ResNet_152_BS_out"
|
||||
|
||||
parallelTrain = true
|
||||
|
||||
TrainNetwork = {
|
||||
action = "train"
|
||||
|
||||
BrainScriptNetworkBuilder = {
|
||||
include "$configDir$/Macros.bs"
|
||||
|
||||
imageShape = 224:224:3 # image dimensions
|
||||
labelDim = 1000 # number of distinct labels
|
||||
|
||||
cMap = 64:128:256:512:1024:2048
|
||||
numLayers = 2:7:35:2
|
||||
bnTimeConst = 0
|
||||
|
||||
# stride in BottleneckInc
|
||||
stride1x1 = (2:2)
|
||||
stride3x3 = (1:1)
|
||||
|
||||
model = Sequential(
|
||||
# conv1 and max pooling
|
||||
ConvBNReLULayer {cMap[0], (7:7), (2:2), bnTimeConst} :
|
||||
MaxPoolingLayer {(3:3), stride = 2, pad = true} :
|
||||
|
||||
# conv2_x
|
||||
ResNetBottleneckInc {cMap[2], cMap[0], (1:1), (1:1), bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[0], cMap[2], cMap[0], bnTimeConst} :
|
||||
|
||||
# conv3_x
|
||||
ResNetBottleneckInc {cMap[3], cMap[1], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[1], cMap[3], cMap[1], bnTimeConst} :
|
||||
|
||||
# conv4_x
|
||||
ResNetBottleneckInc {cMap[4], cMap[2], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[2], cMap[4], cMap[2], bnTimeConst} :
|
||||
|
||||
# conv5_x
|
||||
ResNetBottleneckInc {cMap[5], cMap[3], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[3], cMap[5], cMap[3], bnTimeConst} :
|
||||
|
||||
# avg pooling
|
||||
AveragePoolingLayer {(7: 7), stride = 1} :
|
||||
|
||||
# FC
|
||||
LinearLayer {labelDim, init= 'uniform'}
|
||||
)
|
||||
|
||||
# inputs
|
||||
features = Input {imageShape}
|
||||
labels = Input {labelDim}
|
||||
|
||||
# apply model to features
|
||||
ol = model (features)
|
||||
|
||||
# loss and error computation
|
||||
ce = CrossEntropyWithSoftmax (labels, ol)
|
||||
errs = ClassificationError (labels, ol)
|
||||
top5Errs = ClassificationError (labels, ol, topN = 5)
|
||||
|
||||
# declare special nodes
|
||||
featureNodes = (features)
|
||||
labelNodes = (labels)
|
||||
criterionNodes = (ce)
|
||||
evaluationNodes = (errs) # top5Errs only used in Eval
|
||||
outputNodes = (ol)
|
||||
}
|
||||
|
||||
SGD = {
|
||||
epochSize = 0
|
||||
minibatchSize = 256
|
||||
maxEpochs = 120
|
||||
learningRatesPerMB = 1*30: 0.1*30: 0.01*30: 0.001
|
||||
momentumPerMB = 0.9
|
||||
gradUpdateType = "None"
|
||||
L2RegWeight = 0.0001
|
||||
dropoutRate = 0
|
||||
numMBsToShowResult = 500
|
||||
|
||||
disableRegInBatchNormalization = true
|
||||
|
||||
ParallelTrain = {
|
||||
parallelizationMethod = "DataParallelSGD"
|
||||
distributedMBReading = true
|
||||
parallelizationStartEpoch = 1
|
||||
DataParallelSGD = {
|
||||
gradientBits = 32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/train_map.txt"
|
||||
randomize = "Auto"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Random"
|
||||
jitterType = "UniRatio"
|
||||
cropRatio = 0.46666:0.875
|
||||
hflip = true
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
|
||||
cvReader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/val_map.txt"
|
||||
randomize = "None"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Center"
|
||||
cropRatio = 0.875
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BNStatistics = {
|
||||
action = "bnstat"
|
||||
modelPath = "$modelPath$"
|
||||
minibatchSize = 256
|
||||
itersPerNode = 30
|
||||
enableDistributedMBReading = true
|
||||
|
||||
reader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/train_map.txt"
|
||||
randomize = "Auto"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Random"
|
||||
hflip = true
|
||||
cropRatio = 0.46666:0.875
|
||||
jitterType = "UniRatio"
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Eval = {
|
||||
action = "test"
|
||||
modelPath = "$modelPath$.PBN"
|
||||
minibatchSize = 200
|
||||
evalNodeNames = errs:top5Errs
|
||||
|
||||
reader={
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/val_map.txt"
|
||||
randomize = "None"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Center"
|
||||
cropRatio = 0.875
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
# Node: ResNet-50 with ImageNet -- 50 layers bottleneck ResNet for image classification
|
||||
# Reference: "Deep Residual Learning for Image Recognition" https://arxiv.org/abs/1512.03385
|
||||
|
||||
command = TrainNetwork:BNStatistics:Eval
|
||||
|
||||
precision = "float"; traceLevel = 1 ; deviceId = "auto"
|
||||
|
||||
rootDir = "." ; configDir = "$RootDir$" ; dataDir = "$RootDir$" ;
|
||||
outputDir = "$rootDir$/Output" ;
|
||||
|
||||
modelPath = "$outputDir$/Models/ResNet_50"
|
||||
stderr = "$outputDir$/ResNet_50_BS_out"
|
||||
|
||||
parallelTrain = true
|
||||
|
||||
TrainNetwork = {
|
||||
action = "train"
|
||||
|
||||
BrainScriptNetworkBuilder = {
|
||||
include "$configDir$/Macros.bs"
|
||||
|
||||
imageShape = 224:224:3 # image dimensions
|
||||
labelDim = 1000 # number of distinct labels
|
||||
|
||||
cMap = 64:128:256:512:1024:2048
|
||||
numLayers = 2:3:5:2
|
||||
bnTimeConst = 0
|
||||
|
||||
# stride in BottleneckInc
|
||||
stride1x1 = (2:2)
|
||||
stride3x3 = (1:1)
|
||||
|
||||
model = Sequential(
|
||||
# conv1 and max pooling
|
||||
ConvBNReLULayer {cMap[0], (7:7), (2:2), bnTimeConst} :
|
||||
MaxPoolingLayer {(3:3), stride = 2, pad = true} :
|
||||
|
||||
# conv2_x
|
||||
ResNetBottleneckInc {cMap[2], cMap[0], (1:1), (1:1), bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[0], cMap[2], cMap[0], bnTimeConst} :
|
||||
|
||||
# conv3_x
|
||||
ResNetBottleneckInc {cMap[3], cMap[1], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[1], cMap[3], cMap[1], bnTimeConst} :
|
||||
|
||||
# conv4_x
|
||||
ResNetBottleneckInc {cMap[4], cMap[2], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[2], cMap[4], cMap[2], bnTimeConst} :
|
||||
|
||||
# conv5_x
|
||||
ResNetBottleneckInc {cMap[5], cMap[3], stride1x1, stride3x3, bnTimeConst} :
|
||||
ResNetBottleneckStack {numLayers[3], cMap[5], cMap[3], bnTimeConst} :
|
||||
|
||||
# avg pooling
|
||||
AveragePoolingLayer {(7: 7), stride = 1} :
|
||||
|
||||
# FC
|
||||
LinearLayer {labelDim, init = 'uniform'}
|
||||
)
|
||||
|
||||
# inputs
|
||||
features = Input {imageShape}
|
||||
labels = Input {labelDim}
|
||||
|
||||
# apply model to features
|
||||
z = model (features)
|
||||
|
||||
# loss and error computation
|
||||
ce = CrossEntropyWithSoftmax (labels, z)
|
||||
errs = ClassificationError (labels, z)
|
||||
top5Errs = ClassificationError (labels, z, topN = 5)
|
||||
|
||||
# declare special nodes
|
||||
featureNodes = (features)
|
||||
labelNodes = (labels)
|
||||
criterionNodes = (ce)
|
||||
evaluationNodes = (errs) # top5Errs only used in Eval
|
||||
outputNodes = (z)
|
||||
}
|
||||
|
||||
SGD = {
|
||||
epochSize = 0
|
||||
minibatchSize = 256
|
||||
maxEpochs = 120
|
||||
learningRatesPerMB = 1*30: 0.1*30: 0.01*30: 0.001
|
||||
momentumPerMB = 0.9
|
||||
gradUpdateType = "None"
|
||||
L2RegWeight = 0.0001
|
||||
dropoutRate = 0
|
||||
numMBsToShowResult = 500
|
||||
|
||||
disableRegInBatchNormalization = true
|
||||
|
||||
ParallelTrain = {
|
||||
parallelizationMethod = "DataParallelSGD"
|
||||
distributedMBReading = true
|
||||
parallelizationStartEpoch = 1
|
||||
DataParallelSGD = {
|
||||
gradientBits = 32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/train_map.txt"
|
||||
randomize = "Auto"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Random"
|
||||
jitterType = "UniRatio"
|
||||
cropRatio = 0.46666:0.875
|
||||
hflip = true
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
|
||||
cvReader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/val_map.txt"
|
||||
randomize = "None"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Center"
|
||||
cropRatio = 0.875
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Re-statistics the mean and variance of batch normalization layers while other parameters frozen after training
|
||||
# more details: https://github.com/Microsoft/CNTK/wiki/Post-Batch-Normalization-Statistics#post-batch-normalization-statistics
|
||||
BNStatistics = {
|
||||
action = "bnstat"
|
||||
modelPath = "$modelPath$"
|
||||
minibatchSize = 256
|
||||
itersPerNode = 30
|
||||
enableDistributedMBReading = true
|
||||
|
||||
reader = {
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/train_map.txt"
|
||||
randomize = "Auto"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Random"
|
||||
hflip = true
|
||||
cropRatio = 0.46666:0.875
|
||||
jitterType = "UniRatio"
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Eval = {
|
||||
action = "test"
|
||||
modelPath = "$modelPath$.PBN"
|
||||
minibatchSize = 200
|
||||
evalNodeNames = errs:top5Errs
|
||||
|
||||
reader={
|
||||
readerType = "ImageReader"
|
||||
file = "$DataDir$/val_map.txt"
|
||||
randomize = "None"
|
||||
features = {
|
||||
width = 224
|
||||
height = 224
|
||||
channels = 3
|
||||
cropType = "Center"
|
||||
cropRatio = 0.875
|
||||
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
|
||||
}
|
||||
labels = {
|
||||
labelDim = 1000
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
load=ndlMacros
|
||||
run=DNN
|
||||
|
||||
ndlMacros = [
|
||||
ImageW = 224
|
||||
ImageH = 224
|
||||
ImageC = 3
|
||||
LabelDim = 1000
|
||||
|
||||
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
|
||||
labels = Input(LabelDim, tag = label)
|
||||
|
||||
# Kernels width and height.
|
||||
kW = 3
|
||||
kH = 3
|
||||
# Kernel stride.
|
||||
hs = 1
|
||||
vs = 1
|
||||
|
||||
# Initial parameter values.
|
||||
convWScale = 7.07
|
||||
convBValue = 0
|
||||
|
||||
fcWScale = 2.26
|
||||
fcBValue = 0
|
||||
|
||||
scValue = 1
|
||||
|
||||
# Batch normalization time constant.
|
||||
bnTimeConst = 4096
|
||||
]
|
||||
|
||||
DNN=[
|
||||
cMap1 = 64
|
||||
cMap2 = 128
|
||||
cMap3 = 256
|
||||
cMap4 = 512
|
||||
cMap5 = 1024
|
||||
cMap6 = 2048
|
||||
|
||||
conv1WScale = 0.6
|
||||
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
|
||||
# Max pooling
|
||||
pool1W = 3
|
||||
pool1H = 3
|
||||
pool1hs = 2
|
||||
pool1vs = 2
|
||||
pool1 = MaxPooling(conv1, pool1W, pool1H, pool1hs, pool1vs, imageLayout = "cudnn")
|
||||
|
||||
rn1_1 = ResNetNode3BInc(pool1, cMap1, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst, 1, 1, 1)
|
||||
rn1_2 = ResNetNode3A(rn1_1, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn1_3 = ResNetNode3A(rn1_2, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
rn2_1 = ResNetNode3BInc(rn1_3, cMap3, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
|
||||
rn2_2 = ResNetNode3A(rn2_1, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_3 = ResNetNode3A(rn2_2, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_4 = ResNetNode3A(rn2_3, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_5 = ResNetNode3A(rn2_4, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_6 = ResNetNode3A(rn2_5, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_7 = ResNetNode3A(rn2_6, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_8 = ResNetNode3A(rn2_7, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
rn3_1 = ResNetNode3BInc(rn2_8, cMap4, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
|
||||
rn3_2 = ResNetNode3A(rn3_1, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_3 = ResNetNode3A(rn3_2, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_4 = ResNetNode3A(rn3_3, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_5 = ResNetNode3A(rn3_4, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_6 = ResNetNode3A(rn3_5, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_7 = ResNetNode3A(rn3_6, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_8 = ResNetNode3A(rn3_7, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_9 = ResNetNode3A(rn3_8, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_10= ResNetNode3A(rn3_9, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_11= ResNetNode3A(rn3_10, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_12= ResNetNode3A(rn3_11, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_13= ResNetNode3A(rn3_12, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_14= ResNetNode3A(rn3_13, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_15= ResNetNode3A(rn3_14, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_16= ResNetNode3A(rn3_15, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_17= ResNetNode3A(rn3_16, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_18= ResNetNode3A(rn3_17, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_19= ResNetNode3A(rn3_18, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_20= ResNetNode3A(rn3_19, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_21= ResNetNode3A(rn3_20, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_22= ResNetNode3A(rn3_21, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_23= ResNetNode3A(rn3_22, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_24= ResNetNode3A(rn3_23, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_25= ResNetNode3A(rn3_24, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_26= ResNetNode3A(rn3_25, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_27= ResNetNode3A(rn3_26, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_28= ResNetNode3A(rn3_27, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_29= ResNetNode3A(rn3_28, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_30= ResNetNode3A(rn3_29, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_31= ResNetNode3A(rn3_30, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_32= ResNetNode3A(rn3_31, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_33= ResNetNode3A(rn3_32, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_34= ResNetNode3A(rn3_33, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_35= ResNetNode3A(rn3_34, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_36= ResNetNode3A(rn3_35, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
rn4_1 = ResNetNode3BInc(rn3_36, cMap5, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
|
||||
rn4_2 = ResNetNode3A(rn4_1, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn4_3 = ResNetNode3A(rn4_2, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
# Global average pooling
|
||||
pool2W = 7
|
||||
pool2H = 7
|
||||
pool2hs = 1
|
||||
pool2vs = 1
|
||||
pool2 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
|
||||
|
||||
ol = DnnLayer(cMap6, labelDim, pool2, fcWScale, fcBValue)
|
||||
|
||||
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
|
||||
Err = ClassificationError(labels, ol, tag = Eval)
|
||||
OutputNodes = ol
|
||||
]
|
|
@ -1,136 +0,0 @@
|
|||
# Note: This sample uses the deprecated NdlNetworkBuilder.
|
||||
# An updated version using BrainScript is coming soon.
|
||||
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
|
||||
#
|
||||
RootDir = "."
|
||||
|
||||
ConfigDir = "$RootDir$"
|
||||
DataDir = "$RootDir$"
|
||||
OutputDir = "$RootDir$/Output"
|
||||
ModelDir = "$OutputDir$/Models"
|
||||
|
||||
ndlMacros="$ConfigDir$/Macros.ndl"
|
||||
|
||||
precision="float"
|
||||
deviceId="Auto"
|
||||
|
||||
command=Train:CreateEval:Test
|
||||
|
||||
parallelTrain="false"
|
||||
|
||||
stderr="$OutputDir$/ResNet_152"
|
||||
traceLevel=1
|
||||
numMBsToShowResult=500
|
||||
|
||||
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
|
||||
stride1x1=1
|
||||
stride3x3=2
|
||||
|
||||
Train=[
|
||||
action="train"
|
||||
modelPath="$ModelDir$/ResNet_152"
|
||||
|
||||
NDLNetworkBuilder=[
|
||||
networkDescription="$ConfigDir$/ResNet_152.ndl"
|
||||
]
|
||||
|
||||
SGD=[
|
||||
epochSize=0
|
||||
minibatchSize=256
|
||||
# Note that learning rates are 10x more than in the paper due to a different
|
||||
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
|
||||
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
|
||||
momentumPerMB=0.9
|
||||
maxEpochs=125
|
||||
gradUpdateType="None"
|
||||
L2RegWeight=0.0001
|
||||
dropoutRate=0
|
||||
|
||||
ParallelTrain=[
|
||||
parallelizationMethod="DataParallelSGD"
|
||||
distributedMBReading="true"
|
||||
parallelizationStartEpoch=1
|
||||
DataParallelSGD=[
|
||||
gradientBits=32
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
# Map file which maps images to labels using the following format:
|
||||
# <full path to image><tab><numerical label (0-based class id)>
|
||||
# Example:
|
||||
# C:\Data\ImageNet\2012\train\n01440764\n01440764_10026.JPEG<tab>0
|
||||
file="$DataDir$/train_map.txt"
|
||||
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
|
||||
randomize="Auto"
|
||||
features=[
|
||||
# Below are the required parameters.
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
# Below are the optional parameters.
|
||||
# Possible values: Center, Random. Default: Center
|
||||
cropType="Random"
|
||||
# Horizontal random flip, will be enabled by default if cropType=Random
|
||||
#hflip="true"
|
||||
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
|
||||
cropRatio=0.46666:0.875
|
||||
# Crop scale ratio jitter type.
|
||||
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
|
||||
jitterType="UniRatio"
|
||||
# Interpolation to use when scaling image to width x height size.
|
||||
# Possible values: nearest, linear, cubic, lanczos. Default: linear.
|
||||
interpolations="cubic"
|
||||
# Aspect ratio jitter radius. Default is 0 (disabled).
|
||||
aspectRatioRadius=0:0.2
|
||||
# Brightness, contrast and color jittering. Default is 0 (disabled).
|
||||
# Using 0 in the first epoch so the network can process original images.
|
||||
brightnessRadius=0:0.2
|
||||
contrastRadius=0:0.2
|
||||
saturationRadius=0:0.4
|
||||
# Intensity jittering: enabled if file is specified and intensityStdDev > 0.
|
||||
# The file stores 1x3 vector (eigenvalues) and 3x3 matrix (eigenvectors) in OpenCV XML format.
|
||||
intensityFile="$ConfigDir$/ImageNet1K_intensity.xml"
|
||||
# StdDev for intensity jittering. Start from the second epoch.
|
||||
intensityStdDev=0:0.1
|
||||
# Mean subtraction: enabled if file is specified.
|
||||
# The file stores mean values for each pixel in OpenCV matrix XML format.
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
CreateEval=[
|
||||
action="edit"
|
||||
CurModel="$ModelDir$/ResNet_152"
|
||||
NewModel="$ModelDir$/ResNet_152.Eval"
|
||||
editPath="$ConfigDir$/CreateEvalModel.mel"
|
||||
]
|
||||
|
||||
Test=[
|
||||
action="test"
|
||||
modelPath="$ModelDir$/ResNet_152.Eval"
|
||||
# Set minibatch size for testing.
|
||||
minibatchSize=32
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
file="$DataDir$/val_map.txt"
|
||||
randomize="None"
|
||||
features=[
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
cropType="Center"
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
|
@ -1,72 +0,0 @@
|
|||
load=ndlMacros
|
||||
run=DNN
|
||||
|
||||
ndlMacros = [
|
||||
ImageW = 224
|
||||
ImageH = 224
|
||||
ImageC = 3
|
||||
LabelDim = 1000
|
||||
|
||||
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
|
||||
labels = Input(LabelDim, tag = label)
|
||||
|
||||
# Kernels width and height.
|
||||
kW = 3
|
||||
kH = 3
|
||||
# Kernel stride.
|
||||
hs = 1
|
||||
vs = 1
|
||||
|
||||
# Initial parameter values.
|
||||
convWScale = 7.07
|
||||
convBValue = 0
|
||||
|
||||
fcWScale = 1.13
|
||||
fcBValue = 0
|
||||
|
||||
scValue = 1
|
||||
|
||||
# Batch normalization time constant.
|
||||
bnTimeConst = 32768
|
||||
]
|
||||
|
||||
DNN=[
|
||||
conv1WScale = 0.6
|
||||
cMap1 = 64
|
||||
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
|
||||
# Max pooling
|
||||
pool1W = 3
|
||||
pool1H = 3
|
||||
pool1hs = 2
|
||||
pool1vs = 2
|
||||
pool1 = MaxNDPooling(conv1, pool1W, pool1H, pool1hs, pool1vs)
|
||||
|
||||
rn1_1 = ResNetNode2A(pool1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn1_2 = ResNetNode2A(rn1_1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
cMap2 = 128
|
||||
rn2_1 = ResNetNode2BInc(rn1_2, cMap2, cMap1, 576, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
|
||||
rn2_2 = ResNetNode2A(rn2_1, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
cMap3 = 256
|
||||
rn3_1 = ResNetNode2BInc(rn2_2, cMap3, cMap2, 1152, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
|
||||
rn3_2 = ResNetNode2A(rn3_1, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
cMap4 = 512
|
||||
rn4_1 = ResNetNode2BInc(rn3_2, cMap4, cMap3, 2304, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
|
||||
rn4_2 = ResNetNode2A(rn4_1, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn4_3 = ResNetNode2A(rn4_2, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
# Global average pooling
|
||||
pool2W = 7
|
||||
pool2H = 7
|
||||
pool2hs = 1
|
||||
pool2vs = 1
|
||||
pool5 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
|
||||
|
||||
ol = DnnLayer(cMap4, labelDim, pool5, fcWScale, fcBValue)
|
||||
|
||||
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
|
||||
Err = ClassificationError(labels, ol, tag = Eval)
|
||||
OutputNodes = ol
|
||||
]
|
|
@ -1,136 +0,0 @@
|
|||
# Note: This sample uses the deprecated NdlNetworkBuilder.
|
||||
# An updated version using BrainScript is coming soon.
|
||||
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
|
||||
#
|
||||
RootDir = "."
|
||||
|
||||
ConfigDir = "$RootDir$"
|
||||
DataDir = "$RootDir$"
|
||||
OutputDir = "$RootDir$/Output"
|
||||
ModelDir = "$OutputDir$/Models"
|
||||
|
||||
ndlMacros="$ConfigDir$/Macros.ndl"
|
||||
|
||||
precision="float"
|
||||
deviceId="Auto"
|
||||
|
||||
command=Train:CreateEval:Test
|
||||
|
||||
parallelTrain="false"
|
||||
|
||||
stderr="$OutputDir$/ResNet_18"
|
||||
traceLevel=1
|
||||
numMBsToShowResult=500
|
||||
|
||||
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
|
||||
stride1x1=1
|
||||
stride3x3=2
|
||||
|
||||
Train=[
|
||||
action="train"
|
||||
modelPath="$ModelDir$/ResNet_18"
|
||||
|
||||
NDLNetworkBuilder=[
|
||||
networkDescription="$ConfigDir$/ResNet_18.ndl"
|
||||
]
|
||||
|
||||
SGD=[
|
||||
epochSize=0
|
||||
minibatchSize=256
|
||||
# Note that learning rates are 10x more than in the paper due to a different
|
||||
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
|
||||
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
|
||||
momentumPerMB=0.9
|
||||
maxEpochs=125
|
||||
gradUpdateType="None"
|
||||
L2RegWeight=0.0001
|
||||
dropoutRate=0
|
||||
|
||||
ParallelTrain=[
|
||||
parallelizationMethod="DataParallelSGD"
|
||||
distributedMBReading="true"
|
||||
parallelizationStartEpoch=1
|
||||
DataParallelSGD=[
|
||||
gradientBits=32
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
# Map file which maps images to labels using the following format:
|
||||
# <full path to image><tab><numerical label (0-based class id)>
|
||||
# Example:
|
||||
# C:\Data\ImageNet\2012\train\n01440764\n01440764_10026.JPEG<tab>0
|
||||
file="$DataDir$/train_map.txt"
|
||||
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
|
||||
randomize="Auto"
|
||||
features=[
|
||||
# Below are the required parameters.
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
# Below are the optional parameters.
|
||||
# Possible values: Center, Random, MultiView10. Default: Center
|
||||
cropType="Random"
|
||||
# Horizontal random flip, will be enabled by default if cropType=Random
|
||||
#hflip="true"
|
||||
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
|
||||
cropRatio=0.46666:0.875
|
||||
# Crop scale ratio jitter type.
|
||||
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
|
||||
jitterType="UniRatio"
|
||||
# Interpolation to use when scaling image to width x height size.
|
||||
# Possible values: nearest, linear, cubic, lanczos. Default: linear.
|
||||
interpolations="cubic"
|
||||
# Aspect ratio jitter radius. Default is 0 (disabled).
|
||||
aspectRatioRadius=0:0.2
|
||||
# Brightness, contrast and color jittering. Default is 0 (disabled).
|
||||
# Using 0 in the first epoch so the network can process original images.
|
||||
brightnessRadius=0:0.2
|
||||
contrastRadius=0:0.2
|
||||
saturationRadius=0:0.4
|
||||
# Intensity jittering: enabled if file is specified and intensityStdDev > 0.
|
||||
# The file stores 1x3 vector (eigenvalues) and 3x3 matrix (eigenvectors) in OpenCV XML format.
|
||||
intensityFile="$ConfigDir$/ImageNet1K_intensity.xml"
|
||||
# StdDev for intensity jittering. Start from the second epoch.
|
||||
intensityStdDev=0:0.1
|
||||
# Mean subtraction: enabled if file is specified.
|
||||
# The file stores mean values for each pixel in OpenCV matrix XML format.
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
CreateEval=[
|
||||
action="edit"
|
||||
CurModel="$ModelDir$/ResNet_18"
|
||||
NewModel="$ModelDir$/ResNet_18.Eval"
|
||||
editPath="$ConfigDir$/CreateEvalModel.mel"
|
||||
]
|
||||
|
||||
Test=[
|
||||
action="test"
|
||||
modelPath="$ModelDir$/ResNet_18.Eval"
|
||||
# Set minibatch size for testing.
|
||||
minibatchSize=64
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
file="$DataDir$/val_map.txt"
|
||||
randomize="None"
|
||||
features=[
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
cropType="Center" # Use MultiView10 to enable 10-view testing.
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
|
@ -1,79 +0,0 @@
|
|||
load=ndlMacros
|
||||
run=DNN
|
||||
|
||||
ndlMacros = [
|
||||
ImageW = 224
|
||||
ImageH = 224
|
||||
ImageC = 3
|
||||
LabelDim = 1000
|
||||
|
||||
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
|
||||
labels = Input(LabelDim, tag = label)
|
||||
|
||||
# Kernels width and height.
|
||||
kW = 3
|
||||
kH = 3
|
||||
# Kernel stride.
|
||||
hs = 1
|
||||
vs = 1
|
||||
|
||||
# Initial parameter values.
|
||||
convWScale = 7.07
|
||||
convBValue = 0
|
||||
|
||||
fcWScale = 1.13
|
||||
fcBValue = 0
|
||||
|
||||
scValue = 1
|
||||
|
||||
# Batch normalization time constant.
|
||||
bnTimeConst = 4096
|
||||
]
|
||||
|
||||
DNN=[
|
||||
conv1WScale = 0.6
|
||||
cMap1 = 64
|
||||
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
|
||||
# Max pooling
|
||||
pool1W = 3
|
||||
pool1H = 3
|
||||
pool1hs = 2
|
||||
pool1vs = 2
|
||||
pool1 = MaxNDPooling(conv1, pool1W, pool1H, pool1hs, pool1vs)
|
||||
|
||||
rn1_1 = ResNetNode2A(pool1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn1_2 = ResNetNode2A(rn1_1, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn1_3 = ResNetNode2A(rn1_2, cMap1, 576, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
cMap2 = 128
|
||||
rn2_1 = ResNetNode2BInc(rn1_3, cMap2, cMap1, 576, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
|
||||
rn2_2 = ResNetNode2A(rn2_1, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_3 = ResNetNode2A(rn2_2, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_4 = ResNetNode2A(rn2_3, cMap2, 1152, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
cMap3 = 256
|
||||
rn3_1 = ResNetNode2BInc(rn2_4, cMap3, cMap2, 1152, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
|
||||
rn3_2 = ResNetNode2A(rn3_1, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_3 = ResNetNode2A(rn3_2, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_4 = ResNetNode2A(rn3_3, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_5 = ResNetNode2A(rn3_4, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_6 = ResNetNode2A(rn3_5, cMap3, 2304, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
cMap4 = 512
|
||||
rn4_1 = ResNetNode2BInc(rn3_6, cMap4, cMap3, 2304, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst, $stride1x1$, $stride3x3$)
|
||||
rn4_2 = ResNetNode2A(rn4_1, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn4_3 = ResNetNode2A(rn4_2, cMap4, 4608, kW, kH, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
# Global average pooling
|
||||
pool2W = 7
|
||||
pool2H = 7
|
||||
pool2hs = 1
|
||||
pool2vs = 1
|
||||
pool5 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
|
||||
|
||||
ol = DnnLayer(cMap4, labelDim, pool5, fcWScale, fcBValue)
|
||||
|
||||
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
|
||||
Err = ClassificationError(labels, ol, tag = Eval)
|
||||
OutputNodes = ol
|
||||
]
|
|
@ -1,136 +0,0 @@
|
|||
# Note: This sample uses the deprecated NdlNetworkBuilder.
|
||||
# An updated version using BrainScript is coming soon.
|
||||
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
|
||||
#
|
||||
RootDir = "."
|
||||
|
||||
ConfigDir = "$RootDir$"
|
||||
DataDir = "$RootDir$"
|
||||
OutputDir = "$RootDir$/Output"
|
||||
ModelDir = "$OutputDir$/Models"
|
||||
|
||||
ndlMacros="$ConfigDir$/Macros.ndl"
|
||||
|
||||
precision="float"
|
||||
deviceId="Auto"
|
||||
|
||||
command=Train:CreateEval:Test
|
||||
|
||||
parallelTrain="false"
|
||||
|
||||
stderr="$OutputDir$/ResNet_34"
|
||||
traceLevel=1
|
||||
numMBsToShowResult=500
|
||||
|
||||
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
|
||||
stride1x1=1
|
||||
stride3x3=2
|
||||
|
||||
Train=[
|
||||
action="train"
|
||||
modelPath="$ModelDir$/ResNet_34"
|
||||
|
||||
NDLNetworkBuilder=[
|
||||
networkDescription="$ConfigDir$/ResNet_34.ndl"
|
||||
]
|
||||
|
||||
SGD=[
|
||||
epochSize=0
|
||||
minibatchSize=256
|
||||
# Note that learning rates are 10x more than in the paper due to a different
|
||||
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
|
||||
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
|
||||
momentumPerMB=0.9
|
||||
maxEpochs=125
|
||||
gradUpdateType="None"
|
||||
L2RegWeight=0.0001
|
||||
dropoutRate=0
|
||||
|
||||
ParallelTrain=[
|
||||
parallelizationMethod="DataParallelSGD"
|
||||
distributedMBReading="true"
|
||||
parallelizationStartEpoch=1
|
||||
DataParallelSGD=[
|
||||
gradientBits=32
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
# Map file which maps images to labels using the following format:
|
||||
# <full path to image><tab><numerical label (0-based class id)>
|
||||
# Example:
|
||||
# C:\Data\ImageNet\2012\train\n01440764\n01440764_10026.JPEG<tab>0
|
||||
file="$DataDir$/train_map.txt"
|
||||
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
|
||||
randomize="Auto"
|
||||
features=[
|
||||
# Below are the required parameters.
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
# Below are the optional parameters.
|
||||
# Possible values: Center, Random, MultiView10. Default: Center
|
||||
cropType="Random"
|
||||
# Horizontal random flip, will be enabled by default if cropType=Random
|
||||
#hflip="true"
|
||||
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
|
||||
cropRatio=0.46666:0.875
|
||||
# Crop scale ratio jitter type.
|
||||
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
|
||||
jitterType="UniRatio"
|
||||
# Interpolation to use when scaling image to width x height size.
|
||||
# Possible values: nearest, linear, cubic, lanczos. Default: linear.
|
||||
interpolations="cubic"
|
||||
# Aspect ratio jitter radius. Default is 0 (disabled).
|
||||
aspectRatioRadius=0:0.2
|
||||
# Brightness, contrast and color jittering. Default is 0 (disabled).
|
||||
# Using 0 in the first epoch so the network can process original images.
|
||||
brightnessRadius=0:0.2
|
||||
contrastRadius=0:0.2
|
||||
saturationRadius=0:0.4
|
||||
# Intensity jittering: enabled if file is specified and intensityStdDev > 0.
|
||||
# The file stores 1x3 vector (eigenvalues) and 3x3 matrix (eigenvectors) in OpenCV XML format.
|
||||
intensityFile="$ConfigDir$/ImageNet1K_intensity.xml"
|
||||
# StdDev for intensity jittering. Start from the second epoch.
|
||||
intensityStdDev=0:0.1
|
||||
# Mean subtraction: enabled if file is specified.
|
||||
# The file stores mean values for each pixel in OpenCV matrix XML format.
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
CreateEval=[
|
||||
action="edit"
|
||||
CurModel="$ModelDir$/ResNet_34"
|
||||
NewModel="$ModelDir$/ResNet_34.Eval"
|
||||
editPath="$ConfigDir$/CreateEvalModel.mel"
|
||||
]
|
||||
|
||||
Test=[
|
||||
action="test"
|
||||
modelPath="$ModelDir$/ResNet_34.Eval"
|
||||
# Set minibatch size for testing.
|
||||
minibatchSize=64
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
file="$DataDir$/val_map.txt"
|
||||
randomize="None"
|
||||
features=[
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
cropType="Center" # Use MultiView10 to enable 10-view testing.
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
|
@ -1,82 +0,0 @@
|
|||
load=ndlMacros
|
||||
run=DNN
|
||||
|
||||
ndlMacros = [
|
||||
ImageW = 224
|
||||
ImageH = 224
|
||||
ImageC = 3
|
||||
LabelDim = 1000
|
||||
|
||||
features = ImageInput(ImageW, ImageH, ImageC, tag = feature, imageLayout = "cudnn")
|
||||
labels = Input(LabelDim, tag = label)
|
||||
|
||||
# Kernels width and height.
|
||||
kW = 3
|
||||
kH = 3
|
||||
# Kernel stride.
|
||||
hs = 1
|
||||
vs = 1
|
||||
|
||||
# Initial parameter values.
|
||||
convWScale = 7.07
|
||||
convBValue = 0
|
||||
|
||||
fcWScale = 2.26
|
||||
fcBValue = 0
|
||||
|
||||
scValue = 1
|
||||
|
||||
# Batch normalization time constant.
|
||||
bnTimeConst = 0
|
||||
]
|
||||
|
||||
DNN=[
|
||||
cMap1 = 64
|
||||
cMap2 = 128
|
||||
cMap3 = 256
|
||||
cMap4 = 512
|
||||
cMap5 = 1024
|
||||
cMap6 = 2048
|
||||
|
||||
conv1WScale = 0.6
|
||||
conv1 = ConvBNReLULayer(features, cMap1, 147, 7, 7, 2, 2, conv1WScale, convBValue, scValue, bnTimeConst)
|
||||
# Max pooling
|
||||
pool1W = 3
|
||||
pool1H = 3
|
||||
pool1hs = 2
|
||||
pool1vs = 2
|
||||
pool1 = MaxNDPooling(conv1, pool1W, pool1H, pool1hs, pool1vs)
|
||||
|
||||
rn1_1 = ResNetNode3BInc(pool1, cMap1, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst, 1, 1, 1)
|
||||
rn1_2 = ResNetNode3A(rn1_1, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn1_3 = ResNetNode3A(rn1_2, cMap3, cMap1, cMap3, 576, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
rn2_1 = ResNetNode3BInc(rn1_3, cMap3, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
|
||||
rn2_2 = ResNetNode3A(rn2_1, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_3 = ResNetNode3A(rn2_2, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn2_4 = ResNetNode3A(rn2_3, cMap4, cMap2, cMap4, 1152, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
rn3_1 = ResNetNode3BInc(rn2_4, cMap4, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
|
||||
rn3_2 = ResNetNode3A(rn3_1, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_3 = ResNetNode3A(rn3_2, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_4 = ResNetNode3A(rn3_3, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_5 = ResNetNode3A(rn3_4, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn3_6 = ResNetNode3A(rn3_5, cMap5, cMap3, cMap5, 2304, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
rn4_1 = ResNetNode3BInc(rn3_6, cMap5, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst, 2, $stride1x1$, $stride3x3$)
|
||||
rn4_2 = ResNetNode3A(rn4_1, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
|
||||
rn4_3 = ResNetNode3A(rn4_2, cMap6, cMap4, cMap6, 4608, convWScale, convBValue, scValue, bnTimeConst)
|
||||
|
||||
# Global average pooling
|
||||
pool2W = 7
|
||||
pool2H = 7
|
||||
pool2hs = 1
|
||||
pool2vs = 1
|
||||
pool2 = AveragePooling(rn4_3, pool2W, pool2H, pool2hs, pool2vs, imageLayout = "cudnn")
|
||||
|
||||
ol = DnnLayer(cMap6, labelDim, pool2, fcWScale, fcBValue)
|
||||
|
||||
CE = CrossEntropyWithSoftmax(labels, ol, tag = Criteria)
|
||||
Err = ClassificationError(labels, ol, tag = Eval)
|
||||
OutputNodes = ol
|
||||
]
|
|
@ -1,155 +0,0 @@
|
|||
# Note: This sample uses the deprecated NdlNetworkBuilder.
|
||||
# An updated version using BrainScript is coming soon.
|
||||
# Please find updated samples on Github, https://github.com/Microsoft/CNTK/tree/master/Examples /...
|
||||
#
|
||||
RootDir = "."
|
||||
|
||||
ConfigDir = "$RootDir$"
|
||||
DataDir = "$RootDir$"
|
||||
OutputDir = "$RootDir$/Output"
|
||||
ModelDir = "$OutputDir$/Models"
|
||||
|
||||
ndlMacros="$ConfigDir$/Macros.ndl"
|
||||
|
||||
precision="float"
|
||||
deviceId="Auto"
|
||||
|
||||
command=Train:PBN:CreateEval:Test
|
||||
|
||||
parallelTrain="false"
|
||||
|
||||
stderr="$OutputDir$/ResNet_50"
|
||||
traceLevel=1
|
||||
numMBsToShowResult=500
|
||||
|
||||
# Strides for increasing layers. Defaults (paper) are 2 for 1x1 and 1 for 3x3.
|
||||
stride1x1=2
|
||||
stride3x3=1
|
||||
|
||||
Train=[
|
||||
action="train"
|
||||
modelPath="$ModelDir$/ResNet_50"
|
||||
|
||||
NDLNetworkBuilder=[
|
||||
networkDescription="$ConfigDir$/ResNet_50.ndl"
|
||||
]
|
||||
|
||||
SGD=[
|
||||
epochSize=0
|
||||
minibatchSize=256
|
||||
# Note that learning rates are 10x more than in the paper due to a different
|
||||
# momentum update rule in CNTK: v{t + 1} = lr*(1 - momentum)*g{t + 1} + momentum*v{t}
|
||||
learningRatesPerMB=1.0*30:0.1*30:0.01*30:0.001
|
||||
momentumPerMB=0.9
|
||||
maxEpochs=125
|
||||
gradUpdateType="None"
|
||||
L2RegWeight=0.0001
|
||||
dropoutRate=0
|
||||
|
||||
disableWkInBatchNormal=true
|
||||
|
||||
ParallelTrain=[
|
||||
parallelizationMethod="DataParallelSGD"
|
||||
distributedMBReading="true"
|
||||
parallelizationStartEpoch=1
|
||||
DataParallelSGD=[
|
||||
gradientBits=32
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
file="$DataDir$/train_map.txt"
|
||||
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
|
||||
randomize="Auto"
|
||||
features=[
|
||||
# Below are the required parameters.
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
# Below are the optional parameters.
|
||||
# Possible values: Center, Random. Default: Center
|
||||
cropType="Random"
|
||||
# Horizontal random flip, will be enabled by default if cropType=Random
|
||||
hflip="true"
|
||||
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
|
||||
cropRatio=0.46666:0.875
|
||||
# Crop scale ratio jitter type.
|
||||
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
|
||||
jitterType="UniRatio"
|
||||
# The file stores mean values for each pixel in OpenCV matrix XML format.
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
PBN=[
|
||||
action="pbn"
|
||||
modelPath="$ModelDir$/ResNet_50"
|
||||
# Set minibatch size for testing.
|
||||
minibatchSize=256
|
||||
iters=30
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
file="$DataDir$/train_map.txt"
|
||||
# Randomize images before every epoch. Possible values: None, Auto. Default: Auto.
|
||||
randomize="Auto"
|
||||
features=[
|
||||
# Below are the required parameters.
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
# Below are the optional parameters.
|
||||
# Possible values: Center, Random. Default: Center
|
||||
cropType="Random"
|
||||
# Horizontal random flip, will be enabled by default if cropType=Random
|
||||
hflip="true"
|
||||
# Crop scale ratio. Examples: cropRatio=0.9, cropRatio=0.7:0.9. Default: 1.
|
||||
cropRatio=0.46666:0.875
|
||||
# Crop scale ratio jitter type.
|
||||
# Possible values: None, UniRatio, UniLength, UniArea. Default: UniRatio
|
||||
jitterType="UniRatio"
|
||||
# The file stores mean values for each pixel in OpenCV matrix XML format.
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
CreateEval=[
|
||||
action="edit"
|
||||
CurModel="$ModelDir$/ResNet_50.PBN"
|
||||
NewModel="$ModelDir$/ResNet_50.Eval"
|
||||
editPath="$ConfigDir$/CreateEvalModel.mel"
|
||||
]
|
||||
|
||||
Test=[
|
||||
action="test"
|
||||
modelPath="$ModelDir$/ResNet_50.Eval"
|
||||
# Set minibatch size for testing.
|
||||
minibatchSize=200
|
||||
|
||||
reader=[
|
||||
readerType="ImageReader"
|
||||
file="$DataDir$/val_map.txt"
|
||||
randomize="None"
|
||||
features=[
|
||||
width=224
|
||||
height=224
|
||||
channels=3
|
||||
cropType="Center"
|
||||
cropRatio=0.875
|
||||
meanFile="$ConfigDir$/ImageNet1K_mean.xml"
|
||||
]
|
||||
labels=[
|
||||
labelDim=1000
|
||||
]
|
||||
]
|
||||
]
|
|
@ -0,0 +1,42 @@
|
|||
# Pascal VOC Dataset
|
||||
|
||||
The [Pascal VOC](http://host.robots.ox.ac.uk/pascal/VOC/) (PASCAL Visual Object Classes) data
|
||||
is a well known set of standardised images for object class recognition.
|
||||
|
||||
## Getting the Pascal VOC data
|
||||
|
||||
The Pascal VOC dataset is not included in the CNTK distribution but can be easily
|
||||
downloaded by running the following Python command:
|
||||
|
||||
`python install_pascalvoc.py`
|
||||
|
||||
This will download roughly 3.15GB of data and unpack it into the folder structure that is assumed in the [object recognition tutorial](https://github.com/Microsoft/CNTK/wiki/Object-Detection-using-Fast-R-CNN#run-pascal-voc)
|
||||
|
||||
## Alternative: download data manually
|
||||
|
||||
You need the 2007 (trainval and test) and 2012 (trainval) data as well as the precomputed ROIs used in the original Fast R-CNN paper.
|
||||
For the object recognition tutorial you need to follow the folder structure described below.
|
||||
|
||||
* Download and unpack the 2012 trainval data to `DataSets/Pascal/VOCdevkit`
|
||||
* Website: [http://host.robots.ox.ac.uk/pascal/VOC/voc2012/](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/)
|
||||
* Devkit: [http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar)
|
||||
* Download and unpack the 2007 trainval data to `DataSets/Pascal/VOCdevkit`
|
||||
* Website: [http://host.robots.ox.ac.uk/pascal/VOC/voc2007/](http://host.robots.ox.ac.uk/pascal/VOC/voc2007/)
|
||||
* Devkit: [http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar](http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar)
|
||||
* Download and unpack the 2007 test data into the same folder `DataSets/Pascal/VOCdevkit`
|
||||
* [http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar](http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar)
|
||||
* Download and unpack the precomputed ROIs to `DataSets/Pascal/selective_search_data`
|
||||
* [http://www.cs.berkeley.edu/~rbg/fast-rcnn-data/selective_search_data.tgz](http://www.cs.berkeley.edu/~rbg/fast-rcnn-data/selective_search_data.tgz)
|
||||
|
||||
The `VOCdevkit/VOC2007` folder should contain at least the following (similar for 2012):
|
||||
```
|
||||
VOCdevkit/VOC2007
|
||||
VOCdevkit/VOC2007/Annotations
|
||||
VOCdevkit/VOC2007/ImageSets
|
||||
VOCdevkit/VOC2007/JPEGImages
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
If you are curious about how well computers can perform on Pascal VOC today, the official leaderboards are maintained at
|
||||
[http://host.robots.ox.ac.uk:8080/leaderboard/main_bootstrap.php](http://host.robots.ox.ac.uk:8080/leaderboard/main_bootstrap.php)
|
|
@ -0,0 +1,63 @@
|
|||
from __future__ import print_function
|
||||
import os
|
||||
import os.path
|
||||
import tarfile
|
||||
import zipfile
|
||||
try:
|
||||
from urllib.request import urlretrieve
|
||||
except ImportError:
|
||||
from urllib import urlretrieve
|
||||
|
||||
def download_and_untar(url, filename, filesize):
|
||||
if not os.path.exists(filename):
|
||||
print ('Downloading ' + filesize + ' from ' + url + ', may take a while...')
|
||||
try:
|
||||
urlretrieve(url, filename)
|
||||
except (urllib.ContentTooShortError, IOError) as e:
|
||||
print ("Error downloading file: " + str(e))
|
||||
os.remove(filename)
|
||||
quit()
|
||||
else:
|
||||
print ('Found ' + filename)
|
||||
try:
|
||||
print ('Extracting ' + filename + '...')
|
||||
with tarfile.open(filename) as tar:
|
||||
tar.extractall()
|
||||
print ('Done.')
|
||||
finally:
|
||||
os.remove(filename)
|
||||
return;
|
||||
|
||||
if __name__ == "__main__":
|
||||
directory = "./VOCdevkit/VOC2007"
|
||||
if not os.path.exists(directory):
|
||||
download_and_untar(
|
||||
"http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar",
|
||||
"./VOCtrainval_06-Nov-2007.tar",
|
||||
"450MB")
|
||||
download_and_untar(
|
||||
"http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar",
|
||||
"./VOCtest_06-Nov-2007.tar",
|
||||
"430MB")
|
||||
else:
|
||||
print (directory + ' data already available.')
|
||||
|
||||
directory = "./VOCdevkit/VOC2012"
|
||||
if not os.path.exists(directory):
|
||||
download_and_untar(
|
||||
"http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar",
|
||||
"./VOCtrainval_11-May-2012.tar",
|
||||
"2GB")
|
||||
else:
|
||||
print (directory + ' data already available.')
|
||||
|
||||
directory = "./selective_search_data"
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
download_and_untar(
|
||||
"http://www.cs.berkeley.edu/~rbg/fast-rcnn-data/selective_search_data.tgz",
|
||||
"./selective_search_data.tgz",
|
||||
"460MB")
|
||||
else:
|
||||
print (directory + ' data already available.')
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
from __future__ import print_function
|
||||
from builtins import input
|
||||
import os, sys, importlib
|
||||
import shutil, time
|
||||
import PARAMETERS
|
||||
locals().update(importlib.import_module("PARAMETERS").__dict__)
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
boSaveDebugImg = True
|
||||
subDirs = ['positive', 'testImages', 'negative']
|
||||
image_sets = ["train", "test"]
|
||||
|
||||
# no need to change these parameters
|
||||
boAddSelectiveSearchROIs = True
|
||||
boAddRoisOnGrid = True
|
||||
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
# generate ROIs using selective search and grid (for pascal we use the precomputed ROIs from Ross)
|
||||
if not datasetName.startswith("pascalVoc"):
|
||||
# init
|
||||
makeDirectory(roiDir)
|
||||
roi_minDim = roi_minDimRel * roi_maxImgDim
|
||||
roi_maxDim = roi_maxDimRel * roi_maxImgDim
|
||||
roi_minNrPixels = roi_minNrPixelsRel * roi_maxImgDim*roi_maxImgDim
|
||||
roi_maxNrPixels = roi_maxNrPixelsRel * roi_maxImgDim*roi_maxImgDim
|
||||
|
||||
for subdir in subDirs:
|
||||
makeDirectory(roiDir + subdir)
|
||||
imgFilenames = getFilesInDirectory(imgDir + subdir, ".jpg")
|
||||
|
||||
# loop over all images
|
||||
for imgIndex,imgFilename in enumerate(imgFilenames):
|
||||
roiPath = "{}/{}/{}.roi.txt".format(roiDir, subdir, imgFilename[:-4])
|
||||
|
||||
# load image
|
||||
print (imgIndex, len(imgFilenames), subdir, imgFilename)
|
||||
tstart = datetime.datetime.now()
|
||||
imgPath = imgDir + subdir + "/" + imgFilename
|
||||
imgOrig = imread(imgPath)
|
||||
if imWidth(imgPath) > imHeight(imgPath):
|
||||
print (imWidth(imgPath) , imHeight(imgPath))
|
||||
|
||||
# get rois
|
||||
if boAddSelectiveSearchROIs:
|
||||
print ("Calling selective search..")
|
||||
rects, img, scale = getSelectiveSearchRois(imgOrig, ss_scale, ss_sigma, ss_minSize, roi_maxImgDim) #interpolation=cv2.INTER_AREA
|
||||
print (" Number of rois detected using selective search: " + str(len(rects)))
|
||||
else:
|
||||
rects = []
|
||||
img, scale = imresizeMaxDim(imgOrig, roi_maxImgDim, boUpscale=True, interpolation=cv2.INTER_AREA)
|
||||
imgWidth, imgHeight = imArrayWidthHeight(img)
|
||||
|
||||
# add grid rois
|
||||
if boAddRoisOnGrid:
|
||||
rectsGrid = getGridRois(imgWidth, imgHeight, grid_nrScales, grid_aspectRatios)
|
||||
print (" Number of rois on grid added: " + str(len(rectsGrid)))
|
||||
rects += rectsGrid
|
||||
|
||||
# run filter
|
||||
print (" Number of rectangles before filtering = " + str(len(rects)))
|
||||
rois = filterRois(rects, imgWidth, imgHeight, roi_minNrPixels, roi_maxNrPixels, roi_minDim, roi_maxDim, roi_maxAspectRatio)
|
||||
if len(rois) == 0: #make sure at least one roi returned per image
|
||||
rois = [[5, 5, imgWidth-5, imgHeight-5]]
|
||||
print (" Number of rectangles after filtering = " + str(len(rois)))
|
||||
|
||||
# scale up to original size and save to disk
|
||||
# note: each rectangle is in original image format with [x,y,x2,y2]
|
||||
rois = np.int32(np.array(rois) / scale)
|
||||
assert (np.min(rois) >= 0)
|
||||
assert (np.max(rois[:, [0,2]]) < imArrayWidth(imgOrig))
|
||||
assert (np.max(rois[:, [1,3]]) < imArrayHeight(imgOrig))
|
||||
np.savetxt(roiPath, rois, fmt='%d')
|
||||
print (" Time [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000))
|
||||
|
||||
# clear imdb cache and other files
|
||||
if os.path.exists(cntkFilesDir):
|
||||
assert(cntkFilesDir.endswith("cntkFiles/"))
|
||||
userInput = input('--> INPUT: Press "y" to delete directory ' + cntkFilesDir + ": ")
|
||||
if userInput.lower() not in ['y', 'yes']:
|
||||
print ("User input is %s: exiting now." % userInput)
|
||||
exit(-1)
|
||||
shutil.rmtree(cntkFilesDir)
|
||||
time.sleep(0.1) # avoid access problems
|
||||
|
||||
# create cntk representation for each image
|
||||
for image_set in image_sets:
|
||||
imdb = imdbs[image_set]
|
||||
print ("Number of images in set {} = {}".format(image_set, imdb.num_images))
|
||||
makeDirectory(cntkFilesDir)
|
||||
|
||||
# open files for writing
|
||||
cntkImgsPath, cntkRoiCoordsPath, cntkRoiLabelsPath, nrRoisPath = getCntkInputPaths(cntkFilesDir, image_set)
|
||||
with open(nrRoisPath, 'w') as nrRoisFile, \
|
||||
open(cntkImgsPath, 'w') as cntkImgsFile, \
|
||||
open(cntkRoiCoordsPath, 'w') as cntkRoiCoordsFile, \
|
||||
open(cntkRoiLabelsPath, 'w') as cntkRoiLabelsFile:
|
||||
|
||||
# for each image, transform rois etc to cntk format
|
||||
for imgIndex in range(0, imdb.num_images):
|
||||
if imgIndex % 50 == 0:
|
||||
print ("Processing image set '{}', image {} of {}".format(image_set, imgIndex, imdb.num_images))
|
||||
currBoxes = imdb.roidb[imgIndex]['boxes']
|
||||
currGtOverlaps = imdb.roidb[imgIndex]['gt_overlaps']
|
||||
imgPath = imdb.image_path_at(imgIndex)
|
||||
imgWidth, imgHeight = imWidthHeight(imgPath)
|
||||
|
||||
# all rois need to be scaled + padded to cntk input image size
|
||||
targetw, targeth, w_offset, h_offset, scale = roiTransformPadScaleParams(imgWidth, imgHeight,
|
||||
cntk_padWidth, cntk_padHeight)
|
||||
boxesStr = ""
|
||||
labelsStr = ""
|
||||
nrBoxes = len(currBoxes)
|
||||
for boxIndex, box in enumerate(currBoxes):
|
||||
rect = roiTransformPadScale(box, w_offset, h_offset, scale)
|
||||
boxesStr += getCntkRoiCoordsLine(rect, cntk_padWidth, cntk_padHeight)
|
||||
labelsStr += getCntkRoiLabelsLine(currGtOverlaps[boxIndex, :].toarray()[0],
|
||||
train_posOverlapThres,
|
||||
nrClasses)
|
||||
|
||||
# if less than e.g. 2000 rois per image, then fill in the rest using 'zero-padding'.
|
||||
boxesStr, labelsStr = cntkPadInputs(nrBoxes, cntk_nrRois, nrClasses, boxesStr, labelsStr)
|
||||
|
||||
# update cntk data
|
||||
nrRoisFile.write("{}\n".format(nrBoxes))
|
||||
cntkImgsFile.write("{}\t{}\t0\n".format(imgIndex, imgPath))
|
||||
cntkRoiCoordsFile.write("{} |rois{}\n".format(imgIndex, boxesStr))
|
||||
cntkRoiLabelsFile.write("{} |roiLabels{}\n".format(imgIndex, labelsStr))
|
||||
|
||||
print ("DONE.")
|
|
@ -0,0 +1,53 @@
|
|||
from __future__ import print_function
|
||||
import os, sys, importlib
|
||||
import shutil, time
|
||||
import subprocess
|
||||
import PARAMETERS
|
||||
locals().update(importlib.import_module("PARAMETERS").__dict__)
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
cntkCmdStrPattern = "cntk.exe configFile={0}fastrcnn.cntk currentDirectory={0} {1}"
|
||||
|
||||
# cntk arguments
|
||||
NumLabels = nrClasses
|
||||
|
||||
NumTrainROIs = cntk_nrRois
|
||||
TrainROIDim = cntk_nrRois * 4
|
||||
TrainROILabelDim = cntk_nrRois * nrClasses
|
||||
|
||||
NumTestROIs = cntk_nrRois
|
||||
TestROIDim = cntk_nrRois * 4
|
||||
TestROILabelDim = cntk_nrRois * nrClasses
|
||||
|
||||
cntk_args = "NumLabels={} NumTrainROIs={}".format(NumLabels, NumTrainROIs)
|
||||
cntk_args += " TrainROIDim={} TrainROILabelDim={}".format(TrainROIDim, TrainROILabelDim)
|
||||
cntk_args += " NumTestROIs={}".format(NumTestROIs)
|
||||
cntk_args += " TestROIDim={} TestROILabelDim={}".format(TestROIDim, TestROILabelDim)
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
# copy config file
|
||||
shutil.copy(cntkTemplateDir + "fastrcnn.cntk", cntkFilesDir)
|
||||
|
||||
# run cntk
|
||||
tstart = datetime.datetime.now()
|
||||
os.environ['ACML_FMA'] = str(0)
|
||||
cmdStr = cntkCmdStrPattern.format(cntkFilesDir, cntk_args)
|
||||
print (cmdStr)
|
||||
pid = subprocess.Popen(cmdStr, cwd = cntkFilesDir)
|
||||
pid.wait()
|
||||
print ("Time running cntk [s]: " + str((datetime.datetime.now() - tstart).total_seconds()))
|
||||
|
||||
# delete intermediate model files written during cntk training
|
||||
modelDir = cntkFilesDir + "Output/"
|
||||
filenames = getFilesInDirectory(modelDir, postfix = None)
|
||||
for filename in filenames:
|
||||
if filename.contains('Fast-RCNN.model.'):
|
||||
os.remove(modelDir + filename)
|
||||
assert pid.returncode == 0, "ERROR: cntk ended with exit code {}".format(pid.returncode)
|
||||
|
||||
print ("DONE.")
|
|
@ -0,0 +1,55 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
"""Test a Fast R-CNN network on an image database."""
|
||||
from __future__ import print_function
|
||||
import importlib
|
||||
from fastRCNN.test import test_net
|
||||
from fastRCNN.timer import Timer
|
||||
import PARAMETERS
|
||||
locals().update(importlib.import_module("PARAMETERS").__dict__)
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
image_set = 'test' # 'train', 'test'
|
||||
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
# parse cntk output
|
||||
print ("Parsing CNTK output for image set: " + image_set)
|
||||
cntkImgsListPath = cntkFilesDir + image_set + ".txt"
|
||||
outParsedDir = cntkFilesDir + image_set + "_parsed/"
|
||||
cntkOutputPath = cntkFilesDir + image_set + ".z"
|
||||
|
||||
# write cntk output for each image to separate file
|
||||
makeDirectory(outParsedDir)
|
||||
parseCntkOutput(cntkImgsListPath, cntkOutputPath, outParsedDir, cntk_nrRois, cntk_featureDimensions[classifier],
|
||||
saveCompressed = True, skipCheck = True)
|
||||
|
||||
# delete cntk output file which can be very large
|
||||
# deleteFile(cntkOutputPath)
|
||||
|
||||
imdb = imdbs[image_set]
|
||||
net = DummyNet(4096, imdb.num_classes, outParsedDir)
|
||||
|
||||
# create empty directory for evaluation files
|
||||
if type(imdb) == imdb_data:
|
||||
evalTempDir = None
|
||||
else:
|
||||
# pascal_voc implementation requires temporary directory for evaluation
|
||||
evalTempDir = os.path.join(procDir, "eval_mAP_" + image_set)
|
||||
makeDirectory(evalTempDir)
|
||||
deleteAllFilesInDirectory(evalTempDir, None)
|
||||
|
||||
# compute mAPs
|
||||
test_net(net, imdb, evalTempDir, None, classifier, nmsThreshold, boUsePythonImpl = True)
|
||||
|
||||
print ("DONE.")
|
|
@ -0,0 +1,55 @@
|
|||
from __future__ import print_function
|
||||
import os, importlib, sys
|
||||
from cntk_helpers import *
|
||||
import PARAMETERS
|
||||
locals().update(importlib.import_module("PARAMETERS").__dict__)
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
image_set = 'train' # 'train', 'test'
|
||||
|
||||
# no need to change these parameters
|
||||
parseNrImages = 10 # for speed reasons only parse CNTK file for the first N images
|
||||
boUseNonMaximaSurpression = False
|
||||
nmsThreshold = 0.1
|
||||
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
|
||||
print ("Load ROI co-ordinates and labels")
|
||||
cntkImgsPath, cntkRoiCoordsPath, cntkRoiLabelsPath, nrRoisPath = getCntkInputPaths(cntkFilesDir, image_set)
|
||||
imgPaths = getColumn(readTable(cntkImgsPath), 1)
|
||||
nrRealRois = [int(s) for s in readFile(nrRoisPath)]
|
||||
roiAllLabels = readCntkRoiLabels(cntkRoiLabelsPath, cntk_nrRois, len(classes), parseNrImages)
|
||||
if parseNrImages:
|
||||
imgPaths = imgPaths[:parseNrImages]
|
||||
nrRealRois = nrRealRois[:parseNrImages]
|
||||
roiAllLabels = roiAllLabels[:parseNrImages]
|
||||
roiAllCoords = readCntkRoiCoordinates(imgPaths, cntkRoiCoordsPath, cntk_nrRois, cntk_padWidth, cntk_padHeight,
|
||||
parseNrImages)
|
||||
assert (len(imgPaths) == len(roiAllCoords) == len(roiAllLabels) == len(nrRealRois))
|
||||
|
||||
# loop over all images and visualize
|
||||
for imgIndex, imgPath in enumerate(imgPaths):
|
||||
print ("Visualizing image %d at %s..." % (imgIndex, imgPath))
|
||||
roiCoords = roiAllCoords[imgIndex][:nrRealRois[imgIndex]]
|
||||
roiLabels = roiAllLabels[imgIndex][:nrRealRois[imgIndex]]
|
||||
|
||||
# perform non-maxima surpression. note that the detected classes in the image is not affected by this.
|
||||
nmsKeepIndices = []
|
||||
if boUseNonMaximaSurpression:
|
||||
imgWidth, imgHeight = imWidthHeight(imgPath)
|
||||
nmsKeepIndices = applyNonMaximaSuppression(nmsThreshold, roiLabels, [0] * len(roiLabels), roiCoords)
|
||||
print ("Non-maxima surpression kept {} of {} rois (nmsThreshold={})".format(len(nmsKeepIndices),
|
||||
len(roiLabels), nmsThreshold))
|
||||
|
||||
# visualize results
|
||||
imgDebug = visualizeResults(imgPath, roiLabels, None, roiCoords, cntk_padWidth, cntk_padHeight,
|
||||
classes, nmsKeepIndices, boDrawNegativeRois=True)
|
||||
imshow(imgDebug, waitDuration=0, maxDim=800)
|
||||
|
||||
print ("DONE.")
|
|
@ -0,0 +1,53 @@
|
|||
from __future__ import print_function
|
||||
import sys, os, importlib
|
||||
import PARAMETERS
|
||||
locals().update(importlib.import_module("PARAMETERS").__dict__)
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
subdirs = ['positive', 'testImages']
|
||||
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
overlaps = []
|
||||
roiCounts = []
|
||||
for subdir in subdirs:
|
||||
imgFilenames = getFilesInDirectory(imgDir + subdir, ".jpg")
|
||||
|
||||
# loop over all iamges
|
||||
for imgIndex,imgFilename in enumerate(imgFilenames):
|
||||
if imgIndex % 20 == 0:
|
||||
print ("Processing subdir '{}', image {} of {}".format(subdir, imgIndex, len(imgFilenames)))
|
||||
# load ground truth
|
||||
imgPath = imgDir + subdir + "/" + imgFilename
|
||||
imgWidth, imgHeight = imWidthHeight(imgPath)
|
||||
gtBoxes, gtLabels = readGtAnnotation(imgPath)
|
||||
gtBoxes = [Bbox(*rect) for rect in gtBoxes]
|
||||
|
||||
# load rois and compute scale
|
||||
rois = readRois(roiDir, subdir, imgFilename)
|
||||
rois = [Bbox(*roi) for roi in rois]
|
||||
roiCounts.append(len(rois))
|
||||
|
||||
# for each ground truth, compute if it is covered by an roi
|
||||
maxOverlap = -1
|
||||
for gtIndex, (gtLabel, gtBox) in enumerate(zip(gtLabels,gtBoxes)):
|
||||
assert (gtBox.max() <= max(imgWidth, imgHeight) and gtBox.max() >= 0)
|
||||
gtLabel = gtLabel.decode('utf-8')
|
||||
if gtLabel in classes[1:]:
|
||||
for roi in rois:
|
||||
assert (roi.max() <= max(imgWidth, imgHeight) and roi.max() >= 0)
|
||||
overlap = bboxComputeOverlapVoc(gtBox, roi)
|
||||
maxOverlap = max(maxOverlap, overlap)
|
||||
overlaps.append(maxOverlap)
|
||||
print ("Average number of rois per image " + str(1.0 * sum(roiCounts) / len(overlaps)))
|
||||
|
||||
# compute recall at different overlaps
|
||||
overlaps = np.array(overlaps, np.float32)
|
||||
for overlapThreshold in np.linspace(0,1,11):
|
||||
recall = 1.0 * sum(overlaps >= overlapThreshold) / len(overlaps)
|
||||
print ("At threshold {:.2f}: recall = {:2.2f}".format(overlapThreshold, recall))
|
|
@ -0,0 +1,49 @@
|
|||
from __future__ import print_function
|
||||
import os, importlib, sys
|
||||
import PARAMETERS
|
||||
locals().update(importlib.import_module("PARAMETERS").__dict__)
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
image_set = 'test' # 'train', 'test'
|
||||
|
||||
# no need to change these parameters
|
||||
boUseNonMaximaSurpression = True
|
||||
visualizationDir = resultsDir + "visualizations"
|
||||
cntkParsedOutputDir = cntkFilesDir + image_set + "_parsed/"
|
||||
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
makeDirectory(resultsDir)
|
||||
makeDirectory(visualizationDir)
|
||||
|
||||
# loop over all images and visualize
|
||||
imdb = imdbs[image_set]
|
||||
for imgIndex in range(0, imdb.num_images):
|
||||
imgPath = imdb.image_path_at(imgIndex)
|
||||
imgWidth, imgHeight = imWidthHeight(imgPath)
|
||||
|
||||
# evaluate classifier for all rois
|
||||
labels, scores = nnPredict(imgIndex, cntkParsedOutputDir, cntk_nrRois, len(classes), None)
|
||||
|
||||
# remove the zero-padded rois
|
||||
scores = scores[:len(imdb.roidb[imgIndex]['boxes'])]
|
||||
labels = labels[:len(imdb.roidb[imgIndex]['boxes'])]
|
||||
|
||||
# perform non-maxima surpression. note that the detected classes in the image is not affected by this.
|
||||
nmsKeepIndices = []
|
||||
if boUseNonMaximaSurpression:
|
||||
nmsKeepIndices = applyNonMaximaSuppression(nmsThreshold, labels, scores, imdb.roidb[imgIndex]['boxes'])
|
||||
print ("Non-maxima surpression kept {:4} of {:4} rois (nmsThreshold={})".format(len(nmsKeepIndices), len(labels), nmsThreshold))
|
||||
|
||||
# visualize results
|
||||
imgDebug = visualizeResults(imgPath, labels, scores, imdb.roidb[imgIndex]['boxes'], cntk_padWidth, cntk_padHeight,
|
||||
classes, nmsKeepIndices, boDrawNegativeRois=True)
|
||||
imshow(imgDebug, waitDuration=0, maxDim = 800)
|
||||
# imwrite(imgDebug, visualizationDir + "/" + str(imgIndex) + os.path.basename(imgPath))
|
||||
|
||||
print ("DONE.")
|
|
@ -0,0 +1,117 @@
|
|||
from __future__ import print_function
|
||||
from builtins import chr
|
||||
import os, sys, importlib, shutil
|
||||
from cntk_helpers import *
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
imgDir = "C:/Users/chazhang/Desktop/newImgs/"
|
||||
|
||||
# no need to change these params
|
||||
drawingImgSize = 1000.0
|
||||
|
||||
|
||||
####################################
|
||||
# Functions
|
||||
####################################
|
||||
def event_cv2_drawRectangles(event, x, y, flags, param):
|
||||
global global_image
|
||||
global global_bboxes
|
||||
global global_leftButtonDownPoint
|
||||
|
||||
# draw all previous bounding boxes, and the most recent box in a different color
|
||||
imgCopy = global_image.copy()
|
||||
drawRectangles(imgCopy, global_bboxes)
|
||||
if len(global_bboxes)>0:
|
||||
drawRectangles(imgCopy, [global_bboxes[-1]], color = (255, 0, 0))
|
||||
|
||||
# handle mouse events
|
||||
if event == cv2.EVENT_LBUTTONDOWN:
|
||||
global_leftButtonDownPoint = (x, y)
|
||||
|
||||
elif event == cv2.EVENT_LBUTTONUP:
|
||||
pt1 = global_leftButtonDownPoint
|
||||
pt2 = (x, y)
|
||||
minPt = (min(pt1[0], pt2[0]), min(pt1[1], pt2[1]))
|
||||
maxPt = (max(pt1[0], pt2[0]), max(pt1[1], pt2[1]))
|
||||
imgWidth, imgHeight = imArrayWidthHeight(global_image)
|
||||
minPt = ptClip(minPt, imgWidth, imgHeight)
|
||||
maxPt = ptClip(maxPt, imgWidth, imgHeight)
|
||||
global_bboxes.append(minPt + maxPt)
|
||||
|
||||
elif flags == cv2.EVENT_FLAG_LBUTTON: #if left mouse button is held down
|
||||
cv2.rectangle(imgCopy, global_leftButtonDownPoint, (x, y), (255, 255, 0), 1)
|
||||
|
||||
else:
|
||||
drawCrossbar(imgCopy, (x, y))
|
||||
cv2.imshow("AnnotationWindow", imgCopy)
|
||||
|
||||
def scaleCropBboxes(rectsIn, scaleFactor, imgWidth, imgHeight):
|
||||
if len(rectsIn) <= 0:
|
||||
return rectsIn
|
||||
else:
|
||||
rects = [ [int(round(rect[i]/scaleFactor)) for i in range(4)]
|
||||
for rect in rectsIn]
|
||||
rects = [Bbox(*rect).crop(imgWidth, imgHeight).rect() for rect in rects]
|
||||
for rect in rects:
|
||||
assert (Bbox(*rect).isValid())
|
||||
return rects
|
||||
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
imgFilenames = [f for f in os.listdir(imgDir) if f.lower().endswith(".jpg")]
|
||||
|
||||
# loop over each image and get annotation
|
||||
for imgFilenameIndex,imgFilename in enumerate(imgFilenames):
|
||||
print (imgFilenameIndex, imgFilename)
|
||||
imgPath = os.path.join(imgDir, imgFilename)
|
||||
bBoxPath = imgPath[:-4] + ".bboxes.tsv"
|
||||
|
||||
# skip image if ground truth already exists
|
||||
if os.path.exists(bBoxPath):
|
||||
print ("Skipping image {0} since ground truth already exists".format(imgFilename))
|
||||
continue
|
||||
else:
|
||||
print ("Processing image {0} of {1}: {2}".format(imgFilenameIndex, len(imgFilenames), imgPath))
|
||||
|
||||
# prepare image window and callback
|
||||
global_bboxes = []
|
||||
global_image, scaleFactor = imresizeMaxDim(imread(imgPath), drawingImgSize)
|
||||
cv2.namedWindow("AnnotationWindow")
|
||||
cv2.setMouseCallback("AnnotationWindow", event_cv2_drawRectangles)
|
||||
cv2.imshow("AnnotationWindow", global_image)
|
||||
|
||||
# process user input
|
||||
while True:
|
||||
key = chr(cv2.waitKey())
|
||||
|
||||
# undo/remove last rectangle
|
||||
if key == "u":
|
||||
if len(global_bboxes) >= 1:
|
||||
global_bboxes = global_bboxes[:-1]
|
||||
imgCopy = global_image.copy()
|
||||
drawRectangles(imgCopy, global_bboxes)
|
||||
cv2.imshow("AnnotationWindow", imgCopy)
|
||||
|
||||
# skip image
|
||||
elif key == "s":
|
||||
if os.path.exists(bBoxPath):
|
||||
print ("Skipping image hence deleting existing bbox file: " + bBoxPath)
|
||||
os.remove(bBoxPath)
|
||||
break
|
||||
|
||||
# next image
|
||||
elif key == "n":
|
||||
bboxes = scaleCropBboxes(global_bboxes, scaleFactor, imWidth(imgPath), imHeight(imgPath))
|
||||
writeTable(bBoxPath, bboxes)
|
||||
break
|
||||
|
||||
# quit
|
||||
elif key == "q":
|
||||
sys.exit()
|
||||
|
||||
cv2.destroyAllWindows()
|
|
@ -0,0 +1,84 @@
|
|||
from __future__ import print_function
|
||||
try:
|
||||
# for Python2
|
||||
from Tkinter import *
|
||||
except ImportError:
|
||||
# for Python3
|
||||
from tkinter import *
|
||||
from PIL import ImageTk
|
||||
from cntk_helpers import *
|
||||
|
||||
|
||||
####################################
|
||||
# Parameters
|
||||
####################################
|
||||
imgDir = "C:/Users/chazhang/Desktop/newImgs/"
|
||||
classes = ("avocado", "orange", "butter", "champagne", "cheese", "eggBox", "gerkin", "joghurt", "ketchup",
|
||||
"orangeJuice", "onion", "pepper", "sausage", "tomato", "water", "apple", "milk",
|
||||
"tabasco", "soySauce", "mustard", "beer")
|
||||
|
||||
#no need to change these
|
||||
drawingImgSize = 1000
|
||||
boxWidth = 10
|
||||
boxHeight = 2
|
||||
|
||||
|
||||
####################################
|
||||
# Main
|
||||
####################################
|
||||
# define callback function for tk button
|
||||
def buttonPressedCallback(s):
|
||||
global global_lastButtonPressed
|
||||
global_lastButtonPressed = s
|
||||
|
||||
# create UI
|
||||
objectNames = np.sort(classes).tolist()
|
||||
objectNames += ["UNDECIDED", "EXCLUDE"]
|
||||
tk = Tk()
|
||||
w = Canvas(tk, width=len(objectNames) * boxWidth, height=len(objectNames) * boxHeight, bd = boxWidth, bg = 'white')
|
||||
w.grid(row = len(objectNames), column = 0, columnspan = 2)
|
||||
for objectIndex,objectName in enumerate(objectNames):
|
||||
b = Button(width=boxWidth, height=boxHeight, text=objectName, command=lambda s = objectName: buttonPressedCallback(s))
|
||||
b.grid(row = objectIndex, column = 0)
|
||||
|
||||
# loop over all images
|
||||
imgFilenames = getFilesInDirectory(imgDir, ".jpg")
|
||||
for imgIndex, imgFilename in enumerate(imgFilenames):
|
||||
print (imgIndex, imgFilename)
|
||||
labelsPath = os.path.join(imgDir, imgFilename[:-4] + ".bboxes.labels.tsv")
|
||||
if os.path.exists(labelsPath):
|
||||
print ("Skipping image {:3} ({}) since annotation file already exists: {}".format(imgIndex, imgFilename, labelsPath))
|
||||
continue
|
||||
|
||||
# load image and ground truth rectangles
|
||||
img = imread(os.path.join(imgDir,imgFilename))
|
||||
rectsPath = os.path.join(imgDir, imgFilename[:-4] + ".bboxes.tsv")
|
||||
rects = [ToIntegers(rect) for rect in readTable(rectsPath)]
|
||||
|
||||
# annotate each rectangle in turn
|
||||
labels = []
|
||||
for rectIndex,rect in enumerate(rects):
|
||||
imgCopy = img.copy()
|
||||
drawRectangles(imgCopy, [rect], thickness = 15)
|
||||
|
||||
# draw image in tk window
|
||||
imgTk, _ = imresizeMaxDim(imgCopy, drawingImgSize, boUpscale = True)
|
||||
imgTk = ImageTk.PhotoImage(imconvertCv2Pil(imgTk))
|
||||
label = Label(tk, image=imgTk)
|
||||
label.grid(row=0, column=1, rowspan=drawingImgSize)
|
||||
tk.update_idletasks()
|
||||
tk.update()
|
||||
|
||||
# busy-wait until button pressed
|
||||
global_lastButtonPressed = None
|
||||
while not global_lastButtonPressed:
|
||||
tk.update_idletasks()
|
||||
tk.update()
|
||||
|
||||
# store result
|
||||
print ("Button pressed = ", global_lastButtonPressed)
|
||||
labels.append(global_lastButtonPressed)
|
||||
|
||||
writeFile(labelsPath, labels)
|
||||
tk.destroy()
|
||||
print ("DONE.")
|
|
@ -0,0 +1,117 @@
|
|||
from __future__ import print_function
|
||||
from cntk_helpers import *
|
||||
from imdb_data import imdb_data
|
||||
import fastRCNN, time, datetime
|
||||
from fastRCNN.pascal_voc import pascal_voc # as nmsPython
|
||||
print (datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S'))
|
||||
|
||||
# dataset name
|
||||
datasetName = "grocery"
|
||||
# datasetName = "pascalVoc"
|
||||
# datasetName = "pascalVoc_aeroplanesOnly"
|
||||
|
||||
|
||||
############################
|
||||
# default parameters
|
||||
############################
|
||||
# cntk params
|
||||
cntk_nrRois = 2000 # 2000 # how many ROIs to zero-pad
|
||||
cntk_padWidth = 1000
|
||||
cntk_padHeight = 1000
|
||||
|
||||
# directories
|
||||
rootDir = os.path.dirname(os.path.realpath(sys.argv[0])) + "/"
|
||||
imgDir = rootDir + "../../DataSets/Grocery/"
|
||||
pascalDataDir = rootDir + "../../DataSets/Pascal/"
|
||||
|
||||
# derived directories
|
||||
procDir = rootDir + "proc/" + datasetName + "_{}/".format(cntk_nrRois)
|
||||
resultsDir = rootDir + "results/" + datasetName + "_{}/".format(cntk_nrRois)
|
||||
roiDir = procDir + "rois/"
|
||||
cntkFilesDir = procDir + "cntkFiles/"
|
||||
cntkTemplateDir = rootDir
|
||||
|
||||
# ROI generation
|
||||
roi_minDimRel = 0.01 # minium relative width/height of a ROI
|
||||
roi_maxDimRel = 1.0 # maximum relative width/height of a ROI
|
||||
roi_minNrPixelsRel = 0 # minium relative area covered by ROI
|
||||
roi_maxNrPixelsRel = 1.0 # maximm relative area covered by ROI
|
||||
roi_maxAspectRatio = 4.0 # maximum aspect Ratio of a ROI vertically and horizontally
|
||||
roi_maxImgDim = 200 # image size used for ROI generation
|
||||
ss_scale = 100 # selective search ROIS: parameter controlling cluster size for segmentation
|
||||
ss_sigma = 1.2 # selective search ROIs: width of gaussian kernal for segmentation
|
||||
ss_minSize = 20 # selective search ROIs: minimum component size for segmentation
|
||||
grid_nrScales = 7 # uniform grid ROIs: number of iterations from largest possible ROI to smaller ROIs
|
||||
grid_aspectRatios = [1.0, 2.0, 0.5] # uniform grid ROIs: aspect ratio of ROIs
|
||||
|
||||
# thresholds
|
||||
train_posOverlapThres = 0.5 # threshold for marking ROIs as positive.
|
||||
nmsThreshold = 0.3 # Non-Maxima suppression threshold (in range [0,1]).
|
||||
# The lower the more ROIs will be combined. Used in 5_evaluateResults and 5_visualizeResults.
|
||||
|
||||
|
||||
############################
|
||||
# project-specific parameters
|
||||
############################
|
||||
if datasetName.startswith("grocery"):
|
||||
classes = ('__background__', # always index 0
|
||||
'avocado', 'orange', 'butter', 'champagne', 'eggBox', 'gerkin', 'joghurt', 'ketchup',
|
||||
'orangeJuice', 'onion', 'pepper', 'tomato', 'water', 'milk', 'tabasco', 'mustard')
|
||||
|
||||
# roi generation
|
||||
roi_minDimRel = 0.04
|
||||
roi_maxDimRel = 0.4
|
||||
roi_minNrPixelsRel = 2 * roi_minDimRel * roi_minDimRel
|
||||
roi_maxNrPixelsRel = 0.33 * roi_maxDimRel * roi_maxDimRel
|
||||
|
||||
# model training / scoring
|
||||
classifier = 'nn'
|
||||
|
||||
# postprocessing
|
||||
nmsThreshold = 0.01
|
||||
|
||||
# database
|
||||
imdbs = dict() # database provider of images and image annotations
|
||||
for image_set in ["train", "test"]:
|
||||
imdbs[image_set] = imdb_data(image_set, classes, cntk_nrRois, imgDir, roiDir, cntkFilesDir, boAddGroundTruthRois = (image_set!='test'))
|
||||
|
||||
|
||||
elif datasetName.startswith("pascalVoc"):
|
||||
imgDir = pascalDataDir
|
||||
if datasetName.startswith("pascalVoc_aeroplanesOnly"):
|
||||
classes = ('__background__', 'aeroplane')
|
||||
lutImageSet = {"train": "trainval.aeroplaneOnly", "test": "test.aeroplaneOnly"}
|
||||
else:
|
||||
classes = ('__background__', # always index 0
|
||||
'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable',
|
||||
'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor')
|
||||
lutImageSet = {"train": "trainval", "test": "test"}
|
||||
|
||||
# model training / scoring
|
||||
classifier = 'nn'
|
||||
|
||||
#more than 99% of the test images have less than 4000 rois, but 50% more than 2000
|
||||
cntk_nrRois = 4000
|
||||
|
||||
# database
|
||||
imdbs = dict()
|
||||
for image_set, year in zip(["train", "test"], ["2007", "2007"]):
|
||||
imdbs[image_set] = fastRCNN.pascal_voc(lutImageSet[image_set], year, classes, cntk_nrRois, cacheDir = cntkFilesDir, devkit_path=pascalDataDir)
|
||||
print ("Number of {} images: {}".format(image_set, imdbs[image_set].num_images))
|
||||
|
||||
else:
|
||||
ERROR
|
||||
|
||||
|
||||
############################
|
||||
# computed parameters
|
||||
############################
|
||||
nrClasses = len(classes)
|
||||
cntk_featureDimensions = {'nn': nrClasses}
|
||||
|
||||
assert cntk_padWidth == cntk_padHeight, "ERROR: different width and height for padding currently not supported."
|
||||
assert classifier.lower() in ['svm','nn'], "ERROR: only 'nn' or 'svm' classifier supported."
|
||||
assert not (datasetName == 'pascalVoc' and classifier == 'svm'), "ERROR: while technically possibly, writing 2nd-last layer of CNTK model for all pascalVOC images takes too much disk memory."
|
||||
|
||||
print ("PARAMETERS: datasetName = " + datasetName)
|
||||
print ("PARAMETERS: cntk_nrRois = {}".format(cntk_nrRois))
|
|
@ -0,0 +1,119 @@
|
|||
# CNTK Examples: Image/Detection/Fast R-CNN
|
||||
|
||||
## Overview
|
||||
|
||||
|Data: |A toy dataset of images captured from a refrigerator.
|
||||
|:---------|:---
|
||||
|Purpose |This folder contains an end-to-end solution for using Fast R-CNN to perform object detection using a pre-trained AlexNet model and a set of user-supplied additional images.
|
||||
|Network |Convolutional neural networks, AlexNet.
|
||||
|Training |Stochastic gradient descent with momentum.
|
||||
|Comments |See below.
|
||||
|
||||
## Tutorial
|
||||
|
||||
Check out the CNTK Tutorial on [Object Detection using Fast R-CNN](https://github.com/Microsoft/CNTK/wiki/Object-Detection-using-Fast-R-CNN).
|
||||
|
||||
## Introduction
|
||||
|
||||
`Fast R-CNN` is an object detection algorithm proposed by `Ross Girshick` in 2015. The paper is accepted to ICCV 2015, and archived at https://arxiv.org/abs/1504.08083. Fast R-CNN builds on previous work to efficiently classify object proposals using deep convolutional networks. Compared to previous work, Fast R-CNN employs a `region of interest pooling` scheme that allows training to be single stage, with a multi-task loss. It trains the very deep VGG16 network 9x faster than R-CNN, is 213x faster at test-time, and achieves a higher mAP on PASCAL VOC 2012.
|
||||
|
||||
In this example, we use [AlexNet](../../Classification/AlexNet) as a pre-trained model, and adapt it to a toy dataset of images captured from a refrigerator to detect objects inside.
|
||||
|
||||
## Running the example
|
||||
|
||||
### Getting the data and AlexNet model
|
||||
|
||||
we use a toy dataset of images captured from a refrigerator to demonstrate Fast-R-CNN. Both the dataset and the pre-trained AlexNet model can be downloaded by running the following Python command:
|
||||
|
||||
`python install_fastrcnn.py`
|
||||
|
||||
After running the script, the toy dataset will be installed under the `Image/DataSets/Grocery` folder. And the AlexNet model will be downloaded to the `Image/PretrainedModels` folder. We recommend you to keep the downloaded data in the respective folder while downloading, as the configuration files in this folder assumes that by default.
|
||||
|
||||
### Setup
|
||||
|
||||
Currently, CNTK only supports `Python 3.4`. We recommend to install anaconda python (http://continuum.io/downloads) and create a python 3.4 environment using:
|
||||
```
|
||||
conda create --name cntk python=3.4.3 numpy scipy
|
||||
activate cntk
|
||||
```
|
||||
To run the code in this example, you need to install a few additional packages. Under Python 3.4 (64bit version assumed), go to the FastRCNN folder and run:
|
||||
```
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
You will further need Scikit-Image and OpenCV to run these examples. You can download the corresponding wheel packages and install them manually. For Windows users, visit http://www.lfd.uci.edu/~gohlke/pythonlibs/, and download:
|
||||
|
||||
scikit_image-0.12.3-cp34-cp34m-win_amd64.whl
|
||||
opencv_python-3.1.0-cp34-cp34m-win_amd64.whl
|
||||
|
||||
Once you download the respective wheel binaries, install them with:
|
||||
|
||||
`pip install your_download_folder/scikit_image-0.12.3-cp34-cp34m-win_amd64.whl`
|
||||
`pip install your_download_folder/opencv_python-3.1.0-cp34-cp34m-win_amd64.whl`
|
||||
|
||||
This example code assumes you are using 64bit version of Python 3.4, as the Fast R-CNN DLL files under [utils_win64](./fastRCNN/utils3_win64) are prebuilt for this version. If your task requires the use of a different Python version, please recompile these DLL files yourself in the correct environment.
|
||||
|
||||
The folder where cntk.exe resides needs to be in your PATH environment variable.
|
||||
|
||||
Last but not least, in `PARAMETERS.py`: make sure datasetName is set to "grocery".
|
||||
|
||||
### Preprocess data
|
||||
|
||||
The toy refrigerator data comes with labeled region of interests. To run Fast R-CNN training, the first step is to generate a large set of potential region proposals via selective search. For this purpose, you can run:
|
||||
|
||||
`python A1_GenerateInputROIs.py`
|
||||
|
||||
This script will go through all training, validation and testing images, and extract potential region of interests via selective search (https://staff.fnwi.uva.nl/th.gevers/pub/GeversIJCV2013.pdf).
|
||||
|
||||
To visualize the generated ROIs, you can run:
|
||||
|
||||
`python B1_VisualizeInputROIs.py`
|
||||
|
||||
Press any key to step through the images. Further, you may check the recall of the proposed regions by running:
|
||||
|
||||
`python B2_EvaluateInputROIs.py`
|
||||
|
||||
This will generate something like:
|
||||
|
||||
2016-10-21 07:35:03
|
||||
PARAMETERS: datasetName = grocery
|
||||
PARAMETERS: cntk_nrRois = 2000
|
||||
Processing subdir 'positive', image 0 of 20
|
||||
Processing subdir 'testImages', image 0 of 5
|
||||
Average number of rois per image 1312.92
|
||||
At threshold 0.00: recall = 1.00
|
||||
At threshold 0.10: recall = 1.00
|
||||
At threshold 0.20: recall = 1.00
|
||||
At threshold 0.30: recall = 1.00
|
||||
At threshold 0.40: recall = 1.00
|
||||
At threshold 0.50: recall = 1.00
|
||||
At threshold 0.60: recall = 1.00
|
||||
At threshold 0.70: recall = 1.00
|
||||
At threshold 0.80: recall = 0.84
|
||||
At threshold 0.90: recall = 0.28
|
||||
At threshold 1.00: recall = 0.00
|
||||
|
||||
It shows that up to threashold `0.70`, we have `100%` recall on the ground truth region of interests.
|
||||
|
||||
### Running Fast R-CNN training
|
||||
|
||||
Now you can start a full training of Fast R-CNN on the grocery data by running:
|
||||
|
||||
`python A2_RunCntk.py`
|
||||
|
||||
This python code will start training Fast R-CNN using the [fastrcnn.cntk](./fastrcnn.cntk) configuration file (in BrainScript).
|
||||
|
||||
If you carefully examine the [fastrcnn.cntk](./fastrcnn.cntk) file, you would notice we load the pre-trained AlexNet model, clone the network up to the `conv5_y` layer and freeze all bottom layer parameters, and then added pooling and dense layers on the top with trainable parameters. The training will run for 17 epochs, and reaching training error around `1.05%`. The script will also write the network output for the entire train and test dataset.
|
||||
|
||||
### Evaluate trained model
|
||||
|
||||
One the model has been trained for detection, you may run:
|
||||
|
||||
`python A3_ParseAndEvaluateOutput.py`
|
||||
|
||||
to parse and evaluate the output accuracy. You should see mean average precision (mAP) at around `0.86` for this simple toy example. You may further visualize the detection result on the test data with:
|
||||
|
||||
`python B3_VisualizeOutputROIs.py`
|
||||
|
||||
## Running Fast R-CNN on other data sets
|
||||
|
||||
To learn more about CNTK Fast R-CNN, e.g. how to run it on Pascal VOC data or on your own data set, please go to the CNTK tutorial on [Object Detection using Fast R-CNN](https://github.com/Microsoft/CNTK/wiki/Object-Detection-using-Fast-R-CNN).
|
|
@ -0,0 +1,947 @@
|
|||
from __future__ import print_function
|
||||
from builtins import str
|
||||
import pdb, sys, os, time
|
||||
import numpy as np
|
||||
import selectivesearch
|
||||
from easydict import EasyDict
|
||||
from fastRCNN.nms import nms as nmsPython
|
||||
from builtins import range
|
||||
|
||||
|
||||
####################################
|
||||
# Region-of-interest
|
||||
####################################
|
||||
def getSelectiveSearchRois(img, ssScale, ssSigma, ssMinSize, maxDim):
|
||||
# Selective Search
|
||||
# Parameters
|
||||
# ----------
|
||||
# im_orig : ndarray
|
||||
# Input image
|
||||
# scale : int
|
||||
# Free parameter. Higher means larger clusters in felzenszwalb segmentation.
|
||||
# sigma : float
|
||||
# Width of Gaussian kernel for felzenszwalb segmentation.
|
||||
# min_size : int
|
||||
# Minimum component size for felzenszwalb segmentation.
|
||||
# Returns
|
||||
# -------
|
||||
# img : ndarray
|
||||
# image with region label
|
||||
# region label is stored in the 4th value of each pixel [r,g,b,(region)]
|
||||
# regions : array of dict
|
||||
# [
|
||||
# {
|
||||
# 'rect': (left, top, right, bottom),
|
||||
# 'labels': [...]
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
# inter_area seems to give much better results esp when upscaling image
|
||||
img, scale = imresizeMaxDim(img, maxDim, boUpscale=True, interpolation = cv2.INTER_AREA)
|
||||
_, ssRois = selectivesearch.selective_search(img, scale=ssScale, sigma=ssSigma, min_size=ssMinSize)
|
||||
rects = []
|
||||
for ssRoi in ssRois:
|
||||
x, y, w, h = ssRoi['rect']
|
||||
rects.append([x,y,x+w,y+h])
|
||||
return rects, img, scale
|
||||
|
||||
|
||||
def getGridRois(imgWidth, imgHeight, nrGridScales, aspectRatios = [1.0]):
|
||||
rects = []
|
||||
# start adding large ROIs and then smaller ones
|
||||
for iter in range(nrGridScales):
|
||||
cellWidth = 1.0 * min(imgHeight, imgWidth) / (2 ** iter)
|
||||
step = cellWidth / 2.0
|
||||
|
||||
for aspectRatio in aspectRatios:
|
||||
wStart = 0
|
||||
while wStart < imgWidth:
|
||||
hStart = 0
|
||||
while hStart < imgHeight:
|
||||
if aspectRatio < 1:
|
||||
wEnd = wStart + cellWidth
|
||||
hEnd = hStart + cellWidth / aspectRatio
|
||||
else:
|
||||
wEnd = wStart + cellWidth * aspectRatio
|
||||
hEnd = hStart + cellWidth
|
||||
if wEnd < imgWidth-1 and hEnd < imgHeight-1:
|
||||
rects.append([wStart, hStart, wEnd, hEnd])
|
||||
hStart += step
|
||||
wStart += step
|
||||
return rects
|
||||
|
||||
|
||||
def filterRois(rects, maxWidth, maxHeight, roi_minNrPixels, roi_maxNrPixels,
|
||||
roi_minDim, roi_maxDim, roi_maxAspectRatio):
|
||||
filteredRects = []
|
||||
filteredRectsSet = set()
|
||||
for rect in rects:
|
||||
if tuple(rect) in filteredRectsSet: # excluding rectangles with same co-ordinates
|
||||
continue
|
||||
|
||||
x, y, x2, y2 = rect
|
||||
w = x2 - x
|
||||
h = y2 - y
|
||||
assert(w>=0 and h>=0)
|
||||
|
||||
# apply filters
|
||||
if h == 0 or w == 0 or \
|
||||
x2 > maxWidth or y2 > maxHeight or \
|
||||
w < roi_minDim or h < roi_minDim or \
|
||||
w > roi_maxDim or h > roi_maxDim or \
|
||||
w * h < roi_minNrPixels or w * h > roi_maxNrPixels or \
|
||||
w / h > roi_maxAspectRatio or h / w > roi_maxAspectRatio:
|
||||
continue
|
||||
filteredRects.append(rect)
|
||||
filteredRectsSet.add(tuple(rect))
|
||||
|
||||
# could combine rectangles using non-maxima surpression or with similar co-ordinates
|
||||
# groupedRectangles, weights = cv2.groupRectangles(np.asanyarray(rectsInput, np.float).tolist(), 1, 0.3)
|
||||
# groupedRectangles = nms_python(np.asarray(rectsInput, np.float), 0.5)
|
||||
assert(len(filteredRects) > 0)
|
||||
return filteredRects
|
||||
|
||||
|
||||
def readRois(roiDir, subdir, imgFilename):
|
||||
roiPath = roiDir + subdir + "/" + imgFilename[:-4] + ".roi.txt"
|
||||
rois = np.loadtxt(roiPath, np.int)
|
||||
if len(rois) == 4 and type(rois[0]) == np.int32: # if only a single ROI in an image
|
||||
rois = [rois]
|
||||
return rois
|
||||
|
||||
|
||||
####################################
|
||||
# Generate and parse CNTK files
|
||||
####################################
|
||||
def readGtAnnotation(imgPath):
|
||||
bboxesPath = imgPath[:-4] + ".bboxes.tsv"
|
||||
labelsPath = imgPath[:-4] + ".bboxes.labels.tsv"
|
||||
bboxes = np.array(readTable(bboxesPath), np.int32)
|
||||
labels = readFile(labelsPath)
|
||||
assert (len(bboxes) == len(labels))
|
||||
return bboxes, labels
|
||||
|
||||
def getCntkInputPaths(cntkFilesDir, image_set):
|
||||
cntkImgsListPath = cntkFilesDir + image_set + '.txt'
|
||||
cntkRoiCoordsPath = cntkFilesDir + image_set + '.rois.txt'
|
||||
cntkRoiLabelsPath = cntkFilesDir + image_set + '.roilabels.txt'
|
||||
cntkNrRoisPath = cntkFilesDir + image_set + '.nrRois.txt'
|
||||
return cntkImgsListPath, cntkRoiCoordsPath, cntkRoiLabelsPath, cntkNrRoisPath
|
||||
|
||||
def roiTransformPadScaleParams(imgWidth, imgHeight, padWidth, padHeight, boResizeImg = True):
|
||||
scale = 1.0
|
||||
if boResizeImg:
|
||||
assert padWidth == padHeight, "currently only supported equal width/height"
|
||||
scale = 1.0 * padWidth / max(imgWidth, imgHeight)
|
||||
imgWidth = round(imgWidth * scale)
|
||||
imgHeight = round(imgHeight * scale)
|
||||
|
||||
targetw = padWidth
|
||||
targeth = padHeight
|
||||
w_offset = ((targetw - imgWidth) / 2.)
|
||||
h_offset = ((targeth - imgHeight) / 2.)
|
||||
if boResizeImg and w_offset > 0 and h_offset > 0:
|
||||
print ("ERROR: both offsets are > 0:", imgCounter, imgWidth, imgHeight, w_offset, h_offset)
|
||||
error
|
||||
if (w_offset < 0 or h_offset < 0):
|
||||
print ("ERROR: at least one offset is < 0:", imgWidth, imgHeight, w_offset, h_offset, scale)
|
||||
return targetw, targeth, w_offset, h_offset, scale
|
||||
|
||||
def roiTransformPadScale(rect, w_offset, h_offset, scale = 1.0):
|
||||
rect = [int(round(scale * d)) for d in rect]
|
||||
rect[0] += w_offset
|
||||
rect[1] += h_offset
|
||||
rect[2] += w_offset
|
||||
rect[3] += h_offset
|
||||
return rect
|
||||
|
||||
def getCntkRoiCoordsLine(rect, targetw, targeth):
|
||||
# convert from absolute to relative co-ordinates
|
||||
x, y, x2, y2 = rect
|
||||
xrel = float(x) / (1.0 * targetw)
|
||||
yrel = float(y) / (1.0 * targeth)
|
||||
wrel = float(x2 - x) / (1.0 * targetw)
|
||||
hrel = float(y2 - y) / (1.0 * targeth)
|
||||
assert xrel <= 1.0, "Error: xrel should be <= 1 but is " + str(xrel)
|
||||
assert yrel <= 1.0, "Error: yrel should be <= 1 but is " + str(yrel)
|
||||
assert wrel >= 0.0, "Error: wrel should be >= 0 but is " + str(wrel)
|
||||
assert hrel >= 0.0, "Error: hrel should be >= 0 but is " + str(hrel)
|
||||
return " {} {} {} {}".format(xrel, yrel, wrel, hrel)
|
||||
|
||||
def getCntkRoiLabelsLine(overlaps, thres, nrClasses):
|
||||
# get one hot encoding
|
||||
maxgt = np.argmax(overlaps)
|
||||
if overlaps[maxgt] < thres: # set to background label if small overlap with GT
|
||||
maxgt = 0
|
||||
oneHot = np.zeros((nrClasses), dtype=int)
|
||||
oneHot[maxgt] = 1
|
||||
oneHotString = " {}".format(" ".join(str(x) for x in oneHot))
|
||||
return oneHotString
|
||||
|
||||
def cntkPadInputs(currentNrRois, targetNrRois, nrClasses, boxesStr, labelsStr):
|
||||
assert currentNrRois <= targetNrRois, "Current number of rois ({}) should be <= target number of rois ({})".format(currentNrRois, targetNrRois)
|
||||
while currentNrRois < targetNrRois:
|
||||
boxesStr += " 0 0 0 0"
|
||||
labelsStr += " 1" + " 0" * (nrClasses - 1)
|
||||
currentNrRois += 1
|
||||
return boxesStr, labelsStr
|
||||
|
||||
def checkCntkOutputFile(cntkImgsListPath, cntkOutputPath, cntkNrRois, outputDim):
|
||||
imgPaths = getColumn(readTable(cntkImgsListPath), 1)
|
||||
with open(cntkOutputPath) as fp:
|
||||
for imgIndex in range(len(imgPaths)):
|
||||
if imgIndex % 100 == 1:
|
||||
print ("Checking cntk output file, image %d of %d..." % (imgIndex, len(imgPaths)))
|
||||
for roiIndex in range(cntkNrRois):
|
||||
assert (fp.readline() != "")
|
||||
assert (fp.readline() == "") # test if end-of-file is reached
|
||||
|
||||
# parse the cntk output file and save the output for each image individually
|
||||
def parseCntkOutput(cntkImgsListPath, cntkOutputPath, outParsedDir, cntkNrRois, outputDim,
|
||||
saveCompressed = False, skipCheck = False, skip5Mod = None):
|
||||
if not skipCheck and skip5Mod == None:
|
||||
checkCntkOutputFile(cntkImgsListPath, cntkOutputPath, cntkNrRois, outputDim)
|
||||
|
||||
# parse cntk output and write file for each image
|
||||
# always read in data for each image to forward file pointer
|
||||
imgPaths = getColumn(readTable(cntkImgsListPath), 1)
|
||||
with open(cntkOutputPath) as fp:
|
||||
for imgIndex in range(len(imgPaths)):
|
||||
line = fp.readline()
|
||||
if skip5Mod != None and imgIndex % 5 != skip5Mod:
|
||||
print ("Skipping image {} (skip5Mod = {})".format(imgIndex, skip5Mod))
|
||||
continue
|
||||
print ("Parsing cntk output file, image %d of %d" % (imgIndex, len(imgPaths)))
|
||||
|
||||
# convert to floats
|
||||
data = []
|
||||
values = np.fromstring(line, dtype=float, sep=" ")
|
||||
assert len(values) == cntkNrRois * outputDim, "ERROR: expected dimension of {} but found {}".format(cntkNrRois * outputDim, len(values))
|
||||
for i in range(cntkNrRois):
|
||||
posStart = i * outputDim
|
||||
posEnd = posStart + outputDim
|
||||
currValues = values[posStart:posEnd]
|
||||
data.append(currValues)
|
||||
|
||||
# save
|
||||
data = np.array(data, np.float32)
|
||||
outPath = outParsedDir + str(imgIndex) + ".dat"
|
||||
if saveCompressed:
|
||||
np.savez_compressed(outPath, data)
|
||||
else:
|
||||
np.savez(outPath, data)
|
||||
assert (fp.readline() == "") # test if end-of-file is reached
|
||||
|
||||
# parse the cntk labels file and return the labels
|
||||
def readCntkRoiLabels(roiLabelsPath, nrRois, roiDim, stopAtImgIndex = None):
|
||||
roiLabels = []
|
||||
for imgIndex, line in enumerate(readFile(roiLabelsPath)):
|
||||
if stopAtImgIndex and imgIndex == stopAtImgIndex:
|
||||
break
|
||||
roiLabels.append([])
|
||||
pos = line.find(b'|roiLabels ')
|
||||
valuesString = line[pos + 10:].strip().split(b' ')
|
||||
assert (len(valuesString) == nrRois * roiDim)
|
||||
|
||||
for boxIndex in range(nrRois):
|
||||
oneHotLabels = [int(s) for s in valuesString[boxIndex*roiDim : (boxIndex+1)*roiDim]]
|
||||
assert(sum(oneHotLabels) == 1)
|
||||
roiLabels[imgIndex].append(np.argmax(oneHotLabels))
|
||||
return roiLabels
|
||||
|
||||
# parse the cntk rois file and return the co-ordinates
|
||||
def readCntkRoiCoordinates(imgPaths, cntkRoiCoordsPath, nrRois, padWidth, padHeight, stopAtImgIndex = None):
|
||||
roiCoords = []
|
||||
for imgIndex, line in enumerate(readFile(cntkRoiCoordsPath)):
|
||||
if stopAtImgIndex and imgIndex == stopAtImgIndex:
|
||||
break
|
||||
roiCoords.append([])
|
||||
pos = line.find(b'|rois ')
|
||||
valuesString = line[pos + 5:].strip().split(b' ')
|
||||
assert (len(valuesString) == nrRois * 4)
|
||||
|
||||
imgWidth, imgHeight = imWidthHeight(imgPaths[imgIndex])
|
||||
for boxIndex in range(nrRois):
|
||||
rect = [float(s) for s in valuesString[boxIndex*4 : (boxIndex+1)*4]]
|
||||
x,y,w,h = rect
|
||||
# convert back from padded-rois-co-ordinates to image co-ordinates
|
||||
rect = getAbsoluteROICoordinates([x,y,x+w,y+h], imgWidth, imgHeight, padWidth, padHeight)
|
||||
roiCoords[imgIndex].append(rect)
|
||||
return roiCoords
|
||||
|
||||
# convert roi co-ordinates from CNTK file back to original image co-ordinates
|
||||
def getAbsoluteROICoordinates(roi, imgWidth, imgHeight, padWidth, padHeight, resizeMethod = 'padScale'):
|
||||
if roi == [0,0,0,0]: # if padded roi
|
||||
return [0,0,0,0]
|
||||
|
||||
if resizeMethod == "crop":
|
||||
minDim = min(imgWidth, imgHeight)
|
||||
offsetWidth = 0.5 * abs(imgWidth - imgHeight)
|
||||
if (imgWidth >= imgHeight): # horizontal photo
|
||||
rect = [roi[0] * minDim + offsetWidth, roi[1] * minDim, None, None]
|
||||
else:
|
||||
rect = [roi[0] * minDim, roi[1] * minDim + offsetWidth, None, None]
|
||||
rect[2] = rect[0] + roi[2] * minDim
|
||||
rect[3] = rect[1] + roi[3] * minDim
|
||||
|
||||
elif resizeMethod == "pad" or resizeMethod == "padScale":
|
||||
if resizeMethod == "padScale":
|
||||
scale = float(padWidth) / max(imgWidth, imgHeight)
|
||||
imgWidthScaled = int(round(imgWidth * scale))
|
||||
imgHeightScaled = int(round(imgHeight * scale))
|
||||
else:
|
||||
scale = 1.0
|
||||
imgWidthScaled = imgWidth
|
||||
imgHeightScaled = imgHeight
|
||||
|
||||
w_offset = float(padWidth - imgWidthScaled) / 2.0
|
||||
h_offset = float(padHeight - imgHeightScaled) / 2.0
|
||||
if resizeMethod == "padScale":
|
||||
assert(w_offset == 0 or h_offset == 0)
|
||||
|
||||
x0 = max(roi[0] * padWidth - w_offset, 0)
|
||||
y0 = max(roi[1] * padHeight - h_offset, 0)
|
||||
rect = [x0, y0,
|
||||
x0 + (roi[2] - roi[0]) * padWidth,
|
||||
y0 + (roi[3] - roi[1]) * padHeight]
|
||||
rect = [int(round(r / scale)) for r in rect]
|
||||
else:
|
||||
print ("ERROR: Unknown resize method '%s'" % resizeMethod)
|
||||
error
|
||||
assert(min(rect) >=0 and max(rect[0],rect[2]) <= imgWidth and max(rect[1],rect[3]) <= imgHeight)
|
||||
return rect
|
||||
|
||||
|
||||
####################################
|
||||
# Classifier training / scoring
|
||||
####################################
|
||||
def getSvmModelPaths(svmDir, experimentName):
|
||||
svmWeightsPath = "{}svmweights_{}.txt".format(svmDir, experimentName)
|
||||
svmBiasPath = "{}svmbias_{}.txt".format(svmDir, experimentName)
|
||||
svmFeatScalePath = "{}svmfeature_scale_{}.txt".format(svmDir, experimentName)
|
||||
return svmWeightsPath, svmBiasPath, svmFeatScalePath
|
||||
|
||||
def loadSvm(svmDir, experimentName):
|
||||
svmWeightsPath, svmBiasPath, svmFeatScalePath = getSvmModelPaths(svmDir, experimentName)
|
||||
svmWeights = np.loadtxt(svmWeightsPath, np.float32)
|
||||
svmBias = np.loadtxt(svmBiasPath, np.float32)
|
||||
svmFeatScale = np.loadtxt(svmFeatScalePath, np.float32)
|
||||
return svmWeights, svmBias, svmFeatScale
|
||||
|
||||
def saveSvm(svmDir, experimentName, svmWeights, svmBias, featureScale):
|
||||
svmWeightsPath, svmBiasPath, svmFeatScalePath = getSvmModelPaths(svmDir, experimentName)
|
||||
np.savetxt(svmWeightsPath, svmWeights)
|
||||
np.savetxt(svmBiasPath, svmBias)
|
||||
np.savetxt(svmFeatScalePath, featureScale)
|
||||
|
||||
def svmPredict(imgIndex, cntkOutputIndividualFilesDir, svmWeights, svmBias, svmFeatScale, roiSize, roiDim, decisionThreshold = 0):
|
||||
cntkOutputPath = os.path.join(cntkOutputIndividualFilesDir, str(imgIndex) + ".dat.npz")
|
||||
data = np.load(cntkOutputPath)['arr_0']
|
||||
assert(len(data) == roiSize)
|
||||
|
||||
# get prediction for each roi
|
||||
labels = []
|
||||
maxScores = []
|
||||
for roiIndex in range(roiSize):
|
||||
feat = data[roiIndex]
|
||||
scores = np.dot(svmWeights, feat * 1.0 / svmFeatScale) + svmBias.ravel()
|
||||
assert (len(scores) == roiDim)
|
||||
maxArg = np.argmax(scores[1:]) + 1
|
||||
maxScore = scores[maxArg]
|
||||
if maxScore < decisionThreshold:
|
||||
maxArg = 0
|
||||
labels.append(maxArg)
|
||||
maxScores.append(maxScore)
|
||||
return labels, maxScores
|
||||
|
||||
def nnPredict(imgIndex, cntkParsedOutputDir, roiSize, roiDim, decisionThreshold = None):
|
||||
cntkOutputPath = os.path.join(cntkParsedOutputDir, str(imgIndex) + ".dat.npz")
|
||||
data = np.load(cntkOutputPath)['arr_0']
|
||||
assert(len(data) == roiSize)
|
||||
|
||||
# get prediction for each roi
|
||||
labels = []
|
||||
maxScores = []
|
||||
for roiIndex in range(roiSize):
|
||||
scores = data[roiIndex]
|
||||
scores = softmax(scores)
|
||||
assert (len(scores) == roiDim)
|
||||
maxArg = np.argmax(scores)
|
||||
maxScore = scores[maxArg]
|
||||
if decisionThreshold and maxScore < decisionThreshold:
|
||||
maxArg = 0
|
||||
labels.append(maxArg)
|
||||
maxScores.append(maxScore)
|
||||
return labels, maxScores
|
||||
|
||||
def imdbUpdateRoisWithHighGtOverlap(imdb, positivesGtOverlapThreshold):
|
||||
addedPosCounter = 0
|
||||
existingPosCounter = 0
|
||||
for imgIndex in range(imdb.num_images):
|
||||
for boxIndex, gtLabel in enumerate(imdb.roidb[imgIndex]['gt_classes']):
|
||||
if gtLabel > 0:
|
||||
existingPosCounter += 1
|
||||
else:
|
||||
overlaps = imdb.roidb[imgIndex]['gt_overlaps'][boxIndex, :].toarray()[0]
|
||||
maxInd = np.argmax(overlaps)
|
||||
maxOverlap = overlaps[maxInd]
|
||||
if maxOverlap >= positivesGtOverlapThreshold and maxInd > 0:
|
||||
addedPosCounter += 1
|
||||
imdb.roidb[imgIndex]['gt_classes'][boxIndex] = maxInd
|
||||
return existingPosCounter, addedPosCounter
|
||||
|
||||
|
||||
####################################
|
||||
# Visualize results
|
||||
####################################
|
||||
def visualizeResults(imgPath, roiLabels, roiScores, roiRelCoords, padWidth, padHeight, classes,
|
||||
nmsKeepIndices = None, boDrawNegativeRois = True, decisionThreshold = 0.0):
|
||||
# read and resize image
|
||||
imgWidth, imgHeight = imWidthHeight(imgPath)
|
||||
scale = 800.0 / max(imgWidth, imgHeight)
|
||||
imgDebug = imresize(imread(imgPath), scale)
|
||||
assert(len(roiLabels) == len(roiRelCoords))
|
||||
if roiScores:
|
||||
assert(len(roiLabels) == len(roiScores))
|
||||
|
||||
# draw multiple times to avoid occlusions
|
||||
for iter in range(0,3):
|
||||
for roiIndex in range(len(roiRelCoords)):
|
||||
label = roiLabels[roiIndex]
|
||||
if roiScores:
|
||||
score = roiScores[roiIndex]
|
||||
if decisionThreshold and score < decisionThreshold:
|
||||
label = 0
|
||||
|
||||
# init drawing parameters
|
||||
thickness = 1
|
||||
if label == 0:
|
||||
color = (255, 0, 0)
|
||||
else:
|
||||
color = getColorsPalette()[label]
|
||||
rect = [int(scale * i) for i in roiRelCoords[roiIndex]]
|
||||
|
||||
# draw in higher iterations only the detections
|
||||
if iter == 0 and boDrawNegativeRois:
|
||||
drawRectangles(imgDebug, [rect], color=color, thickness=thickness)
|
||||
elif iter==1 and label > 0:
|
||||
if not nmsKeepIndices or (roiIndex in nmsKeepIndices):
|
||||
thickness = 4
|
||||
drawRectangles(imgDebug, [rect], color=color, thickness=thickness)
|
||||
elif iter == 2 and label > 0:
|
||||
if not nmsKeepIndices or (roiIndex in nmsKeepIndices):
|
||||
font = ImageFont.truetype("arial.ttf", 18)
|
||||
text = classes[label]
|
||||
if roiScores:
|
||||
text += "(" + str(round(score, 2)) + ")"
|
||||
imgDebug = drawText(imgDebug, (rect[0],rect[1]), text, color = (255,255,255), font = font, colorBackground=color)
|
||||
return imgDebug
|
||||
|
||||
def applyNonMaximaSuppression(nmsThreshold, labels, scores, coords):
|
||||
# generate input for nms
|
||||
allIndices = []
|
||||
nmsRects = [[[]] for _ in range(max(labels) + 1)]
|
||||
coordsWithScores = np.hstack((coords, np.array([scores]).T))
|
||||
for i in range(max(labels) + 1):
|
||||
indices = np.where(np.array(labels) == i)[0]
|
||||
nmsRects[i][0] = coordsWithScores[indices,:]
|
||||
allIndices.append(indices)
|
||||
|
||||
# call nms
|
||||
_, nmsKeepIndicesList = apply_nms(nmsRects, nmsThreshold)
|
||||
|
||||
# map back to original roi indices
|
||||
nmsKeepIndices = []
|
||||
for i in range(max(labels) + 1):
|
||||
for keepIndex in nmsKeepIndicesList[i][0]:
|
||||
nmsKeepIndices.append(allIndices[i][keepIndex]) # for keepIndex in nmsKeepIndicesList[i][0]]
|
||||
assert (len(nmsKeepIndices) == len(set(nmsKeepIndices))) # check if no roi indices was added >1 times
|
||||
return nmsKeepIndices
|
||||
|
||||
def apply_nms(all_boxes, thresh, boUsePythonImpl = True):
|
||||
"""Apply non-maximum suppression to all predicted boxes output by the test_net method."""
|
||||
num_classes = len(all_boxes)
|
||||
num_images = len(all_boxes[0])
|
||||
nms_boxes = [[[] for _ in range(num_images)]
|
||||
for _ in range(num_classes)]
|
||||
nms_keepIndices = [[[] for _ in range(num_images)]
|
||||
for _ in range(num_classes)]
|
||||
for cls_ind in range(num_classes):
|
||||
for im_ind in range(num_images):
|
||||
dets = all_boxes[cls_ind][im_ind]
|
||||
if dets == []:
|
||||
continue
|
||||
if boUsePythonImpl:
|
||||
keep = nmsPython(dets, thresh)
|
||||
else:
|
||||
keep = nms(dets, thresh)
|
||||
if len(keep) == 0:
|
||||
continue
|
||||
nms_boxes[cls_ind][im_ind] = dets[keep, :].copy()
|
||||
nms_keepIndices[cls_ind][im_ind] = keep
|
||||
return nms_boxes, nms_keepIndices
|
||||
|
||||
####################################
|
||||
# Wrappers for compatibility with
|
||||
# original fastRCNN code
|
||||
####################################
|
||||
class DummyNet(object):
|
||||
def __init__(self, dim, num_classes, cntkParsedOutputDir):
|
||||
self.name = 'dummyNet'
|
||||
self.cntkParsedOutputDir = cntkParsedOutputDir
|
||||
self.params = {
|
||||
"cls_score": [ EasyDict({'data': np.zeros((num_classes, dim), np.float32) }),
|
||||
EasyDict({'data': np.zeros((num_classes, 1), np.float32) })],
|
||||
"trainers" : None,
|
||||
}
|
||||
|
||||
def im_detect(net, im, boxes, feature_scale=None, bboxIndices=None, boReturnClassifierScore=True, classifier = 'svm'): # trainers=None,
|
||||
# Return:
|
||||
# scores (ndarray): R x K array of object class scores (K includes
|
||||
# background as object category 0)
|
||||
# (optional) boxes (ndarray): R x (4*K) array of predicted bounding boxes
|
||||
# load cntk output for the given image
|
||||
cntkOutputPath = os.path.join(net.cntkParsedOutputDir, str(im) + ".dat.npz")
|
||||
cntkOutput = np.load(cntkOutputPath)['arr_0']
|
||||
if bboxIndices != None:
|
||||
cntkOutput = cntkOutput[bboxIndices, :] # only keep output for certain rois
|
||||
else:
|
||||
cntkOutput = cntkOutput[:len(boxes), :] # remove zero-padded rois
|
||||
|
||||
# compute scores for each box and each class
|
||||
scores = None
|
||||
if boReturnClassifierScore:
|
||||
if classifier == 'nn':
|
||||
scores = softmax2D(cntkOutput)
|
||||
elif classifier == 'svm':
|
||||
svmBias = net.params['cls_score'][1].data.transpose()
|
||||
svmWeights = net.params['cls_score'][0].data.transpose()
|
||||
scores = np.dot(cntkOutput * 1.0 / feature_scale, svmWeights) + svmBias
|
||||
assert (np.unique(scores[:, 0]) == 0) # svm always returns 0 for label 0
|
||||
else:
|
||||
error
|
||||
return scores, None, cntkOutput
|
||||
|
||||
|
||||
####################################
|
||||
# Subset of helper library
|
||||
# used in the fastRCNN code
|
||||
####################################
|
||||
# Typical meaning of variable names -- Computer Vision:
|
||||
# pt = 2D point (column,row)
|
||||
# img = image
|
||||
# width,height (or w/h) = image dimensions
|
||||
# bbox = bbox object (stores: left, top,right,bottom co-ordinates)
|
||||
# rect = rectangle (order: left, top, right, bottom)
|
||||
# angle = rotation angle in degree
|
||||
# scale = image up/downscaling factor
|
||||
|
||||
# Typical meaning of variable names -- general:
|
||||
# lines,strings = list of strings
|
||||
# line,string = single string
|
||||
# xmlString = string with xml tags
|
||||
# table = 2D row/column matrix implemented using a list of lists
|
||||
# row,list1D = single row in a table, i.e. single 1D-list
|
||||
# rowItem = single item in a row
|
||||
# list1D = list of items, not necessarily strings
|
||||
# item = single item of a list1D
|
||||
# slotValue = e.g. "terminator" in: play <movie> terminator </movie>
|
||||
# slotTag = e.g. "<movie>" or "</movie>" in: play <movie> terminator </movie>
|
||||
# slotName = e.g. "movie" in: play <movie> terminator </movie>
|
||||
# slot = e.g. "<movie> terminator </movie>" in: play <movie> terminator </movie>
|
||||
|
||||
import cv2, copy, textwrap
|
||||
from PIL import Image, ImageFont, ImageDraw
|
||||
from PIL.ExifTags import TAGS
|
||||
|
||||
def makeDirectory(directory):
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
def getFilesInDirectory(directory, postfix = ""):
|
||||
fileNames = [s for s in os.listdir(directory) if not os.path.isdir(directory+"/"+s)]
|
||||
if not postfix or postfix == "":
|
||||
return fileNames
|
||||
else:
|
||||
return [s for s in fileNames if s.lower().endswith(postfix)]
|
||||
|
||||
def readFile(inputFile):
|
||||
#reading as binary, to avoid problems with end-of-text characters
|
||||
#note that readlines() does not remove the line ending characters
|
||||
with open(inputFile,'rb') as f:
|
||||
lines = f.readlines()
|
||||
return [removeLineEndCharacters(s) for s in lines]
|
||||
|
||||
def readTable(inputFile, delimiter='\t', columnsToKeep=None):
|
||||
lines = readFile(inputFile);
|
||||
if columnsToKeep != None:
|
||||
header = lines[0].split(delimiter)
|
||||
columnsToKeepIndices = listFindItems(header, columnsToKeep)
|
||||
else:
|
||||
columnsToKeepIndices = None;
|
||||
return splitStrings(lines, delimiter, columnsToKeepIndices)
|
||||
|
||||
def getColumn(table, columnIndex):
|
||||
column = [];
|
||||
for row in table:
|
||||
column.append(row[columnIndex])
|
||||
return column
|
||||
|
||||
def deleteFile(filePath):
|
||||
if os.path.exists(filePath):
|
||||
os.remove(filePath)
|
||||
|
||||
def writeFile(outputFile, lines):
|
||||
with open(outputFile,'w') as f:
|
||||
for line in lines:
|
||||
f.write("%s\n" % line)
|
||||
|
||||
def writeTable(outputFile, table):
|
||||
lines = tableToList1D(table)
|
||||
writeFile(outputFile, lines)
|
||||
|
||||
def deleteFile(filePath):
|
||||
if os.path.exists(filePath):
|
||||
os.remove(filePath)
|
||||
|
||||
def deleteAllFilesInDirectory(directory, fileEndswithString, boPromptUser = False):
|
||||
if boPromptUser:
|
||||
userInput = raw_input('--> INPUT: Press "y" to delete files in directory ' + directory + ": ")
|
||||
if not (userInput.lower() == 'y' or userInput.lower() == 'yes'):
|
||||
print ("User input is %s: exiting now." % userInput)
|
||||
exit()
|
||||
for filename in getFilesInDirectory(directory):
|
||||
if fileEndswithString == None or filename.lower().endswith(fileEndswithString):
|
||||
deleteFile(directory + "/" + filename)
|
||||
|
||||
def removeLineEndCharacters(line):
|
||||
if line.endswith(b'\r\n'):
|
||||
return line[:-2]
|
||||
elif line.endswith(b'\n'):
|
||||
return line[:-1]
|
||||
else:
|
||||
return line
|
||||
|
||||
def splitString(string, delimiter='\t', columnsToKeepIndices=None):
|
||||
if string == None:
|
||||
return None
|
||||
items = string.decode('utf-8').split(delimiter)
|
||||
if columnsToKeepIndices != None:
|
||||
items = getColumns([items], columnsToKeepIndices)
|
||||
items = items[0]
|
||||
return items;
|
||||
|
||||
def splitStrings(strings, delimiter, columnsToKeepIndices=None):
|
||||
table = [splitString(string, delimiter, columnsToKeepIndices) for string in strings]
|
||||
return table;
|
||||
|
||||
def find(list1D, func):
|
||||
return [index for (index,item) in enumerate(list1D) if func(item)]
|
||||
|
||||
def tableToList1D(table, delimiter='\t'):
|
||||
return [delimiter.join([str(s) for s in row]) for row in table]
|
||||
|
||||
def sortDictionary(dictionary, sortIndex=0, reverseSort=False):
|
||||
return sorted(dictionary.items(), key=lambda x: x[sortIndex], reverse=reverseSort)
|
||||
|
||||
def imread(imgPath, boThrowErrorIfExifRotationTagSet = True):
|
||||
if not os.path.exists(imgPath):
|
||||
"ERROR: image path does not exist."
|
||||
error
|
||||
|
||||
rotation = rotationFromExifTag(imgPath)
|
||||
if boThrowErrorIfExifRotationTagSet and rotation != 0:
|
||||
print ("Error: exif roation tag set, image needs to be rotated by %d degrees." % rotation)
|
||||
img = cv2.imread(imgPath)
|
||||
if img is None:
|
||||
print ("ERROR: cannot load image " + imgPath)
|
||||
error
|
||||
if rotation != 0:
|
||||
img = imrotate(img, -90).copy() # got this error occassionally without copy "TypeError: Layout of the output array img is incompatible with cv::Mat"
|
||||
return img
|
||||
|
||||
def rotationFromExifTag(imgPath):
|
||||
TAGSinverted = {v: k for k, v in TAGS.items()}
|
||||
orientationExifId = TAGSinverted['Orientation']
|
||||
try:
|
||||
imageExifTags = Image.open(imgPath)._getexif()
|
||||
except:
|
||||
imageExifTags = None
|
||||
|
||||
# rotate the image if orientation exif tag is present
|
||||
rotation = 0
|
||||
if imageExifTags != None and orientationExifId != None and orientationExifId in imageExifTags:
|
||||
orientation = imageExifTags[orientationExifId]
|
||||
# print ("orientation = " + str(imageExifTags[orientationExifId]))
|
||||
if orientation == 1 or orientation == 0:
|
||||
rotation = 0 # no need to do anything
|
||||
elif orientation == 6:
|
||||
rotation = -90
|
||||
elif orientation == 8:
|
||||
rotation = 90
|
||||
else:
|
||||
print ("ERROR: orientation = " + str(orientation) + " not_supported!")
|
||||
error
|
||||
return rotation
|
||||
|
||||
def imwrite(img, imgPath):
|
||||
cv2.imwrite(imgPath, img)
|
||||
|
||||
def imresize(img, scale, interpolation = cv2.INTER_LINEAR):
|
||||
return cv2.resize(img, (0,0), fx=scale, fy=scale, interpolation=interpolation)
|
||||
|
||||
def imresizeMaxDim(img, maxDim, boUpscale = False, interpolation = cv2.INTER_LINEAR):
|
||||
scale = 1.0 * maxDim / max(img.shape[:2])
|
||||
if scale < 1 or boUpscale:
|
||||
img = imresize(img, scale, interpolation)
|
||||
else:
|
||||
scale = 1.0
|
||||
return img, scale
|
||||
|
||||
def imWidth(input):
|
||||
return imWidthHeight(input)[0]
|
||||
|
||||
def imHeight(input):
|
||||
return imWidthHeight(input)[1]
|
||||
|
||||
def imWidthHeight(input):
|
||||
width, height = Image.open(input).size #this does not load the full image
|
||||
return width,height
|
||||
|
||||
def imArrayWidth(input):
|
||||
return imArrayWidthHeight(input)[0]
|
||||
|
||||
def imArrayHeight(input):
|
||||
return imArrayWidthHeight(input)[1]
|
||||
|
||||
def imArrayWidthHeight(input):
|
||||
width = input.shape[1]
|
||||
height = input.shape[0]
|
||||
return width,height
|
||||
|
||||
def imshow(img, waitDuration=0, maxDim = None, windowName = 'img'):
|
||||
if isinstance(img, str): #test if 'img' is a string
|
||||
img = cv2.imread(img)
|
||||
if maxDim is not None:
|
||||
scaleVal = 1.0 * maxDim / max(img.shape[:2])
|
||||
if scaleVal < 1:
|
||||
img = imresize(img, scaleVal)
|
||||
cv2.imshow(windowName, img)
|
||||
cv2.waitKey(waitDuration)
|
||||
|
||||
def drawRectangles(img, rects, color = (0, 255, 0), thickness = 2):
|
||||
for rect in rects:
|
||||
pt1 = tuple(ToIntegers(rect[0:2]))
|
||||
pt2 = tuple(ToIntegers(rect[2:]))
|
||||
cv2.rectangle(img, pt1, pt2, color, thickness)
|
||||
|
||||
def drawCrossbar(img, pt):
|
||||
(x,y) = pt
|
||||
cv2.rectangle(img, (0, y), (x, y), (255, 255, 0), 1)
|
||||
cv2.rectangle(img, (x, 0), (x, y), (255, 255, 0), 1)
|
||||
cv2.rectangle(img, (img.shape[1],y), (x, y), (255, 255, 0), 1)
|
||||
cv2.rectangle(img, (x, img.shape[0]), (x, y), (255, 255, 0), 1)
|
||||
|
||||
def ptClip(pt, maxWidth, maxHeight):
|
||||
pt = list(pt)
|
||||
pt[0] = max(pt[0], 0)
|
||||
pt[1] = max(pt[1], 0)
|
||||
pt[0] = min(pt[0], maxWidth)
|
||||
pt[1] = min(pt[1], maxHeight)
|
||||
return pt
|
||||
|
||||
def drawText(img, pt, text, textWidth=None, color = (255,255,255), colorBackground = None, font = ImageFont.truetype("arial.ttf", 16)):
|
||||
pilImg = imconvertCv2Pil(img)
|
||||
pilImg = pilDrawText(pilImg, pt, text, textWidth, color, colorBackground, font)
|
||||
return imconvertPil2Cv(pilImg)
|
||||
|
||||
def pilDrawText(pilImg, pt, text, textWidth=None, color = (255,255,255), colorBackground = None, font = ImageFont.truetype("arial.ttf", 16)):
|
||||
textY = pt[1]
|
||||
draw = ImageDraw.Draw(pilImg)
|
||||
if textWidth == None:
|
||||
lines = [text]
|
||||
else:
|
||||
lines = textwrap.wrap(text, width=textWidth)
|
||||
for line in lines:
|
||||
width, height = font.getsize(line)
|
||||
if colorBackground != None:
|
||||
draw.rectangle((pt[0], pt[1], pt[0] + width, pt[1] + height), fill=tuple(colorBackground[::-1]))
|
||||
draw.text(pt, line, fill = tuple(color), font = font)
|
||||
textY += height
|
||||
return pilImg
|
||||
|
||||
def getColorsPalette():
|
||||
colors = [[255,0,0], [0,255,0], [0,0,255], [255,255,0], [255,0,255]]
|
||||
for i in range(5):
|
||||
for dim in range(0,3):
|
||||
for s in (0.25, 0.5, 0.75):
|
||||
if colors[i][dim] != 0:
|
||||
newColor = copy.deepcopy(colors[i])
|
||||
newColor[dim] = int(round(newColor[dim] * s))
|
||||
colors.append(newColor)
|
||||
return colors
|
||||
|
||||
def imconvertPil2Cv(pilImg):
|
||||
rgb = pilImg.convert('RGB')
|
||||
return np.array(rgb).copy()[:, :, ::-1]
|
||||
|
||||
def imconvertCv2Pil(img):
|
||||
cv2_im = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
|
||||
return Image.fromarray(cv2_im)
|
||||
|
||||
def ToIntegers(list1D):
|
||||
return [int(float(x)) for x in list1D]
|
||||
|
||||
def softmax(vec):
|
||||
expVec = np.exp(vec)
|
||||
# TODO: check numerical stability
|
||||
if max(expVec) == np.inf:
|
||||
outVec = np.zeros(len(expVec))
|
||||
outVec[expVec == np.inf] = vec[expVec == np.inf]
|
||||
outVec = outVec / np.sum(outVec)
|
||||
else:
|
||||
outVec = expVec / np.sum(expVec)
|
||||
return outVec
|
||||
|
||||
def softmax2D(w):
|
||||
e = np.exp(w)
|
||||
dist = e / np.sum(e, axis=1)[:, np.newaxis]
|
||||
return dist
|
||||
|
||||
def getDictionary(keys, values, boConvertValueToInt = True):
|
||||
dictionary = {}
|
||||
for key,value in zip(keys, values):
|
||||
if (boConvertValueToInt):
|
||||
value = int(value)
|
||||
dictionary[key] = value
|
||||
return dictionary
|
||||
|
||||
class Bbox:
|
||||
MAX_VALID_DIM = 100000
|
||||
left = top = right = bottom = None
|
||||
|
||||
def __init__(self, left, top, right, bottom):
|
||||
self.left = int(round(float(left)))
|
||||
self.top = int(round(float(top)))
|
||||
self.right = int(round(float(right)))
|
||||
self.bottom = int(round(float(bottom)))
|
||||
self.standardize()
|
||||
|
||||
def __str__(self):
|
||||
return ("Bbox object: left = {0}, top = {1}, right = {2}, bottom = {3}".format(self.left, self.top, self.right, self.bottom))
|
||||
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
def rect(self):
|
||||
return [self.left, self.top, self.right, self.bottom]
|
||||
|
||||
def max(self):
|
||||
return max([self.left, self.top, self.right, self.bottom])
|
||||
|
||||
def min(self):
|
||||
return min([self.left, self.top, self.right, self.bottom])
|
||||
|
||||
def width(self):
|
||||
width = self.right - self.left + 1
|
||||
assert(width>=0)
|
||||
return width
|
||||
|
||||
def height(self):
|
||||
height = self.bottom - self.top + 1
|
||||
assert(height>=0)
|
||||
return height
|
||||
|
||||
def surfaceArea(self):
|
||||
return self.width() * self.height()
|
||||
|
||||
def getOverlapBbox(self, bbox):
|
||||
left1, top1, right1, bottom1 = self.rect()
|
||||
left2, top2, right2, bottom2 = bbox.rect()
|
||||
overlapLeft = max(left1, left2)
|
||||
overlapTop = max(top1, top2)
|
||||
overlapRight = min(right1, right2)
|
||||
overlapBottom = min(bottom1, bottom2)
|
||||
if (overlapLeft>overlapRight) or (overlapTop>overlapBottom):
|
||||
return None
|
||||
else:
|
||||
return Bbox(overlapLeft, overlapTop, overlapRight, overlapBottom)
|
||||
|
||||
def standardize(self): #NOTE: every setter method should call standardize
|
||||
leftNew = min(self.left, self.right)
|
||||
topNew = min(self.top, self.bottom)
|
||||
rightNew = max(self.left, self.right)
|
||||
bottomNew = max(self.top, self.bottom)
|
||||
self.left = leftNew
|
||||
self.top = topNew
|
||||
self.right = rightNew
|
||||
self.bottom = bottomNew
|
||||
|
||||
def crop(self, maxWidth, maxHeight):
|
||||
leftNew = min(max(self.left, 0), maxWidth)
|
||||
topNew = min(max(self.top, 0), maxHeight)
|
||||
rightNew = min(max(self.right, 0), maxWidth)
|
||||
bottomNew = min(max(self.bottom, 0), maxHeight)
|
||||
return Bbox(leftNew, topNew, rightNew, bottomNew)
|
||||
|
||||
def isValid(self):
|
||||
if self.left>=self.right or self.top>=self.bottom:
|
||||
return False
|
||||
if min(self.rect()) < -self.MAX_VALID_DIM or max(self.rect()) > self.MAX_VALID_DIM:
|
||||
return False
|
||||
return True
|
||||
|
||||
def getEnclosingBbox(pts):
|
||||
left = top = float('inf')
|
||||
right = bottom = float('-inf')
|
||||
for pt in pts:
|
||||
left = min(left, pt[0])
|
||||
top = min(top, pt[1])
|
||||
right = max(right, pt[0])
|
||||
bottom = max(bottom, pt[1])
|
||||
return Bbox(left, top, right, bottom)
|
||||
|
||||
def bboxComputeOverlapVoc(bbox1, bbox2):
|
||||
surfaceRect1 = bbox1.surfaceArea()
|
||||
surfaceRect2 = bbox2.surfaceArea()
|
||||
overlapBbox = bbox1.getOverlapBbox(bbox2)
|
||||
if overlapBbox == None:
|
||||
return 0
|
||||
else:
|
||||
surfaceOverlap = overlapBbox.surfaceArea()
|
||||
overlap = max(0, 1.0 * surfaceOverlap / (surfaceRect1 + surfaceRect2 - surfaceOverlap))
|
||||
assert (overlap >= 0 and overlap <= 1)
|
||||
return overlap
|
||||
|
||||
def computeAveragePrecision(recalls, precisions, use_07_metric=False):
|
||||
""" ap = voc_ap(recalls, precisions, [use_07_metric])
|
||||
Compute VOC AP given precision and recall.
|
||||
If use_07_metric is true, uses the
|
||||
VOC 07 11 point method (default:False).
|
||||
"""
|
||||
if use_07_metric:
|
||||
# 11 point metric
|
||||
ap = 0.
|
||||
for t in np.arange(0., 1.1, 0.1):
|
||||
if np.sum(recalls >= t) == 0:
|
||||
p = 0
|
||||
else:
|
||||
p = np.max(precisions[recalls >= t])
|
||||
ap = ap + p / 11.
|
||||
else:
|
||||
# correct AP calculation
|
||||
# first append sentinel values at the end
|
||||
mrecalls = np.concatenate(([0.], recalls, [1.]))
|
||||
mprecisions = np.concatenate(([0.], precisions, [0.]))
|
||||
|
||||
# compute the precision envelope
|
||||
for i in range(mprecisions.size - 1, 0, -1):
|
||||
mprecisions[i - 1] = np.maximum(mprecisions[i - 1], mprecisions[i])
|
||||
|
||||
# to calculate area under PR curve, look for points
|
||||
# where X axis (recall) changes value
|
||||
i = np.where(mrecalls[1:] != mrecalls[:-1])[0]
|
||||
|
||||
# and sum (\Delta recall) * prec
|
||||
ap = np.sum((mrecalls[i + 1] - mrecalls[i]) * mprecisions[i + 1])
|
||||
return ap
|
|
@ -0,0 +1,9 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
from .imdb import imdb
|
||||
from .pascal_voc import pascal_voc
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
import os
|
||||
import os.path as osp
|
||||
import PIL
|
||||
import numpy as np
|
||||
import scipy.sparse
|
||||
from builtins import range
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] < 3:
|
||||
from utils2_win64.cython_bbox import bbox_overlaps
|
||||
else:
|
||||
from .utils3_win64.cython_bbox import bbox_overlaps
|
||||
|
||||
class imdb(object):
|
||||
"""Image database."""
|
||||
|
||||
def __init__(self, name):
|
||||
self._name = name
|
||||
self._num_classes = 0
|
||||
self._classes = []
|
||||
self._image_index = []
|
||||
self._obj_proposer = 'selective_search'
|
||||
self._roidb = None
|
||||
self._roidb_handler = self.default_roidb
|
||||
# Use this dict for storing dataset specific config options
|
||||
self.config = {}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def num_classes(self):
|
||||
return len(self._classes)
|
||||
|
||||
@property
|
||||
def classes(self):
|
||||
return self._classes
|
||||
|
||||
@property
|
||||
def image_index(self):
|
||||
return self._image_index
|
||||
|
||||
@property
|
||||
def roidb_handler(self):
|
||||
return self._roidb_handler
|
||||
|
||||
@roidb_handler.setter
|
||||
def roidb_handler(self, val):
|
||||
self._roidb_handler = val
|
||||
|
||||
@property
|
||||
def roidb(self):
|
||||
# A roidb is a list of dictionaries, each with the following keys:
|
||||
# boxes
|
||||
# gt_overlaps
|
||||
# gt_classes
|
||||
# flipped
|
||||
if self._roidb is not None:
|
||||
return self._roidb
|
||||
self._roidb = self.roidb_handler()
|
||||
return self._roidb
|
||||
|
||||
# @property
|
||||
# def cache_path(self):
|
||||
# cache_path = osp.abspath(osp.join(datasets.ROOT_DIR, 'data', 'cache'))
|
||||
# print cache_path
|
||||
# if not os.path.exists(cache_path):
|
||||
# os.makedirs(cache_path)
|
||||
# return cache_path
|
||||
|
||||
@property
|
||||
def num_images(self):
|
||||
return len(self.image_index)
|
||||
|
||||
def image_path_at(self, i):
|
||||
raise NotImplementedError
|
||||
|
||||
def default_roidb(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def evaluate_detections(self, all_boxes, output_dir=None):
|
||||
"""
|
||||
all_boxes is a list of length number-of-classes.
|
||||
Each list element is a list of length number-of-images.
|
||||
Each of those list elements is either an empty list []
|
||||
or a numpy array of detection.
|
||||
|
||||
all_boxes[class][image] = [] or np.array of shape #dets x 5
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def append_flipped_images(self):
|
||||
num_images = self.num_images
|
||||
widths = [PIL.Image.open(self.image_path_at(i)).size[0]
|
||||
for i in range(num_images)]
|
||||
for i in range(num_images):
|
||||
boxes = self.roidb[i]['boxes'].copy()
|
||||
oldx1 = boxes[:, 0].copy()
|
||||
oldx2 = boxes[:, 2].copy()
|
||||
boxes[:, 0] = widths[i] - oldx2 - 1
|
||||
boxes[:, 2] = widths[i] - oldx1 - 1
|
||||
assert (boxes[:, 2] >= boxes[:, 0]).all()
|
||||
entry = {'boxes' : boxes,
|
||||
'gt_overlaps' : self.roidb[i]['gt_overlaps'],
|
||||
'gt_classes' : self.roidb[i]['gt_classes'],
|
||||
'flipped' : True}
|
||||
self.roidb.append(entry)
|
||||
self._image_index = self._image_index * 2
|
||||
|
||||
def evaluate_recall(self, candidate_boxes, ar_thresh=0.5):
|
||||
# Record max overlap value for each gt box
|
||||
# Return vector of overlap values
|
||||
gt_overlaps = np.zeros(0)
|
||||
for i in range(self.num_images):
|
||||
gt_inds = np.where(self.roidb[i]['gt_classes'] > 0)[0]
|
||||
gt_boxes = self.roidb[i]['boxes'][gt_inds, :]
|
||||
|
||||
boxes = candidate_boxes[i]
|
||||
if boxes.shape[0] == 0:
|
||||
continue
|
||||
overlaps = bbox_overlaps(boxes.astype(np.float),
|
||||
gt_boxes.astype(np.float))
|
||||
|
||||
# gt_overlaps = np.hstack((gt_overlaps, overlaps.max(axis=0)))
|
||||
_gt_overlaps = np.zeros((gt_boxes.shape[0]))
|
||||
for j in range(gt_boxes.shape[0]):
|
||||
argmax_overlaps = overlaps.argmax(axis=0)
|
||||
max_overlaps = overlaps.max(axis=0)
|
||||
gt_ind = max_overlaps.argmax()
|
||||
gt_ovr = max_overlaps.max()
|
||||
assert(gt_ovr >= 0)
|
||||
box_ind = argmax_overlaps[gt_ind]
|
||||
_gt_overlaps[j] = overlaps[box_ind, gt_ind]
|
||||
assert(_gt_overlaps[j] == gt_ovr)
|
||||
overlaps[box_ind, :] = -1
|
||||
overlaps[:, gt_ind] = -1
|
||||
|
||||
gt_overlaps = np.hstack((gt_overlaps, _gt_overlaps))
|
||||
|
||||
num_pos = gt_overlaps.size
|
||||
gt_overlaps = np.sort(gt_overlaps)
|
||||
step = 0.001
|
||||
thresholds = np.minimum(np.arange(0.5, 1.0 + step, step), 1.0)
|
||||
recalls = np.zeros_like(thresholds)
|
||||
for i, t in enumerate(thresholds):
|
||||
recalls[i] = (gt_overlaps >= t).sum() / float(num_pos)
|
||||
ar = 2 * np.trapz(recalls, thresholds)
|
||||
|
||||
return ar, gt_overlaps, recalls, thresholds
|
||||
|
||||
def create_roidb_from_box_list(self, box_list, gt_roidb):
|
||||
assert len(box_list) == self.num_images, \
|
||||
'Number of boxes must match number of ground-truth images'
|
||||
roidb = []
|
||||
for i in range(self.num_images):
|
||||
boxes = box_list[i]
|
||||
num_boxes = boxes.shape[0]
|
||||
overlaps = np.zeros((num_boxes, self.num_classes), dtype=np.float32)
|
||||
|
||||
if gt_roidb and gt_roidb[i]:
|
||||
gt_boxes = gt_roidb[i]['boxes']
|
||||
gt_classes = gt_roidb[i]['gt_classes']
|
||||
if len(gt_classes) > 0: #for pascal every image has at least one annotated object. This is not the case however if including negative images
|
||||
gt_overlaps = bbox_overlaps(boxes.astype(np.float),
|
||||
gt_boxes.astype(np.float))
|
||||
|
||||
argmaxes = gt_overlaps.argmax(axis=1)
|
||||
maxes = gt_overlaps.max(axis=1)
|
||||
I = np.where(maxes > 0)[0]
|
||||
overlaps[I, gt_classes[argmaxes[I]]] = maxes[I]
|
||||
|
||||
overlaps = scipy.sparse.csr_matrix(overlaps)
|
||||
roidb.append({'boxes' : boxes,
|
||||
'gt_classes' : np.zeros((num_boxes,),
|
||||
dtype=np.int32),
|
||||
'gt_overlaps' : overlaps,
|
||||
'flipped' : False})
|
||||
return roidb
|
||||
|
||||
@staticmethod
|
||||
def merge_roidbs(a, b):
|
||||
assert len(a) == len(b)
|
||||
for i in range(len(a)):
|
||||
if a[i]: #if image has at least one annotated object
|
||||
a[i]['boxes'] = np.vstack((a[i]['boxes'], b[i]['boxes']))
|
||||
a[i]['gt_classes'] = np.hstack((a[i]['gt_classes'],
|
||||
b[i]['gt_classes']))
|
||||
a[i]['gt_overlaps'] = scipy.sparse.vstack([a[i]['gt_overlaps'],
|
||||
b[i]['gt_overlaps']])
|
||||
else:
|
||||
a[i] = b[i]
|
||||
return a
|
||||
|
||||
def competition_mode(self, on):
|
||||
"""Turn competition mode on or off."""
|
||||
pass
|
|
@ -0,0 +1,37 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
import numpy as np
|
||||
|
||||
def nms(dets, thresh):
|
||||
x1 = dets[:, 0]
|
||||
y1 = dets[:, 1]
|
||||
x2 = dets[:, 2]
|
||||
y2 = dets[:, 3]
|
||||
scores = dets[:, 4]
|
||||
|
||||
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
|
||||
order = scores.argsort()[::-1]
|
||||
|
||||
keep = []
|
||||
while order.size > 0:
|
||||
i = order[0]
|
||||
keep.append(i)
|
||||
xx1 = np.maximum(x1[i], x1[order[1:]])
|
||||
yy1 = np.maximum(y1[i], y1[order[1:]])
|
||||
xx2 = np.minimum(x2[i], x2[order[1:]])
|
||||
yy2 = np.minimum(y2[i], y2[order[1:]])
|
||||
|
||||
w = np.maximum(0.0, xx2 - xx1 + 1)
|
||||
h = np.maximum(0.0, yy2 - yy1 + 1)
|
||||
inter = w * h
|
||||
ovr = inter / (areas[i] + areas[order[1:]] - inter)
|
||||
|
||||
inds = np.where(ovr <= thresh)[0]
|
||||
order = order[inds + 1]
|
||||
|
||||
return keep
|
|
@ -0,0 +1,363 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
from __future__ import print_function
|
||||
import os, pdb
|
||||
import xml.dom.minidom as minidom
|
||||
import numpy as np
|
||||
import scipy.sparse
|
||||
import scipy.io as sio
|
||||
import pickle as cp
|
||||
import subprocess
|
||||
from .imdb import imdb
|
||||
from .voc_eval import voc_eval
|
||||
#from fastRCNN.imdb import imdb
|
||||
#from fastRCNN.voc_eval import voc_eval
|
||||
|
||||
class pascal_voc(imdb):
|
||||
def __init__(self, image_set, year, classes, maxNrRois, cacheDir, devkit_path=None):
|
||||
imdb.__init__(self, 'voc_' + year + '_' + image_set)
|
||||
self._year = year
|
||||
self._image_set = image_set
|
||||
self._maxNrRois = maxNrRois
|
||||
self._ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
|
||||
self._cacheDir = cacheDir
|
||||
self._devkit_path = self._get_default_path() if devkit_path is None \
|
||||
else os.path.join(devkit_path, 'VOCdevkit')
|
||||
self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year)
|
||||
self._classes = classes
|
||||
#('__background__', # always index 0
|
||||
# 'aeroplane', 'bicycle', 'bird', 'boat',
|
||||
# 'bottle', 'bus', 'car', 'cat', 'chair',
|
||||
# 'cow', 'diningtable', 'dog', 'horse',
|
||||
# 'motorbike', 'person', 'pottedplant',
|
||||
# 'sheep', 'sofa', 'train', 'tvmonitor')
|
||||
self._class_to_ind = dict(zip(self.classes, range(self.num_classes)))
|
||||
self._image_ext = '.jpg'
|
||||
self._image_index = self._load_image_set_index()
|
||||
# Default to roidb handler
|
||||
self._roidb_handler = self.selective_search_roidb
|
||||
|
||||
# PASCAL specific config options
|
||||
self.config = {'cleanup' : True,
|
||||
'use_salt' : True,
|
||||
'top_k' : 2000}
|
||||
|
||||
assert os.path.exists(self._devkit_path), \
|
||||
'VOCdevkit path does not exist: {}'.format(self._devkit_path)
|
||||
assert os.path.exists(self._data_path), \
|
||||
'Path does not exist: {}'.format(self._data_path)
|
||||
|
||||
@property
|
||||
def cache_path(self):
|
||||
cache_path = self._cacheDir
|
||||
#cache_path = osp.abspath(osp.join(datasets.ROOT_DIR, 'data', 'cache'))
|
||||
if not os.path.exists(cache_path):
|
||||
os.makedirs(cache_path)
|
||||
return cache_path
|
||||
|
||||
def image_path_at(self, i):
|
||||
"""
|
||||
Return the absolute path to image i in the image sequence.
|
||||
"""
|
||||
return self.image_path_from_index(self._image_index[i])
|
||||
|
||||
def image_path_from_index(self, index):
|
||||
"""
|
||||
Construct an image path from the image's "index" identifier.
|
||||
"""
|
||||
image_path = os.path.join(self._data_path, 'JPEGImages',
|
||||
index + self._image_ext)
|
||||
assert os.path.exists(image_path), \
|
||||
'Path does not exist: {}'.format(image_path)
|
||||
return image_path
|
||||
|
||||
def _load_image_set_index(self):
|
||||
"""
|
||||
Load the indexes listed in this dataset's image set file.
|
||||
"""
|
||||
# Example path to image set file:
|
||||
# self._devkit_path + /VOCdevkit/VOC2007/ImageSets/Main/val.txt
|
||||
image_set_file = os.path.join(self._data_path, 'ImageSets', 'Main',
|
||||
self._image_set + '.txt')
|
||||
assert os.path.exists(image_set_file), \
|
||||
'Path does not exist: {}'.format(image_set_file)
|
||||
with open(image_set_file) as f:
|
||||
image_index = [x.strip() for x in f.readlines()]
|
||||
return image_index
|
||||
|
||||
def _get_default_path(self):
|
||||
"""
|
||||
Return the default path where PASCAL VOC is expected to be installed.
|
||||
"""
|
||||
return os.path.join(self._ROOT_DIR, 'data', 'pascalVoc', 'VOCdevkit')
|
||||
|
||||
def gt_roidb(self):
|
||||
"""
|
||||
Return the database of ground-truth regions of interest.
|
||||
|
||||
This function loads/saves from/to a cache file to speed up future calls.
|
||||
"""
|
||||
cache_file = os.path.join(self.cache_path, self.name + '_gt_roidb.pkl')
|
||||
if os.path.exists(cache_file):
|
||||
with open(cache_file, 'rb') as fid:
|
||||
roidb = cp.load(fid)
|
||||
print ('{} gt roidb loaded from {}'.format(self.name, cache_file))
|
||||
return roidb
|
||||
|
||||
gt_roidb = [self._load_pascal_annotation(index)
|
||||
for index in self.image_index]
|
||||
with open(cache_file, 'wb') as fid:
|
||||
cp.dump(gt_roidb, fid, cp.HIGHEST_PROTOCOL)
|
||||
print ('wrote gt roidb to {}'.format(cache_file))
|
||||
|
||||
return gt_roidb
|
||||
|
||||
def selective_search_roidb(self):
|
||||
"""
|
||||
Return the database of selective search regions of interest.
|
||||
Ground-truth ROIs are also included.
|
||||
|
||||
This function loads/saves from/to a cache file to speed up future calls.
|
||||
"""
|
||||
cache_file = os.path.join(self.cache_path,
|
||||
self.name + '_selective_search_roidb.pkl')
|
||||
|
||||
if os.path.exists(cache_file):
|
||||
with open(cache_file, 'rb') as fid:
|
||||
roidb = cp.load(fid, encoding='latin1')
|
||||
print ('{} ss roidb loaded from {}'.format(self.name, cache_file))
|
||||
return roidb
|
||||
|
||||
if int(self._year) == 2007 or not self._image_set.startswith('test'):
|
||||
gt_roidb = self.gt_roidb()
|
||||
ss_roidb = self._load_selective_search_roidb(gt_roidb)
|
||||
roidb = imdb.merge_roidbs(gt_roidb, ss_roidb)
|
||||
else:
|
||||
roidb = self._load_selective_search_roidb(None)
|
||||
|
||||
# Keep max of e.g. 2000 rois
|
||||
if type(self._maxNrRois) == int:
|
||||
print ("Only keep the first %d ROIs..." % self._maxNrRois)
|
||||
for i in range(self.num_images):
|
||||
gt_overlaps = roidb[i]['gt_overlaps']
|
||||
gt_overlaps = gt_overlaps.todense()[:self._maxNrRois]
|
||||
gt_overlaps = scipy.sparse.csr_matrix(gt_overlaps)
|
||||
roidb[i]['boxes'] = roidb[i]['boxes'][:self._maxNrRois, :]
|
||||
roidb[i]['gt_classes'] = roidb[i]['gt_classes'][:self._maxNrRois]
|
||||
roidb[i]['gt_overlaps'] = roidb[i]['gt_overlaps'] = gt_overlaps
|
||||
|
||||
with open(cache_file, 'wb') as fid:
|
||||
cp.dump(roidb, fid, cp.HIGHEST_PROTOCOL)
|
||||
print ('wrote ss roidb to {}'.format(cache_file))
|
||||
|
||||
return roidb
|
||||
|
||||
def _load_selective_search_roidb(self, gt_roidb):
|
||||
filename = os.path.abspath(os.path.join(self._devkit_path, '..',
|
||||
'selective_search_data',
|
||||
self.name + '.mat'))
|
||||
assert os.path.exists(filename), \
|
||||
'Selective search data not found at: {}'.format(filename)
|
||||
raw_data = sio.loadmat(filename)['boxes'].ravel()
|
||||
|
||||
box_list = []
|
||||
for i in range(raw_data.shape[0]):
|
||||
box_list.append(raw_data[i][:, (1, 0, 3, 2)] - 1)
|
||||
|
||||
return self.create_roidb_from_box_list(box_list, gt_roidb)
|
||||
|
||||
def selective_search_IJCV_roidb(self):
|
||||
"""
|
||||
Return the database of selective search regions of interest.
|
||||
Ground-truth ROIs are also included.
|
||||
|
||||
This function loads/saves from/to a cache file to speed up future calls.
|
||||
"""
|
||||
cache_file = os.path.join(self.cache_path,
|
||||
'{:s}_selective_search_IJCV_top_{:d}_roidb.pkl'.
|
||||
format(self.name, self.config['top_k']))
|
||||
|
||||
if os.path.exists(cache_file):
|
||||
with open(cache_file, 'rb') as fid:
|
||||
roidb = cp.load(fid)
|
||||
print ('{} ss roidb loaded from {}'.format(self.name, cache_file))
|
||||
return roidb
|
||||
|
||||
gt_roidb = self.gt_roidb()
|
||||
ss_roidb = self._load_selective_search_IJCV_roidb(gt_roidb)
|
||||
roidb = imdb.merge_roidbs(gt_roidb, ss_roidb)
|
||||
with open(cache_file, 'wb') as fid:
|
||||
cp.dump(roidb, fid, cp.HIGHEST_PROTOCOL)
|
||||
print ('wrote ss roidb to {}'.format(cache_file))
|
||||
|
||||
return roidb
|
||||
|
||||
def _load_selective_search_IJCV_roidb(self, gt_roidb):
|
||||
IJCV_path = os.path.abspath(os.path.join(self.cache_path, '..',
|
||||
'selective_search_IJCV_data',
|
||||
'voc_' + self._year))
|
||||
assert os.path.exists(IJCV_path), \
|
||||
'Selective search IJCV data not found at: {}'.format(IJCV_path)
|
||||
|
||||
top_k = self.config['top_k']
|
||||
box_list = []
|
||||
for i in range(self.num_images):
|
||||
filename = os.path.join(IJCV_path, self.image_index[i] + '.mat')
|
||||
raw_data = sio.loadmat(filename)
|
||||
box_list.append((raw_data['boxes'][:top_k, :]-1).astype(np.uint16))
|
||||
|
||||
return self.create_roidb_from_box_list(box_list, gt_roidb)
|
||||
|
||||
def _load_pascal_annotation(self, index):
|
||||
"""
|
||||
Load image and bounding boxes info from XML file in the PASCAL VOC
|
||||
format.
|
||||
"""
|
||||
filename = os.path.join(self._data_path, 'Annotations', index + '.xml')
|
||||
# print ('Loading: {}'.format(filename))
|
||||
def get_data_from_tag(node, tag):
|
||||
return node.getElementsByTagName(tag)[0].childNodes[0].data
|
||||
|
||||
with open(filename) as f:
|
||||
data = minidom.parseString(f.read())
|
||||
|
||||
objs = data.getElementsByTagName('object')
|
||||
num_objs = len(objs)
|
||||
|
||||
boxes = np.zeros((num_objs, 4), dtype=np.uint16)
|
||||
gt_classes = np.zeros((num_objs), dtype=np.int32)
|
||||
overlaps = np.zeros((num_objs, self.num_classes), dtype=np.float32)
|
||||
|
||||
# Load object bounding boxes into a data frame.
|
||||
for ix, obj in enumerate(objs):
|
||||
# Make pixel indexes 0-based
|
||||
x1 = float(get_data_from_tag(obj, 'xmin')) - 1
|
||||
y1 = float(get_data_from_tag(obj, 'ymin')) - 1
|
||||
x2 = float(get_data_from_tag(obj, 'xmax')) - 1
|
||||
y2 = float(get_data_from_tag(obj, 'ymax')) - 1
|
||||
cls = self._class_to_ind[
|
||||
str(get_data_from_tag(obj, "name")).lower().strip()]
|
||||
boxes[ix, :] = [x1, y1, x2, y2]
|
||||
gt_classes[ix] = cls
|
||||
overlaps[ix, cls] = 1.0
|
||||
|
||||
overlaps = scipy.sparse.csr_matrix(overlaps)
|
||||
|
||||
return {'boxes' : boxes,
|
||||
'gt_classes': gt_classes,
|
||||
'gt_overlaps' : overlaps,
|
||||
'flipped' : False}
|
||||
|
||||
def _write_voc_results_file(self, all_boxes, output_dir):
|
||||
comp_id = 'comp4'
|
||||
if self.config['use_salt']:
|
||||
comp_id += '-{}'.format(os.getpid())
|
||||
|
||||
for cls_ind, cls in enumerate(self.classes):
|
||||
if cls == '__background__':
|
||||
continue
|
||||
print ('Writing {} VOC results file'.format(cls))
|
||||
filename = self._get_voc_results_file_template(output_dir).format(cls)
|
||||
with open(filename, 'wt') as f:
|
||||
for im_ind, index in enumerate(self.image_index):
|
||||
dets = all_boxes[cls_ind][im_ind]
|
||||
if dets == []:
|
||||
continue
|
||||
# the VOCdevkit expects 1-based indices
|
||||
for k in range(dets.shape[0]):
|
||||
f.write('{:s} {:.3f} {:.1f} {:.1f} {:.1f} {:.1f}\n'.
|
||||
format(index, dets[k, -1],
|
||||
dets[k, 0] + 1, dets[k, 1] + 1,
|
||||
dets[k, 2] + 1, dets[k, 3] + 1))
|
||||
return comp_id
|
||||
|
||||
def evaluate_detections(self, all_boxes, output_dir, boUsePythonImpl = True, use_07_metric = False):
|
||||
self._write_voc_results_file(all_boxes, output_dir)
|
||||
if not boUsePythonImpl:
|
||||
self._do_matlab_eval(comp_id, output_dir)
|
||||
else:
|
||||
self._do_python_eval(output_dir, use_07_metric)
|
||||
|
||||
def _do_matlab_eval(self, comp_id, output_dir='output'):
|
||||
rm_results = self.config['cleanup']
|
||||
|
||||
path = os.path.join(os.path.dirname(__file__),
|
||||
'VOCdevkit-matlab-wrapper')
|
||||
cmd = 'cd {} && '.format(path)
|
||||
cmd += '{:s} -nodisplay -nodesktop '.format(datasets.MATLAB)
|
||||
cmd += '-r "dbstop if error; '
|
||||
cmd += 'voc_eval(\'{:s}\',\'{:s}\',\'{:s}\',\'{:s}\',{:d}); quit;"' \
|
||||
.format(self._devkit_path, comp_id,
|
||||
self._image_set, output_dir, int(rm_results))
|
||||
print('Running:\n{}'.format(cmd))
|
||||
status = subprocess.call(cmd, shell=True)
|
||||
|
||||
def competition_mode(self, on):
|
||||
if on:
|
||||
self.config['use_salt'] = False
|
||||
self.config['cleanup'] = False
|
||||
else:
|
||||
self.config['use_salt'] = True
|
||||
self.config['cleanup'] = True
|
||||
|
||||
#########################################################################
|
||||
# Python evaluation functions (copied from faster-RCNN)
|
||||
##########################################################################
|
||||
def _get_voc_results_file_template(self, evalDir):
|
||||
if not os.path.exists(evalDir):
|
||||
os.makedirs(evalDir)
|
||||
filename = self._image_set + '_{:s}.txt'
|
||||
return os.path.join(evalDir, filename)
|
||||
|
||||
def _do_python_eval(self, output_dir='output', use_07_metric=None):
|
||||
annopath = os.path.join(self._devkit_path, 'VOC' + self._year, 'Annotations', '{}.xml')
|
||||
imagesetfile = os.path.join(
|
||||
self._devkit_path,
|
||||
'VOC' + self._year,
|
||||
'ImageSets',
|
||||
'Main',
|
||||
self._image_set + '.txt')
|
||||
aps = []
|
||||
# The PASCAL VOC metric changed in 2010
|
||||
if use_07_metric == None:
|
||||
use_07_metric = True if int(self._year) < 2010 else False
|
||||
|
||||
print ('VOC07 metric? ' + ('Yes' if use_07_metric else 'No'))
|
||||
if not os.path.isdir(output_dir):
|
||||
os.mkdir(output_dir)
|
||||
for i, cls in enumerate(self._classes):
|
||||
if cls == '__background__':
|
||||
continue
|
||||
filename = self._get_voc_results_file_template(output_dir).format(cls)
|
||||
|
||||
rec, prec, ap = voc_eval(
|
||||
filename, annopath, imagesetfile, cls, cachedir = output_dir, ovthresh=0.5,
|
||||
use_07_metric=use_07_metric)
|
||||
aps += [ap]
|
||||
print('AP for {} = {:.4f}'.format(cls, ap))
|
||||
with open(os.path.join(output_dir, cls + '_pr.pkl'), 'wb') as f:
|
||||
cp.dump({'rec': rec, 'prec': prec, 'ap': ap}, f)
|
||||
print('Mean AP = {:.4f}'.format(np.mean(aps)))
|
||||
# print('~~~~~~~~')
|
||||
# print('Results:')
|
||||
# for ap in aps:
|
||||
# print('{:.3f}'.format(ap))
|
||||
# print('{:.3f}'.format(np.mean(aps)))
|
||||
# print('~~~~~~~~')
|
||||
# print('')
|
||||
print('--------------------------------------------------------------')
|
||||
print('Results computed with the **unofficial** Python eval code.')
|
||||
print('Results should be very close to the official MATLAB eval code.')
|
||||
print('Recompute with `./tools/reval.py --matlab ...` for your paper.')
|
||||
print('-- Thanks, The Management')
|
||||
print('--------------------------------------------------------------')
|
||||
|
||||
if __name__ == '__main__':
|
||||
d = datasets.pascal_voc('trainval', '2007')
|
||||
res = d.roidb
|
||||
from IPython import embed; embed()
|
|
@ -0,0 +1,346 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
"""Test a Fast R-CNN network on an imdb (image database)."""
|
||||
|
||||
#from config import cfg #, get_output_dir
|
||||
#from blob import im_list_to_blob
|
||||
from __future__ import print_function
|
||||
import os, sys, cv2, numpy as np, pickle as cp, heapq
|
||||
from .nms import nms as nmsPython
|
||||
if sys.version_info[0] < 3:
|
||||
from utils2_win64.cython_nms import nms
|
||||
else:
|
||||
from .utils3_win64.cython_nms import nms
|
||||
from .timer import Timer
|
||||
from cntk_helpers import im_detect, apply_nms
|
||||
from builtins import range
|
||||
|
||||
|
||||
def _get_image_blob(im):
|
||||
"""Converts an image into a network input.
|
||||
|
||||
Arguments:
|
||||
im (ndarray): a color image in BGR order
|
||||
|
||||
Returns:
|
||||
blob (ndarray): a data blob holding an image pyramid
|
||||
im_scale_factors (list): list of image scales (relative to im) used
|
||||
in the image pyramid
|
||||
"""
|
||||
im_orig = im.astype(np.float32, copy=True)
|
||||
im_orig -= cfg.PIXEL_MEANS
|
||||
|
||||
im_shape = im_orig.shape
|
||||
im_size_min = np.min(im_shape[0:2])
|
||||
im_size_max = np.max(im_shape[0:2])
|
||||
|
||||
processed_ims = []
|
||||
im_scale_factors = []
|
||||
|
||||
for target_size in cfg.TEST.SCALES:
|
||||
im_scale = float(target_size) / float(im_size_min)
|
||||
# Prevent the biggest axis from being more than MAX_SIZE
|
||||
if np.round(im_scale * im_size_max) > cfg.TEST.MAX_SIZE:
|
||||
im_scale = float(cfg.TEST.MAX_SIZE) / float(im_size_max)
|
||||
im = cv2.resize(im_orig, None, None, fx=im_scale, fy=im_scale,
|
||||
interpolation=cv2.INTER_LINEAR)
|
||||
im_scale_factors.append(im_scale)
|
||||
processed_ims.append(im)
|
||||
|
||||
# Create a blob to hold the input images
|
||||
blob = im_list_to_blob(processed_ims)
|
||||
|
||||
return blob, np.array(im_scale_factors)
|
||||
|
||||
def _get_rois_blob(im_rois, im_scale_factors):
|
||||
"""Converts RoIs into network inputs.
|
||||
|
||||
Arguments:
|
||||
im_rois (ndarray): R x 4 matrix of RoIs in original image coordinates
|
||||
im_scale_factors (list): scale factors as returned by _get_image_blob
|
||||
|
||||
Returns:
|
||||
blob (ndarray): R x 5 matrix of RoIs in the image pyramid
|
||||
"""
|
||||
rois, levels = _project_im_rois(im_rois, im_scale_factors)
|
||||
rois_blob = np.hstack((levels, rois))
|
||||
return rois_blob.astype(np.float32, copy=False)
|
||||
|
||||
def _project_im_rois(im_rois, scales):
|
||||
"""Project image RoIs into the image pyramid built by _get_image_blob.
|
||||
|
||||
Arguments:
|
||||
im_rois (ndarray): R x 4 matrix of RoIs in original image coordinates
|
||||
scales (list): scale factors as returned by _get_image_blob
|
||||
|
||||
Returns:
|
||||
rois (ndarray): R x 4 matrix of projected RoI coordinates
|
||||
levels (list): image pyramid levels used by each projected RoI
|
||||
"""
|
||||
im_rois = im_rois.astype(np.float, copy=False)
|
||||
|
||||
if len(scales) > 1:
|
||||
widths = im_rois[:, 2] - im_rois[:, 0] + 1
|
||||
heights = im_rois[:, 3] - im_rois[:, 1] + 1
|
||||
|
||||
areas = widths * heights
|
||||
scaled_areas = areas[:, np.newaxis] * (scales[np.newaxis, :] ** 2)
|
||||
diff_areas = np.abs(scaled_areas - 224 * 224)
|
||||
levels = diff_areas.argmin(axis=1)[:, np.newaxis]
|
||||
else:
|
||||
levels = np.zeros((im_rois.shape[0], 1), dtype=np.int)
|
||||
|
||||
rois = im_rois * scales[levels]
|
||||
|
||||
return rois, levels
|
||||
|
||||
def _get_blobs(im, rois):
|
||||
"""Convert an image and RoIs within that image into network inputs."""
|
||||
blobs = {'data' : None, 'rois' : None}
|
||||
blobs['data'], im_scale_factors = _get_image_blob(im)
|
||||
blobs['rois'] = _get_rois_blob(rois, im_scale_factors)
|
||||
return blobs, im_scale_factors
|
||||
|
||||
def _bbox_pred(boxes, box_deltas):
|
||||
"""Transform the set of class-agnostic boxes into class-specific boxes
|
||||
by applying the predicted offsets (box_deltas)
|
||||
"""
|
||||
if boxes.shape[0] == 0:
|
||||
return np.zeros((0, box_deltas.shape[1]))
|
||||
|
||||
boxes = boxes.astype(np.float, copy=False)
|
||||
widths = boxes[:, 2] - boxes[:, 0] + cfg.EPS
|
||||
heights = boxes[:, 3] - boxes[:, 1] + cfg.EPS
|
||||
ctr_x = boxes[:, 0] + 0.5 * widths
|
||||
ctr_y = boxes[:, 1] + 0.5 * heights
|
||||
|
||||
dx = box_deltas[:, 0::4]
|
||||
dy = box_deltas[:, 1::4]
|
||||
dw = box_deltas[:, 2::4]
|
||||
dh = box_deltas[:, 3::4]
|
||||
|
||||
pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis]
|
||||
pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis]
|
||||
pred_w = np.exp(dw) * widths[:, np.newaxis]
|
||||
pred_h = np.exp(dh) * heights[:, np.newaxis]
|
||||
|
||||
pred_boxes = np.zeros(box_deltas.shape)
|
||||
# x1
|
||||
pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w
|
||||
# y1
|
||||
pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h
|
||||
# x2
|
||||
pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w
|
||||
# y2
|
||||
pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h
|
||||
|
||||
return pred_boxes
|
||||
|
||||
def _clip_boxes(boxes, im_shape):
|
||||
"""Clip boxes to image boundaries."""
|
||||
# x1 >= 0
|
||||
boxes[:, 0::4] = np.maximum(boxes[:, 0::4], 0)
|
||||
# y1 >= 0
|
||||
boxes[:, 1::4] = np.maximum(boxes[:, 1::4], 0)
|
||||
# x2 < im_shape[1]
|
||||
boxes[:, 2::4] = np.minimum(boxes[:, 2::4], im_shape[1] - 1)
|
||||
# y2 < im_shape[0]
|
||||
boxes[:, 3::4] = np.minimum(boxes[:, 3::4], im_shape[0] - 1)
|
||||
return boxes
|
||||
|
||||
# def im_detect(net, im, boxes):
|
||||
# """Detect object classes in an image given object proposals.
|
||||
#
|
||||
# Arguments:
|
||||
# net (caffe.Net): Fast R-CNN network to use
|
||||
# im (ndarray): color image to test (in BGR order)
|
||||
# boxes (ndarray): R x 4 array of object proposals
|
||||
#
|
||||
# Returns:
|
||||
# scores (ndarray): R x K array of object class scores (K includes
|
||||
# background as object category 0)
|
||||
# boxes (ndarray): R x (4*K) array of predicted bounding boxes
|
||||
# """
|
||||
# blobs, unused_im_scale_factors = _get_blobs(im, boxes)
|
||||
#
|
||||
# # When mapping from image ROIs to feature map ROIs, there's some aliasing
|
||||
# # (some distinct image ROIs get mapped to the same feature ROI).
|
||||
# # Here, we identify duplicate feature ROIs, so we only compute features
|
||||
# # on the unique subset.
|
||||
# if cfg.DEDUP_BOXES > 0:
|
||||
# v = np.array([1, 1e3, 1e6, 1e9, 1e12])
|
||||
# hashes = np.round(blobs['rois'] * cfg.DEDUP_BOXES).dot(v)
|
||||
# _, index, inv_index = np.unique(hashes, return_index=True,
|
||||
# return_inverse=True)
|
||||
# blobs['rois'] = blobs['rois'][index, :]
|
||||
# boxes = boxes[index, :]
|
||||
#
|
||||
# # reshape network inputs
|
||||
# net.blobs['data'].reshape(*(blobs['data'].shape))
|
||||
# net.blobs['rois'].reshape(*(blobs['rois'].shape))
|
||||
# blobs_out = net.forward(data=blobs['data'].astype(np.float32, copy=False),
|
||||
# rois=blobs['rois'].astype(np.float32, copy=False))
|
||||
# if cfg.TEST.SVM:
|
||||
# # use the raw scores before softmax under the assumption they
|
||||
# # were trained as linear SVMs
|
||||
# scores = net.blobs['cls_score'].data
|
||||
# else:
|
||||
# # use softmax estimated probabilities
|
||||
# scores = blobs_out['cls_prob']
|
||||
#
|
||||
# if cfg.TEST.BBOX_REG:
|
||||
# # Apply bounding-box regression deltas
|
||||
# box_deltas = blobs_out['bbox_pred']
|
||||
# pred_boxes = _bbox_pred(boxes, box_deltas)
|
||||
# pred_boxes = _clip_boxes(pred_boxes, im.shape)
|
||||
# else:
|
||||
# # Simply repeat the boxes, once for each class
|
||||
# pred_boxes = np.tile(boxes, (1, scores.shape[1]))
|
||||
#
|
||||
# if cfg.DEDUP_BOXES > 0:
|
||||
# # Map scores and predictions back to the original set of boxes
|
||||
# scores = scores[inv_index, :]
|
||||
# pred_boxes = pred_boxes[inv_index, :]
|
||||
#
|
||||
# return scores, pred_boxes
|
||||
|
||||
def vis_detections(im, class_name, dets, thresh=0.3):
|
||||
"""Visual debugging of detections."""
|
||||
import matplotlib.pyplot as plt
|
||||
im = im[:, :, (2, 1, 0)]
|
||||
for i in range(np.minimum(10, dets.shape[0])):
|
||||
bbox = dets[i, :4]
|
||||
score = dets[i, -1]
|
||||
if score > thresh:
|
||||
plt.cla()
|
||||
plt.imshow(im)
|
||||
plt.gca().add_patch(
|
||||
plt.Rectangle((bbox[0], bbox[1]),
|
||||
bbox[2] - bbox[0],
|
||||
bbox[3] - bbox[1], fill=False,
|
||||
edgecolor='g', linewidth=3)
|
||||
)
|
||||
plt.title('{} {:.3f}'.format(class_name, score))
|
||||
plt.show()
|
||||
|
||||
def test_net(net, imdb, output_dir, feature_scale, classifier = 'svm', nmsThreshold = 0.3,
|
||||
boUsePythonImpl = False, boThresholdDetections = True, boApplyNms = True):
|
||||
"""Test a Fast R-CNN network on an image database."""
|
||||
num_images = len(imdb.image_index)
|
||||
# heuristic: keep an average of 40 detections per class per images prior
|
||||
# to NMS
|
||||
max_per_set = 40 * num_images
|
||||
# heuristic: keep at most 100 detection per class per image prior to NMS
|
||||
max_per_image = 100
|
||||
# detection thresold for each class (this is adaptively set based on the
|
||||
# max_per_set constraint)
|
||||
thresh = -np.inf * np.ones(imdb.num_classes)
|
||||
# top_scores will hold one minheap of scores per class (used to enforce
|
||||
# the max_per_set constraint)
|
||||
top_scores = [[] for _ in range(imdb.num_classes)]
|
||||
# all detections are collected into:
|
||||
# all_boxes[cls][image] = N x 5 array of detections in
|
||||
# (x1, y1, x2, y2, score)
|
||||
all_boxes = [[[] for _ in range(num_images)]
|
||||
for _ in range(imdb.num_classes)]
|
||||
|
||||
#output_dir = get_output_dir(imdb, net)
|
||||
|
||||
# timers
|
||||
_t = {'im_detect' : Timer(), 'misc' : Timer()}
|
||||
roidb = imdb.roidb
|
||||
|
||||
if not boThresholdDetections:
|
||||
for i in range(num_images):
|
||||
if i % 1000 == 0:
|
||||
print (" Processing image {} of {}..".format(i, num_images))
|
||||
scores, _, _ = im_detect(net, i, roidb[i]['boxes'], feature_scale=feature_scale, classifier=classifier)
|
||||
|
||||
for j in range(1, imdb.num_classes):
|
||||
inds = np.where(roidb[i]['gt_classes'] == 0)[0]
|
||||
cls_scores = scores[inds, j]
|
||||
cls_boxes = roidb[i]['boxes'][inds]
|
||||
all_boxes[j][i] = \
|
||||
np.hstack((cls_boxes, cls_scores[:, np.newaxis])) \
|
||||
.astype(np.float32, copy=False)
|
||||
|
||||
else:
|
||||
for i in range(num_images):
|
||||
if i % 1000 == 0:
|
||||
print (" Processing image {} of {}..".format(i, num_images))
|
||||
#im = cv2.imread(imdb.image_path_at(i))
|
||||
#_t['im_detect'].tic()
|
||||
scores, _, _ = im_detect(net, i, roidb[i]['boxes'], feature_scale = feature_scale, classifier = classifier)
|
||||
#_t['im_detect'].toc()
|
||||
|
||||
_t['misc'].tic()
|
||||
for j in range(1, imdb.num_classes):
|
||||
inds = np.where((scores[:, j] > thresh[j]) &
|
||||
(roidb[i]['gt_classes'] == 0))[0]
|
||||
cls_scores = scores[inds, j]
|
||||
|
||||
# cls_boxes = boxes[inds, j * 4:(j + 1) * 4]
|
||||
boxes = roidb[i]['boxes']
|
||||
cls_boxes = boxes[inds]
|
||||
|
||||
top_inds = np.argsort(-cls_scores)[:max_per_image]
|
||||
cls_scores = cls_scores[top_inds]
|
||||
cls_boxes = cls_boxes[top_inds, :]
|
||||
# push new scores onto the minheap
|
||||
for val in cls_scores:
|
||||
heapq.heappush(top_scores[j], val)
|
||||
# if we've collected more than the max number of detection,
|
||||
# then pop items off the minheap and update the class threshold
|
||||
if len(top_scores[j]) > max_per_set:
|
||||
while len(top_scores[j]) > max_per_set:
|
||||
heapq.heappop(top_scores[j])
|
||||
thresh[j] = top_scores[j][0]
|
||||
|
||||
all_boxes[j][i] = \
|
||||
np.hstack((cls_boxes, cls_scores[:, np.newaxis])) \
|
||||
.astype(np.float32, copy=False)
|
||||
|
||||
#visualize rois
|
||||
if False:
|
||||
im = cv2.imread(imdb.image_path_at(i))
|
||||
if boUsePythonImpl:
|
||||
keep = nmsPython.nms(all_boxes[j][i], 0.3)
|
||||
else:
|
||||
keep = nms(all_boxes[j][i], 0.3)
|
||||
vis_detections(im, imdb.classes[j], all_boxes[j][i][keep, :])
|
||||
_t['misc'].toc()
|
||||
|
||||
# print ('im_detect: {:d}/{:d} {:.3f}s {:.3f}s' \
|
||||
# .format(i + 1, num_images, _t['im_detect'].average_time,
|
||||
# _t['misc'].average_time))
|
||||
|
||||
#keep only the boxes with highest score for each class
|
||||
# shape of all_boxes: e.g. 21 classes x 4952 images x 58 rois x 5 coord+score
|
||||
for j in range(1, imdb.num_classes):
|
||||
for i in range(num_images):
|
||||
inds = np.where(all_boxes[j][i][:, -1] > thresh[j])[0]
|
||||
if len(inds) == 0:
|
||||
all_boxes[j][i] = []
|
||||
else:
|
||||
all_boxes[j][i] = all_boxes[j][i][inds, :]
|
||||
|
||||
if output_dir:
|
||||
det_file = os.path.join(output_dir, 'detections.pkl')
|
||||
with open(det_file, 'wb') as f:
|
||||
cp.dump(all_boxes, f, cp.HIGHEST_PROTOCOL)
|
||||
|
||||
if boApplyNms:
|
||||
print ("Number of rois before non-maxima surpression: %d" % sum([len(all_boxes[i][j]) for i in range(imdb.num_classes) for j in range(imdb.num_images)]))
|
||||
nms_dets,_ = apply_nms(all_boxes, nmsThreshold, boUsePythonImpl)
|
||||
print ("Number of rois after non-maxima surpression: %d" % sum([len(nms_dets[i][j]) for i in range(imdb.num_classes) for j in range(imdb.num_images)]))
|
||||
else:
|
||||
print ("Skipping non-maxima surpression")
|
||||
nms_dets = all_boxes
|
||||
|
||||
print ('Evaluating detections')
|
||||
imdb.evaluate_detections(nms_dets, output_dir)
|
|
@ -0,0 +1,32 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
import time
|
||||
|
||||
class Timer(object):
|
||||
"""A simple timer."""
|
||||
def __init__(self):
|
||||
self.total_time = 0.
|
||||
self.calls = 0
|
||||
self.start_time = 0.
|
||||
self.diff = 0.
|
||||
self.average_time = 0.
|
||||
|
||||
def tic(self):
|
||||
# using time.time instead of time.clock because time time.clock
|
||||
# does not normalize for multithreading
|
||||
self.start_time = time.time()
|
||||
|
||||
def toc(self, average=True):
|
||||
self.diff = time.time() - self.start_time
|
||||
self.total_time += self.diff
|
||||
self.calls += 1
|
||||
self.average_time = self.total_time / self.calls
|
||||
if average:
|
||||
return self.average_time
|
||||
else:
|
||||
return self.diff
|
|
@ -0,0 +1,315 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
"""
|
||||
Train post-hoc SVMs using the algorithm and hyper-parameters from
|
||||
traditional R-CNN.
|
||||
"""
|
||||
|
||||
from timer import Timer
|
||||
from sklearn import svm
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
||||
#################################################
|
||||
# Slightly modified SVM training functions
|
||||
#################################################
|
||||
class SVMTrainer(object):
|
||||
"""
|
||||
Trains post-hoc detection SVMs for all classes using the algorithm
|
||||
and hyper-parameters of traditional R-CNN.
|
||||
"""
|
||||
|
||||
def __init__(self, net, imdb, im_detect, svmWeightsPath, svmBiasPath, svmFeatScalePath,
|
||||
svm_C, svm_B, svm_nrEpochs, svm_retrainLimit, svm_evictThreshold, svm_posWeight,
|
||||
svm_targetNorm, svm_penality, svm_loss, svm_rngSeed):
|
||||
self.net = net
|
||||
self.imdb = imdb
|
||||
self.im_detect = im_detect
|
||||
self.svm_nrEpochs = svm_nrEpochs
|
||||
self.svm_targetNorm = svm_targetNorm
|
||||
self.svmWeightsPath = svmWeightsPath
|
||||
self.svmBiasPath = svmBiasPath
|
||||
self.svmFeatScalePath = svmFeatScalePath
|
||||
self.layer = 'fc7'
|
||||
self.hard_thresh = -1.0001
|
||||
self.neg_iou_thresh = 0.3
|
||||
dim = net.params['cls_score'][0].data.shape[1]
|
||||
self.feature_scale = self._get_feature_scale()
|
||||
print('Feature dim: {}'.format(dim))
|
||||
print('Feature scale: {:.3f}'.format(self.feature_scale))
|
||||
self.trainers = [SVMClassTrainer(cls, dim, self.feature_scale, svm_C, svm_B, svm_posWeight, svm_penality, svm_loss,
|
||||
svm_rngSeed, svm_retrainLimit, svm_evictThreshold) for cls in imdb.classes]
|
||||
|
||||
|
||||
def _get_feature_scale(self, num_images=100):
|
||||
_t = Timer()
|
||||
roidb = self.imdb.roidb
|
||||
total_norm = 0.0
|
||||
total_sum = 0.0
|
||||
count = 0.0
|
||||
num_images = min(num_images, self.imdb.num_images)
|
||||
inds = np.random.choice(range(self.imdb.num_images), size=num_images, replace=False)
|
||||
|
||||
for i_, i in enumerate(inds):
|
||||
#im = cv2.imread(self.imdb.image_path_at(i))
|
||||
#if roidb[i]['flipped']:
|
||||
# im = im[:, ::-1, :]
|
||||
#im = self.imdb.image_path_at(i)
|
||||
_t.tic()
|
||||
scores, boxes, feat = self.im_detect(self.net, i, roidb[i]['boxes'], boReturnClassifierScore = False)
|
||||
_t.toc()
|
||||
#feat = self.net.blobs[self.layer].data
|
||||
total_norm += np.sqrt((feat ** 2).sum(axis=1)).sum()
|
||||
total_sum += 1.0 * sum(sum(feat)) / len(feat)
|
||||
count += feat.shape[0]
|
||||
print('{}/{}: avg feature norm: {:.3f}, average value: {:.3f}'.format(i_ + 1, num_images,
|
||||
total_norm / count, total_sum / count))
|
||||
|
||||
return self.svm_targetNorm * 1.0 / (total_norm / count)
|
||||
|
||||
def _get_pos_counts(self):
|
||||
counts = np.zeros((len(self.imdb.classes)), dtype=np.int)
|
||||
roidb = self.imdb.roidb
|
||||
for i in range(len(roidb)):
|
||||
for j in range(1, self.imdb.num_classes):
|
||||
I = np.where(roidb[i]['gt_classes'] == j)[0]
|
||||
counts[j] += len(I)
|
||||
|
||||
for j in range(1, self.imdb.num_classes):
|
||||
print('class {:s} has {:d} positives'.
|
||||
format(self.imdb.classes[j], counts[j]))
|
||||
|
||||
return counts
|
||||
|
||||
def get_pos_examples(self):
|
||||
counts = self._get_pos_counts()
|
||||
for i in range(len(counts)):
|
||||
self.trainers[i].alloc_pos(counts[i])
|
||||
|
||||
_t = Timer()
|
||||
roidb = self.imdb.roidb
|
||||
num_images = len(roidb)
|
||||
for i in range(num_images):
|
||||
#im = cv2.imread(self.imdb.image_path_at(i))
|
||||
#if roidb[i]['flipped']:
|
||||
# im = im[:, ::-1, :]
|
||||
#im = self.imdb.image_path_at(i)
|
||||
gt_inds = np.where(roidb[i]['gt_classes'] > 0)[0]
|
||||
gt_boxes = roidb[i]['boxes'][gt_inds]
|
||||
_t.tic()
|
||||
scores, boxes, feat = self.im_detect(self.net, i, gt_boxes, self.feature_scale, gt_inds, boReturnClassifierScore = False)
|
||||
_t.toc()
|
||||
#feat = self.net.blobs[self.layer].data
|
||||
for j in range(1, self.imdb.num_classes):
|
||||
cls_inds = np.where(roidb[i]['gt_classes'][gt_inds] == j)[0]
|
||||
if len(cls_inds) > 0:
|
||||
cls_feat = feat[cls_inds, :]
|
||||
self.trainers[j].append_pos(cls_feat)
|
||||
if i % 50 == 0:
|
||||
print 'get_pos_examples: {:d}/{:d} {:.3f}s' \
|
||||
.format(i + 1, len(roidb), _t.average_time)
|
||||
|
||||
def initialize_net(self):
|
||||
# Start all SVM parameters at zero
|
||||
self.net.params['cls_score'][0].data[...] = 0
|
||||
self.net.params['cls_score'][1].data[...] = 0
|
||||
|
||||
# Initialize SVMs in a smart way. Not doing this because its such
|
||||
# a good initialization that we might not learn something close to
|
||||
# the SVM solution.
|
||||
# # subtract background weights and biases for the foreground classes
|
||||
# w_bg = self.net.params['cls_score'][0].data[0, :]
|
||||
# b_bg = self.net.params['cls_score'][1].data[0]
|
||||
# self.net.params['cls_score'][0].data[1:, :] -= w_bg
|
||||
# self.net.params['cls_score'][1].data[1:] -= b_bg
|
||||
# # set the background weights and biases to 0 (where they shall remain)
|
||||
# self.net.params['cls_score'][0].data[0, :] = 0
|
||||
# self.net.params['cls_score'][1].data[0] = 0
|
||||
|
||||
def update_net(self, cls_ind, w, b):
|
||||
self.net.params['cls_score'][0].data[cls_ind, :] = w
|
||||
self.net.params['cls_score'][1].data[cls_ind] = b
|
||||
|
||||
def train_with_hard_negatives(self):
|
||||
_t = Timer()
|
||||
roidb = self.imdb.roidb
|
||||
num_images = len(roidb)
|
||||
|
||||
for epoch in range(0,self.svm_nrEpochs):
|
||||
|
||||
# num_images = 100
|
||||
for i in range(num_images):
|
||||
print "*** EPOCH = %d, IMAGE = %d *** " % (epoch, i)
|
||||
#im = cv2.imread(self.imdb.image_path_at(i))
|
||||
#if roidb[i]['flipped']:
|
||||
# im = im[:, ::-1, :]
|
||||
#im = self.imdb.image_path_at(i)
|
||||
_t.tic()
|
||||
scores, boxes, feat = self.im_detect(self.net, i, roidb[i]['boxes'], self.feature_scale)
|
||||
_t.toc()
|
||||
#feat = self.net.blobs[self.layer].data
|
||||
for j in range(1, self.imdb.num_classes):
|
||||
hard_inds = \
|
||||
np.where((scores[:, j] > self.hard_thresh) &
|
||||
(roidb[i]['gt_overlaps'][:, j].toarray().ravel() <
|
||||
self.neg_iou_thresh))[0]
|
||||
if len(hard_inds) > 0:
|
||||
hard_feat = feat[hard_inds, :].copy()
|
||||
new_w_b = \
|
||||
self.trainers[j].append_neg_and_retrain(feat=hard_feat)
|
||||
if new_w_b is not None:
|
||||
self.update_net(j, new_w_b[0], new_w_b[1])
|
||||
np.savetxt(self.svmWeightsPath[:-4] + "_epoch" + str(epoch) + ".txt", self.net.params['cls_score'][0].data)
|
||||
np.savetxt(self.svmBiasPath[:-4] + "_epoch" + str(epoch) + ".txt", self.net.params['cls_score'][1].data)
|
||||
np.savetxt(self.svmFeatScalePath[:-4] + "_epoch" + str(epoch) + ".txt", [self.feature_scale])
|
||||
|
||||
print(('train_with_hard_negatives: '
|
||||
'{:d}/{:d} {:.3f}s').format(i + 1, len(roidb),
|
||||
_t.average_time))
|
||||
|
||||
def train(self):
|
||||
# Initialize SVMs using
|
||||
# a. w_i = fc8_w_i - fc8_w_0
|
||||
# b. b_i = fc8_b_i - fc8_b_0
|
||||
# c. Install SVMs into net
|
||||
self.initialize_net()
|
||||
|
||||
# Pass over roidb to count num positives for each class
|
||||
# a. Pre-allocate arrays for positive feature vectors
|
||||
# Pass over roidb, computing features for positives only
|
||||
self.get_pos_examples()
|
||||
|
||||
# Pass over roidb
|
||||
# a. Compute cls_score with forward pass
|
||||
# b. For each class
|
||||
# i. Select hard negatives
|
||||
# ii. Add them to cache
|
||||
# c. For each class
|
||||
# i. If SVM retrain criteria met, update SVM
|
||||
# ii. Install new SVM into net
|
||||
self.train_with_hard_negatives()
|
||||
|
||||
# One final SVM retraining for each class
|
||||
# Install SVMs into net
|
||||
for j in range(1, self.imdb.num_classes):
|
||||
new_w_b = self.trainers[j].append_neg_and_retrain(force=True)
|
||||
self.update_net(j, new_w_b[0], new_w_b[1])
|
||||
|
||||
#save svm
|
||||
np.savetxt(self.svmWeightsPath, self.net.params['cls_score'][0].data)
|
||||
np.savetxt(self.svmBiasPath, self.net.params['cls_score'][1].data)
|
||||
np.savetxt(self.svmFeatScalePath, [self.feature_scale])
|
||||
|
||||
|
||||
class SVMClassTrainer(object):
|
||||
"""Manages post-hoc SVM training for a single object class."""
|
||||
|
||||
def __init__(self, cls, dim, feature_scale,
|
||||
C, B, pos_weight, svm_penality, svm_loss, svm_rngSeed, svm_retrainLimit, svm_evictThreshold):
|
||||
self.pos = np.zeros((0, dim), dtype=np.float32)
|
||||
self.neg = np.zeros((0, dim), dtype=np.float32)
|
||||
self.B = B
|
||||
self.C = C
|
||||
self.cls = cls
|
||||
self.pos_weight = pos_weight
|
||||
self.dim = dim
|
||||
self.feature_scale = feature_scale
|
||||
if type(pos_weight) == str: #e.g. pos_weight == 'auto'
|
||||
class_weight = pos_weight
|
||||
else:
|
||||
class_weight = {1: pos_weight, -1: 1}
|
||||
|
||||
self.svm = svm.LinearSVC(C=C, class_weight=class_weight,
|
||||
intercept_scaling=B, verbose=1,
|
||||
penalty=svm_penality, loss=svm_loss,
|
||||
random_state=svm_rngSeed, dual=True)
|
||||
|
||||
self.pos_cur = 0
|
||||
self.num_neg_added = 0
|
||||
self.retrain_limit = svm_retrainLimit
|
||||
self.evict_thresh = svm_evictThreshold
|
||||
self.loss_history = []
|
||||
|
||||
def alloc_pos(self, count):
|
||||
self.pos_cur = 0
|
||||
self.pos = np.zeros((count, self.dim), dtype=np.float32)
|
||||
|
||||
def append_pos(self, feat):
|
||||
num = feat.shape[0]
|
||||
self.pos[self.pos_cur:self.pos_cur + num, :] = feat
|
||||
self.pos_cur += num
|
||||
|
||||
def train(self):
|
||||
print('>>> Updating {} detector <<<'.format(self.cls))
|
||||
num_pos = self.pos.shape[0]
|
||||
num_neg = self.neg.shape[0]
|
||||
print('Cache holds {} pos examples and {} neg examples'.
|
||||
format(num_pos, num_neg))
|
||||
X = np.vstack((self.pos, self.neg)) * self.feature_scale
|
||||
y = np.hstack((np.ones(num_pos),
|
||||
-np.ones(num_neg)))
|
||||
self.svm.fit(X, y)
|
||||
w = self.svm.coef_
|
||||
b = self.svm.intercept_[0]
|
||||
|
||||
scores = self.svm.decision_function(X)
|
||||
pos_scores = scores[:num_pos]
|
||||
neg_scores = scores[num_pos:]
|
||||
|
||||
num_neg_wrong = sum(neg_scores > 0)
|
||||
num_pos_wrong = sum(pos_scores < 0)
|
||||
meanAcc = 0.5 * (num_pos - num_pos_wrong) / num_pos + 0.5*(num_neg - num_neg_wrong) / num_neg
|
||||
if type(self.pos_weight) == str:
|
||||
pos_loss = 0
|
||||
else:
|
||||
pos_loss = (self.C * self.pos_weight *
|
||||
np.maximum(0, 1 - pos_scores).sum())
|
||||
neg_loss = self.C * np.maximum(0, 1 + neg_scores).sum()
|
||||
reg_loss = 0.5 * np.dot(w.ravel(), w.ravel()) + 0.5 * b ** 2
|
||||
tot_loss = pos_loss + neg_loss + reg_loss
|
||||
self.loss_history.append((meanAcc, num_pos_wrong, num_pos, num_neg_wrong, num_neg, tot_loss, pos_loss, neg_loss, reg_loss))
|
||||
for i, losses in enumerate(self.loss_history):
|
||||
print((' {:4d}: meanAcc={:.3f} -- pos wrong: {:5}/{:5}; neg wrong: {:5}/{:5}; '
|
||||
' obj val: {:.3f} = {:.3f} (posUnscaled) + {:.3f} (neg) + {:.3f} (reg)').format(i, *losses))
|
||||
|
||||
# Sanity check
|
||||
|
||||
scores_ret = (
|
||||
X * 1.0 / self.feature_scale).dot(w.T * self.feature_scale) + b
|
||||
assert np.allclose(scores, scores_ret[:, 0], atol=1e-5), \
|
||||
"Scores from returned model don't match decision function"
|
||||
|
||||
return ((w * self.feature_scale, b), pos_scores, neg_scores)
|
||||
|
||||
def append_neg_and_retrain(self, feat=None, force=False):
|
||||
if feat is not None:
|
||||
num = feat.shape[0]
|
||||
self.neg = np.vstack((self.neg, feat))
|
||||
self.num_neg_added += num
|
||||
if self.num_neg_added > self.retrain_limit or force:
|
||||
self.num_neg_added = 0
|
||||
new_w_b, pos_scores, neg_scores = self.train()
|
||||
# scores = np.dot(self.neg, new_w_b[0].T) + new_w_b[1]
|
||||
# easy_inds = np.where(neg_scores < self.evict_thresh)[0]
|
||||
print(' Pruning easy negatives')
|
||||
print(' before pruning: #neg = ' + str(len(self.neg)))
|
||||
not_easy_inds = np.where(neg_scores >= self.evict_thresh)[0]
|
||||
if len(not_easy_inds) > 0:
|
||||
self.neg = self.neg[not_easy_inds, :]
|
||||
# self.neg = np.delete(self.neg, easy_inds)
|
||||
print(' after pruning: #neg = ' + str(len(self.neg)))
|
||||
print(' Cache holds {} pos examples and {} neg examples'.
|
||||
format(self.pos.shape[0], self.neg.shape[0]))
|
||||
print(' {} pos support vectors'.format((pos_scores <= 1).sum()))
|
||||
print(' {} neg support vectors'.format((neg_scores >= -1).sum()))
|
||||
return new_w_b
|
||||
else:
|
||||
return None
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,2 @@
|
|||
|
||||
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,204 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast/er R-CNN
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Bharath Hariharan
|
||||
# --------------------------------------------------------
|
||||
|
||||
from __future__ import print_function
|
||||
import xml.etree.ElementTree as ET
|
||||
import os
|
||||
import pickle as cp
|
||||
import numpy as np
|
||||
|
||||
def parse_rec(filename):
|
||||
""" Parse a PASCAL VOC xml file """
|
||||
tree = ET.parse(filename)
|
||||
objects = []
|
||||
for obj in tree.findall('object'):
|
||||
obj_struct = {}
|
||||
obj_struct['name'] = obj.find('name').text
|
||||
obj_struct['pose'] = obj.find('pose').text
|
||||
obj_struct['truncated'] = int(obj.find('truncated').text)
|
||||
obj_struct['difficult'] = int(obj.find('difficult').text)
|
||||
bbox = obj.find('bndbox')
|
||||
obj_struct['bbox'] = [int(bbox.find('xmin').text),
|
||||
int(bbox.find('ymin').text),
|
||||
int(bbox.find('xmax').text),
|
||||
int(bbox.find('ymax').text)]
|
||||
objects.append(obj_struct)
|
||||
|
||||
return objects
|
||||
|
||||
def voc_ap(rec, prec, use_07_metric=False):
|
||||
""" ap = voc_ap(rec, prec, [use_07_metric])
|
||||
Compute VOC AP given precision and recall.
|
||||
If use_07_metric is true, uses the
|
||||
VOC 07 11 point method (default:False).
|
||||
"""
|
||||
if use_07_metric:
|
||||
# 11 point metric
|
||||
ap = 0.
|
||||
for t in np.arange(0., 1.1, 0.1):
|
||||
if np.sum(rec >= t) == 0:
|
||||
p = 0
|
||||
else:
|
||||
p = np.max(prec[rec >= t])
|
||||
ap = ap + p / 11.
|
||||
else:
|
||||
# correct AP calculation
|
||||
# first append sentinel values at the end
|
||||
mrec = np.concatenate(([0.], rec, [1.]))
|
||||
mpre = np.concatenate(([0.], prec, [0.]))
|
||||
|
||||
# compute the precision envelope
|
||||
for i in range(mpre.size - 1, 0, -1):
|
||||
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
|
||||
|
||||
# to calculate area under PR curve, look for points
|
||||
# where X axis (recall) changes value
|
||||
i = np.where(mrec[1:] != mrec[:-1])[0]
|
||||
|
||||
# and sum (\Delta recall) * prec
|
||||
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
|
||||
return ap
|
||||
|
||||
def voc_eval(detpath,
|
||||
annopath,
|
||||
imagesetfile,
|
||||
classname,
|
||||
cachedir,
|
||||
ovthresh=0.5,
|
||||
use_07_metric=False):
|
||||
"""rec, prec, ap = voc_eval(detpath,
|
||||
annopath,
|
||||
imagesetfile,
|
||||
classname,
|
||||
[ovthresh],
|
||||
[use_07_metric])
|
||||
|
||||
Top level function that does the PASCAL VOC evaluation.
|
||||
|
||||
detpath: Path to detections
|
||||
detpath.format(classname) should produce the detection results file.
|
||||
annopath: Path to annotations
|
||||
annopath.format(imagename) should be the xml annotations file.
|
||||
imagesetfile: Text file containing the list of images, one image per line.
|
||||
classname: Category name (duh)
|
||||
cachedir: Directory for caching the annotations
|
||||
[ovthresh]: Overlap threshold (default = 0.5)
|
||||
[use_07_metric]: Whether to use VOC07's 11 point AP computation
|
||||
(default False)
|
||||
"""
|
||||
# assumes detections are in detpath.format(classname)
|
||||
# assumes annotations are in annopath.format(imagename)
|
||||
# assumes imagesetfile is a text file with each line an image name
|
||||
# cachedir caches the annotations in a pickle file
|
||||
|
||||
# first load gt
|
||||
if cachedir:
|
||||
if not os.path.isdir(cachedir):
|
||||
os.mkdir(cachedir)
|
||||
cachefile = os.path.join(cachedir, 'annots.pkl')
|
||||
# read list of images
|
||||
with open(imagesetfile, 'r') as f:
|
||||
lines = f.readlines()
|
||||
imagenames = [x.strip() for x in lines]
|
||||
|
||||
if not cachedir or not os.path.isfile(cachefile):
|
||||
# load annots
|
||||
recs = {}
|
||||
for i, imagename in enumerate(imagenames):
|
||||
recs[imagename] = parse_rec(annopath.format(imagename))
|
||||
if i % 1000 == 0:
|
||||
print ('Reading annotation for {:d}/{:d}'.format(
|
||||
i + 1, len(imagenames)))
|
||||
# save
|
||||
if cachedir:
|
||||
print ('Saving cached annotations to {:s}'.format(cachefile))
|
||||
with open(cachefile, 'wb') as f:
|
||||
cp.dump(recs, f)
|
||||
else:
|
||||
# load
|
||||
with open(cachefile, 'rb') as f:
|
||||
recs = cp.load(f)
|
||||
|
||||
# extract gt objects for this class
|
||||
class_recs = {}
|
||||
npos = 0
|
||||
for imagename in imagenames:
|
||||
R = [obj for obj in recs[imagename] if obj['name'] == classname]
|
||||
bbox = np.array([x['bbox'] for x in R])
|
||||
difficult = np.array([x['difficult'] for x in R]).astype(np.bool)
|
||||
det = [False] * len(R)
|
||||
npos = npos + sum(~difficult)
|
||||
class_recs[imagename] = {'bbox': bbox,
|
||||
'difficult': difficult,
|
||||
'det': det}
|
||||
|
||||
# read dets
|
||||
detfile = detpath.format(classname)
|
||||
with open(detfile, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
splitlines = [x.strip().split(' ') for x in lines]
|
||||
image_ids = [x[0] for x in splitlines]
|
||||
confidence = np.array([float(x[1]) for x in splitlines])
|
||||
BB = np.array([[float(z) for z in x[2:]] for x in splitlines])
|
||||
|
||||
# sort by confidence
|
||||
sorted_ind = np.argsort(-confidence)
|
||||
sorted_scores = np.sort(-confidence)
|
||||
|
||||
BB = BB[sorted_ind, :]
|
||||
image_ids = [image_ids[x] for x in sorted_ind]
|
||||
|
||||
# go down dets and mark TPs and FPs
|
||||
nd = len(image_ids)
|
||||
tp = np.zeros(nd)
|
||||
fp = np.zeros(nd)
|
||||
for d in range(nd):
|
||||
R = class_recs[image_ids[d]]
|
||||
bb = BB[d, :].astype(float)
|
||||
ovmax = -np.inf
|
||||
BBGT = R['bbox'].astype(float)
|
||||
|
||||
if BBGT.size > 0:
|
||||
# compute overlaps
|
||||
# intersection
|
||||
ixmin = np.maximum(BBGT[:, 0], bb[0])
|
||||
iymin = np.maximum(BBGT[:, 1], bb[1])
|
||||
ixmax = np.minimum(BBGT[:, 2], bb[2])
|
||||
iymax = np.minimum(BBGT[:, 3], bb[3])
|
||||
iw = np.maximum(ixmax - ixmin + 1., 0.)
|
||||
ih = np.maximum(iymax - iymin + 1., 0.)
|
||||
inters = iw * ih
|
||||
|
||||
# union
|
||||
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
|
||||
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
|
||||
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
|
||||
|
||||
overlaps = inters / uni
|
||||
ovmax = np.max(overlaps)
|
||||
jmax = np.argmax(overlaps)
|
||||
|
||||
if ovmax > ovthresh:
|
||||
if not R['difficult'][jmax]:
|
||||
if not R['det'][jmax]:
|
||||
tp[d] = 1.
|
||||
R['det'][jmax] = 1
|
||||
else:
|
||||
fp[d] = 1.
|
||||
else:
|
||||
fp[d] = 1.
|
||||
|
||||
# compute precision recall
|
||||
fp = np.cumsum(fp)
|
||||
tp = np.cumsum(tp)
|
||||
rec = tp / float(npos)
|
||||
# avoid divide by zero in case the first detection matches a difficult
|
||||
# ground truth
|
||||
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
|
||||
ap = voc_ap(rec, prec, use_07_metric)
|
||||
|
||||
return rec, prec, ap
|
|
@ -10,8 +10,8 @@
|
|||
# by the following layer (usually a set of pretrained fully connected layers).
|
||||
# Classification error and evaluation criterion are computed for each ROI.
|
||||
|
||||
command = Train:Test
|
||||
#command = Write
|
||||
#makeMode = false
|
||||
command = Train:WriteTest:WriteTrain
|
||||
|
||||
deviceId = "Auto"
|
||||
precision = "float"
|
||||
|
@ -22,22 +22,21 @@ rootDir = "."
|
|||
dataDir = "$rootDir$/data/"
|
||||
outputDir = "$rootDir$/Output"
|
||||
|
||||
modelPath = "$outputDir$/Fast-RCNN"
|
||||
stderr = "$outputDir$/Fast-RCNN.log"
|
||||
modelPath = "$outputDir$/Fast-RCNN.model"
|
||||
#stderr = "$outputDir$/Fast-RCNN.log"
|
||||
|
||||
ImageH = 1000
|
||||
ImageW = 1000
|
||||
ImageC = 3
|
||||
|
||||
NumLabels = 21
|
||||
NumLabels = 22
|
||||
NumTrainROIs = 200
|
||||
NumTestROIs = 2000
|
||||
|
||||
NumTrainROIs = 64
|
||||
TrainROIDim = 256 # $NumTrainROIs$ * 4
|
||||
TrainROILabelDim = 1344 # $NumTrainROIs$ * $NumLabels$
|
||||
|
||||
NumTestROIs = 200
|
||||
TestROIDim = 800
|
||||
TestROILabelDim = 4200
|
||||
TrainROIDim = 800 # $NumTrainROIs$ * 4
|
||||
TrainROILabelDim = 4400 # $NumTrainROIs$ * $NumLabels$
|
||||
TestROIDim = 4000 # $NumTestROIs$ * 4
|
||||
TestROILabelDim = 22000 # $NumTestROIs$ * $NumLabels$
|
||||
|
||||
# For training we load a pretrained AlexNet model (AlexNet.89) and clone three parts of it.
|
||||
# For the first part (up to pool1) we keep the weights fixed. The middle part contains the
|
||||
|
@ -52,22 +51,20 @@ Train = {
|
|||
|
||||
BrainScriptNetworkBuilder = {
|
||||
imageShape = $ImageH$:$ImageW$:$ImageC$ # 1000:1000:3
|
||||
labelShape = $NumLabels$:$NumTrainROIs$ # 21:64
|
||||
ROIShape = 4:$NumTrainROIs$ # 4:64
|
||||
labelShape = $NumLabels$:$NumTrainROIs$ # 21:200
|
||||
ROIShape = 4:$NumTrainROIs$ # 4:200
|
||||
|
||||
network = BS.Network.Load ("AlexNet.89")
|
||||
pool1 = BS.Network.CloneFunction(network.features, network.pool1, parameters = "constant")
|
||||
convLayers = BS.Network.CloneFunction(network.pool1, network.conv5_y)
|
||||
network = BS.Network.Load ("../../../../../PretrainedModels/AlexNet.model")
|
||||
convLayers = BS.Network.CloneFunction(network.features, network.conv5_y, parameters = "constant")
|
||||
fcLayers = BS.Network.CloneFunction(network.pool3, network.h2_d)
|
||||
|
||||
model (features, rois) = {
|
||||
featNorm = features - 114
|
||||
pool1Out = pool1 (featNorm)
|
||||
conv5Out = convLayers (pool1Out)
|
||||
roiOut = ROIPooling (conv5Out, rois, (6:6))
|
||||
convOut = convLayers (featNorm)
|
||||
roiOut = ROIPooling (convOut, rois, (6:6))
|
||||
fcOut = fcLayers (roiOut)
|
||||
W = ParameterTensor{(21:4096)}
|
||||
b = ParameterTensor{21, init = 'zero'}
|
||||
W = ParameterTensor{($NumLabels$:4096), init="glorotUniform"}
|
||||
b = ParameterTensor{$NumLabels$, init = 'zero'}
|
||||
z = W * fcOut + b
|
||||
}.z
|
||||
|
||||
|
@ -89,13 +86,14 @@ Train = {
|
|||
|
||||
SGD = {
|
||||
epochSize = 0
|
||||
minibatchSize = 2
|
||||
maxEpochs = 15
|
||||
minibatchSize = 1
|
||||
maxEpochs = 17
|
||||
|
||||
learningRatesPerSample = 0.00005
|
||||
momentumAsTimeConstant = 0*5:1024 # was: 0.9 per MB
|
||||
L2RegWeight = 0.0001
|
||||
dropoutRate = 0.5
|
||||
learningRatesPerSample=0.00001*10:0.000001*5:0.0000001
|
||||
momentumPerMB=0.9
|
||||
gradUpdateType=None
|
||||
L2RegWeight=0.0005
|
||||
dropoutRate=0.5
|
||||
|
||||
numMBsToShowResult = 50
|
||||
}
|
||||
|
@ -105,15 +103,15 @@ Train = {
|
|||
verbosity = 2
|
||||
deserializers = ({
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = "$dataDir$/tv2012pad.rois.txt"
|
||||
file = train.rois.txt
|
||||
input = { rois = { dim = $TrainROIDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = "$dataDir$/tv2012pad.roilabels.txt"
|
||||
file = train.roilabels.txt
|
||||
input = { roiLabels = { dim = $TrainROILabelDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "ImageDeserializer" ; module = "ImageReader"
|
||||
file = "$dataDir$/tv2012pad.txt"
|
||||
file = train.txt
|
||||
input = {
|
||||
features = { transforms = (
|
||||
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:
|
||||
|
@ -125,22 +123,86 @@ Train = {
|
|||
}
|
||||
}
|
||||
|
||||
# For testing we load the trained Fast-RCNN model and modify the input size,
|
||||
# such that the network accepts 200 ROIs per image. To this end we load and
|
||||
# clone the entire network and define new inputs with the desired size
|
||||
# corresponding to 200 ROIs.
|
||||
Test = {
|
||||
action = "test"
|
||||
# Write network output for entire test data set
|
||||
WriteTest = {
|
||||
action = "write"
|
||||
minibatchSize = 1
|
||||
|
||||
# use this for write action
|
||||
# action = "write"
|
||||
# outputPath = "$OutputDir$/fastrcnnNetOutput"
|
||||
outputPath=test
|
||||
|
||||
reader = {
|
||||
randomize = false
|
||||
verbosity = 2
|
||||
deserializers = ({
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = test.rois.txt
|
||||
input = { rois = { dim = $TestROIDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = test.roilabels.txt
|
||||
input = { roiLabels = { dim = $TestROILabelDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "ImageDeserializer" ; module = "ImageReader"
|
||||
file = test.txt
|
||||
input = {
|
||||
features = { transforms = (
|
||||
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:
|
||||
{ type = "Transpose" }
|
||||
)}
|
||||
ignored = {labelDim = 1000}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
# Write network output for entire train data set
|
||||
WriteTrain = {
|
||||
action = "write"
|
||||
minibatchSize = 1
|
||||
|
||||
# outputPath = "$OutputDir$/fastrcnnNetOutput"
|
||||
outputPath=train
|
||||
|
||||
reader = {
|
||||
randomize = false
|
||||
verbosity = 2
|
||||
deserializers = ({
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = train.rois.txt
|
||||
input = { rois = { dim = $TestROIDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = train.roilabels.txt
|
||||
input = { roiLabels = { dim = $TestROILabelDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "ImageDeserializer" ; module = "ImageReader"
|
||||
file = train.txt
|
||||
input = {
|
||||
features = { transforms = (
|
||||
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:
|
||||
{ type = "Transpose" }
|
||||
)}
|
||||
ignored = {labelDim = 1000}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
# For testing you can optionally load the trained Fast-RCNN model and modify the input size,
|
||||
# such that the network accepts a different number of ROIs per image, e.g. 2000. To this end we load and
|
||||
# clone the network and define new inputs with the desired size corresponding to 2000 ROIs.
|
||||
WriteTestModify = {
|
||||
action = "write"
|
||||
minibatchSize = 1
|
||||
|
||||
# outputPath = "$OutputDir$/fastrcnnNetOutput"
|
||||
outputPath=test
|
||||
|
||||
BrainScriptNetworkBuilder = {
|
||||
imageShape = $ImageH$:$ImageW$:$ImageC$ # 1000:1000:3
|
||||
labelShape = $NumLabels$:$NumTestROIs$ # 21:200
|
||||
ROIShape = 4:$NumTestROIs$ # 4:200
|
||||
labelShape = $NumLabels$:$NumTestROIs$ # 21:2000
|
||||
ROIShape = 4:$NumTestROIs$ # 4:2000
|
||||
|
||||
# load network
|
||||
network = BS.Network.Load ("$modelPath$")
|
||||
|
@ -167,15 +229,15 @@ Test = {
|
|||
verbosity = 2
|
||||
deserializers = ({
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = "$dataDir$/test2007pad_all.rois.txt"
|
||||
file = test.rois.txt
|
||||
input = { rois = { dim = $TestROIDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
|
||||
file = "$dataDir$/test2007pad_all.roilabels.txt"
|
||||
file = test.roilabels.txt
|
||||
input = { roiLabels = { dim = $TestROILabelDim$ ; format = "dense" } }
|
||||
}:{
|
||||
type = "ImageDeserializer" ; module = "ImageReader"
|
||||
file = "$dataDir$/test2007pad_all.txt"
|
||||
file = test.txt
|
||||
input = {
|
||||
features = { transforms = (
|
||||
{ type = "Scale" ; width = $ImageW$ ; height = $ImageW$ ; channels = $ImageC$ ; scaleMode = "pad" ; padValue = 114 }:
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
# --------------------------------------------------------
|
||||
# Fast R-CNN
|
||||
# Copyright (c) 2015 Microsoft
|
||||
# Licensed under The MIT License [see LICENSE for details]
|
||||
# Written by Ross Girshick
|
||||
# --------------------------------------------------------
|
||||
|
||||
from __future__ import print_function
|
||||
from builtins import range
|
||||
import sys, os
|
||||
from cntk_helpers import *
|
||||
import scipy.sparse
|
||||
import scipy.io as sio
|
||||
import pickle as cp
|
||||
import numpy as np
|
||||
import fastRCNN
|
||||
|
||||
|
||||
class imdb_data(fastRCNN.imdb):
|
||||
def __init__(self, image_set, classes, maxNrRois, imgDir, roiDir, cacheDir, boAddGroundTruthRois):
|
||||
fastRCNN.imdb.__init__(self, image_set + ".cache") #'data_' + image_set)
|
||||
self._image_set = image_set
|
||||
self._maxNrRois = maxNrRois
|
||||
self._imgDir = imgDir
|
||||
self._roiDir = roiDir
|
||||
self._cacheDir = cacheDir #cache_path
|
||||
self._imgSubdirs ={'train': ['positive', 'negative'], 'test': ['testImages']}
|
||||
self._classes = classes
|
||||
self._class_to_ind = dict(zip(self.classes, range(self.num_classes)))
|
||||
self._image_ext = '.jpg'
|
||||
self._image_index, self._image_subdirs = self._load_image_set_index()
|
||||
self._roidb_handler = self.selective_search_roidb
|
||||
self._boAddGroundTruthRois = boAddGroundTruthRois
|
||||
|
||||
|
||||
#overwrite parent definition
|
||||
@property
|
||||
def cache_path(self):
|
||||
return self._cacheDir
|
||||
|
||||
def image_path_at(self, i):
|
||||
"""
|
||||
Return the absolute path to image i in the image sequence.
|
||||
"""
|
||||
return self.image_path_from_index(self._image_subdirs[i], self._image_index[i])
|
||||
|
||||
def image_path_from_index(self, subdir, fname):
|
||||
"""
|
||||
Construct an image path from the image's "index" identifier.
|
||||
"""
|
||||
image_path = os.path.join(self._imgDir, subdir, fname)
|
||||
assert os.path.exists(image_path), \
|
||||
'Path does not exist: {}'.format(image_path)
|
||||
return image_path
|
||||
|
||||
def _load_image_set_index(self):
|
||||
"""
|
||||
Compile list of image indices and the subdirectories they are in.
|
||||
"""
|
||||
image_index = []
|
||||
image_subdirs = []
|
||||
for subdir in self._imgSubdirs[self._image_set]:
|
||||
imgFilenames = getFilesInDirectory(self._imgDir + subdir, self._image_ext)
|
||||
image_index += imgFilenames
|
||||
image_subdirs += [subdir] * len(imgFilenames)
|
||||
return image_index, image_subdirs
|
||||
|
||||
def gt_roidb(self):
|
||||
"""
|
||||
Return the database of ground-truth regions of interest.
|
||||
|
||||
This function loads/saves from/to a cache file to speed up future calls.
|
||||
"""
|
||||
cache_file = os.path.join(self.cache_path, self.name + '_gt_roidb.pkl')
|
||||
if os.path.exists(cache_file):
|
||||
with open(cache_file, 'rb') as fid:
|
||||
roidb = cp.load(fid)
|
||||
print ('{} gt roidb loaded from {}'.format(self.name, cache_file))
|
||||
return roidb
|
||||
|
||||
gt_roidb = [self._load_annotation(i) for i in range(self.num_images)]
|
||||
with open(cache_file, 'wb') as fid:
|
||||
cp.dump(gt_roidb, fid, cp.HIGHEST_PROTOCOL)
|
||||
print ('wrote gt roidb to {}'.format(cache_file))
|
||||
|
||||
return gt_roidb
|
||||
|
||||
def selective_search_roidb(self):
|
||||
"""
|
||||
Return the database of selective search regions of interest.
|
||||
Ground-truth ROIs are also included.
|
||||
|
||||
This function loads/saves from/to a cache file to speed up future calls.
|
||||
"""
|
||||
cache_file = os.path.join(self.cache_path,
|
||||
self.name + '_selective_search_roidb.pkl')
|
||||
|
||||
if os.path.exists(cache_file):
|
||||
with open(cache_file, 'rb') as fid:
|
||||
if sys.version_info[0] < 3:
|
||||
roidb = cp.load(fid)
|
||||
else:
|
||||
roidb = cp.load(fid, encoding='latin1')
|
||||
print ('{} ss roidb loaded from {}'.format(self.name, cache_file))
|
||||
return roidb
|
||||
|
||||
|
||||
gt_roidb = self.gt_roidb()
|
||||
ss_roidb = self._load_selective_search_roidb(gt_roidb)
|
||||
|
||||
#add ground truth ROIs
|
||||
if self._boAddGroundTruthRois:
|
||||
roidb = self.merge_roidbs(gt_roidb, ss_roidb)
|
||||
else:
|
||||
roidb = ss_roidb
|
||||
|
||||
#Keep max of e.g. 2000 rois
|
||||
if self._maxNrRois and self._maxNrRois > 0:
|
||||
print ("Only keeping the first %d ROIs.." % self._maxNrRois)
|
||||
for i in range(self.num_images):
|
||||
gt_overlaps = roidb[i]['gt_overlaps']
|
||||
gt_overlaps = gt_overlaps.todense()[:self._maxNrRois]
|
||||
gt_overlaps = scipy.sparse.csr_matrix(gt_overlaps)
|
||||
roidb[i]['gt_overlaps'] = gt_overlaps
|
||||
roidb[i]['boxes'] = roidb[i]['boxes'][:self._maxNrRois,:]
|
||||
roidb[i]['gt_classes'] = roidb[i]['gt_classes'][:self._maxNrRois]
|
||||
|
||||
with open(cache_file, 'wb') as fid:
|
||||
cp.dump(roidb, fid, cp.HIGHEST_PROTOCOL)
|
||||
print ('wrote ss roidb to {}'.format(cache_file))
|
||||
|
||||
return roidb
|
||||
|
||||
def _load_selective_search_roidb(self, gt_roidb):
|
||||
# box_list = nrImages x nrBoxes x 4
|
||||
box_list = []
|
||||
for imgFilename, subdir in zip(self._image_index, self._image_subdirs):
|
||||
roiPath = "{}/{}/{}.roi.txt".format(self._roiDir, subdir, imgFilename[:-4])
|
||||
assert os.path.exists(roiPath), "Error: rois file not found: " + roiPath
|
||||
rois = np.loadtxt(roiPath, np.int32)
|
||||
box_list.append(rois)
|
||||
return self.create_roidb_from_box_list(box_list, gt_roidb)
|
||||
|
||||
def _load_annotation(self, imgIndex):
|
||||
"""
|
||||
Load image and bounding boxes info from human annotations.
|
||||
"""
|
||||
#negative images do not have any ground truth annotations
|
||||
if self._image_subdirs[imgIndex].lower() == "negative":
|
||||
return None
|
||||
|
||||
imgPath = self.image_path_at(imgIndex)
|
||||
bboxesPaths = imgPath[:-4] + ".bboxes.tsv"
|
||||
labelsPaths = imgPath[:-4] + ".bboxes.labels.tsv"
|
||||
assert os.path.exists(bboxesPaths), "Error: ground truth bounding boxes file not found: " + bboxesPaths
|
||||
assert os.path.exists(labelsPaths), "Error: ground truth labels file not found: " + bboxesPaths
|
||||
bboxes = np.loadtxt(bboxesPaths, np.float32)
|
||||
labels = readFile(labelsPaths)
|
||||
|
||||
#remove boxes marked as 'undecided' or 'exclude'
|
||||
indicesToKeep = find(labels, lambda x: x!='EXCLUDE' and x!='UNDECIDED')
|
||||
bboxes = [bboxes[i] for i in indicesToKeep]
|
||||
labels = [labels[i] for i in indicesToKeep]
|
||||
|
||||
# Load object bounding boxes into a data frame.
|
||||
num_objs = len(bboxes)
|
||||
boxes = np.zeros((num_objs,4), dtype=np.uint16)
|
||||
gt_classes = np.zeros(num_objs, dtype=np.int32)
|
||||
overlaps = np.zeros((num_objs, self.num_classes), dtype=np.float32)
|
||||
for bboxIndex,(bbox,label) in enumerate(zip(bboxes,labels)):
|
||||
cls = self._class_to_ind[label.decode('utf-8')]
|
||||
boxes[bboxIndex, :] = bbox
|
||||
gt_classes[bboxIndex] = cls
|
||||
overlaps[bboxIndex, cls] = 1.0
|
||||
|
||||
overlaps = scipy.sparse.csr_matrix(overlaps)
|
||||
|
||||
return {'boxes' : boxes,
|
||||
'gt_classes': gt_classes,
|
||||
'gt_overlaps' : overlaps,
|
||||
'flipped' : False}
|
||||
|
||||
# main call to compute per-calass average precision
|
||||
# shape of all_boxes: e.g. 21 classes x 4952 images x 58 rois x 5 coords+score
|
||||
# (see also test_net() in fastRCNN\test.py)
|
||||
def evaluate_detections(self, all_boxes, output_dir, use_07_metric=False):
|
||||
aps = []
|
||||
for classIndex, className in enumerate(self._classes):
|
||||
if className != '__background__':
|
||||
rec, prec, ap = self._evaluate_detections(classIndex, all_boxes, use_07_metric = use_07_metric)
|
||||
aps += [ap]
|
||||
print('AP for {:>15} = {:.4f}'.format(className, ap))
|
||||
print('Mean AP = {:.4f}'.format(np.nanmean(aps)))
|
||||
|
||||
def _evaluate_detections(self, classIndex, all_boxes, overlapThreshold = 0.5, use_07_metric = False):
|
||||
"""
|
||||
Top level function that does the PASCAL VOC evaluation.
|
||||
|
||||
[overlapThreshold]: Overlap threshold (default = 0.5)
|
||||
[use_07_metric]: Whether to use VOC07's 11 point AP computation (default False)
|
||||
"""
|
||||
assert (len(all_boxes) == self.num_classes)
|
||||
assert (len(all_boxes[0]) == self.num_images)
|
||||
|
||||
# load ground truth annotations for this class
|
||||
gtInfos = []
|
||||
for imgIndex in range(self.num_images):
|
||||
imgPath = self.image_path_at(imgIndex)
|
||||
imgSubir = os.path.normpath(imgPath).split(os.path.sep)[-2]
|
||||
if imgSubir != 'negative':
|
||||
gtBoxes, gtLabels = readGtAnnotation(imgPath)
|
||||
gtBoxes = [box for box, label in zip(gtBoxes, gtLabels) if label.decode('utf-8') == self.classes[classIndex]]
|
||||
else:
|
||||
gtBoxes = []
|
||||
gtInfos.append({'bbox': np.array(gtBoxes),
|
||||
'difficult': [False] * len(gtBoxes),
|
||||
'det': [False] * len(gtBoxes)})
|
||||
|
||||
# parse detections for this class
|
||||
# shape of all_boxes: e.g. 21 classes x 4952 images x 58 rois x 5 coords+score
|
||||
detBboxes = []
|
||||
detImgIndices = []
|
||||
detConfidences = []
|
||||
for imgIndex in range(self.num_images):
|
||||
dets = all_boxes[classIndex][imgIndex]
|
||||
if dets != []:
|
||||
for k in range(dets.shape[0]):
|
||||
detImgIndices.append(imgIndex)
|
||||
detConfidences.append(dets[k, -1])
|
||||
# the VOCdevkit expects 1-based indices
|
||||
detBboxes.append([dets[k, 0] + 1, dets[k, 1] + 1, dets[k, 2] + 1, dets[k, 3] + 1])
|
||||
detBboxes = np.array(detBboxes)
|
||||
detConfidences = np.array(detConfidences)
|
||||
|
||||
# compute precision / recall / ap
|
||||
rec, prec, ap = self._voc_computePrecisionRecallAp(
|
||||
class_recs=gtInfos,
|
||||
confidence=detConfidences,
|
||||
image_ids=detImgIndices,
|
||||
BB=detBboxes,
|
||||
ovthresh=overlapThreshold,
|
||||
use_07_metric=use_07_metric)
|
||||
return rec, prec, ap
|
||||
|
||||
|
||||
#########################################################################
|
||||
# Python evaluation functions (copied/refactored from faster-RCNN)
|
||||
##########################################################################
|
||||
def _voc_computePrecisionRecallAp(self, class_recs, confidence, image_ids, BB, ovthresh=0.5, use_07_metric=False):
|
||||
# sort by confidence
|
||||
sorted_ind = np.argsort(-confidence)
|
||||
BB = BB[sorted_ind, :]
|
||||
image_ids = [image_ids[x] for x in sorted_ind]
|
||||
|
||||
# go down dets and mark TPs and FPs
|
||||
nd = len(image_ids)
|
||||
tp = np.zeros(nd)
|
||||
fp = np.zeros(nd)
|
||||
for d in range(nd):
|
||||
R = class_recs[image_ids[d]]
|
||||
bb = BB[d, :].astype(float)
|
||||
ovmax = -np.inf
|
||||
BBGT = R['bbox'].astype(float)
|
||||
|
||||
if BBGT.size > 0:
|
||||
# compute overlaps
|
||||
ixmin = np.maximum(BBGT[:, 0], bb[0])
|
||||
iymin = np.maximum(BBGT[:, 1], bb[1])
|
||||
ixmax = np.minimum(BBGT[:, 2], bb[2])
|
||||
iymax = np.minimum(BBGT[:, 3], bb[3])
|
||||
iw = np.maximum(ixmax - ixmin + 1., 0.)
|
||||
ih = np.maximum(iymax - iymin + 1., 0.)
|
||||
inters = iw * ih
|
||||
|
||||
# union
|
||||
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
|
||||
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
|
||||
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
|
||||
|
||||
overlaps = inters / uni
|
||||
ovmax = np.max(overlaps)
|
||||
jmax = np.argmax(overlaps)
|
||||
|
||||
if ovmax > ovthresh:
|
||||
if not R['difficult'][jmax]:
|
||||
if not R['det'][jmax]:
|
||||
tp[d] = 1.
|
||||
R['det'][jmax] = 1
|
||||
else:
|
||||
fp[d] = 1.
|
||||
else:
|
||||
fp[d] = 1.
|
||||
|
||||
# compute precision recall
|
||||
npos = sum([len(cr['bbox']) for cr in class_recs])
|
||||
fp = np.cumsum(fp)
|
||||
tp = np.cumsum(tp)
|
||||
rec = tp / float(npos)
|
||||
# avoid divide by zero in case the first detection matches a difficult
|
||||
# ground truth
|
||||
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
|
||||
ap = computeAveragePrecision(rec, prec, use_07_metric)
|
||||
return rec, prec, ap
|
|
@ -0,0 +1,40 @@
|
|||
from __future__ import print_function
|
||||
import os
|
||||
import zipfile
|
||||
import os
|
||||
import os.path
|
||||
try:
|
||||
from urllib.request import urlretrieve
|
||||
except ImportError:
|
||||
from urllib import urlretrieve
|
||||
|
||||
if __name__ == "__main__":
|
||||
directory = "./../../DataSets"
|
||||
if not os.path.exists(directory + "/Grocery"):
|
||||
filename = directory + "/Grocery.zip"
|
||||
if not os.path.exists(filename):
|
||||
url = "https://www.cntk.ai/DataSets/Grocery/Grocery.zip"
|
||||
print ('Downloading data from ' + url + '...')
|
||||
urlretrieve(url, filename)
|
||||
try:
|
||||
print ('Extracting ' + filename + '...')
|
||||
with zipfile.ZipFile(filename) as myzip:
|
||||
myzip.extractall(directory)
|
||||
finally:
|
||||
os.remove(filename)
|
||||
print ('Done.')
|
||||
else:
|
||||
print ('Data already available at ' + directory)
|
||||
|
||||
directory = "./../../PretrainedModels"
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
filename = directory + "/AlexNet.model"
|
||||
if not os.path.exists(filename):
|
||||
url = "https://www.cntk.ai/Models/AlexNet/AlexNet.model"
|
||||
print ('Downloading model from ' + url + ', may take a while...')
|
||||
urlretrieve(url, filename)
|
||||
print ('Saved model as ' + filename)
|
||||
else:
|
||||
print ('CNTK model already available at ' + filename)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
future
|
||||
Pillow
|
||||
xmltodict
|
||||
wheel
|
||||
matplotlib
|
||||
EasyDict
|
||||
numpy
|
||||
scikit-learn
|
||||
scipy
|
|
@ -0,0 +1,20 @@
|
|||
# Selective Search
|
||||
|
||||
This code is a revision of the selective search implementation at:
|
||||
https://github.com/AlpacaDB/selectivesearch, such that the code can work under Python 3 environment.
|
||||
|
||||
This file is based on or incorporates material from the projects listed below (Third Party OSS). The original copyright notice and the license under which Microsoft received such Third Party OSS, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft licenses the Third Party OSS to you under the licensing terms for the Microsoft product or service. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise.
|
||||
|
||||
`alpacadb-selectivesearch`
|
||||
Copyright (c) 2015-2016 AlpacaDB
|
||||
Copyright (c) 2016 Oussama ENNAFII
|
||||
|
||||
Provided for Informational Purposes Only
|
||||
|
||||
MIT License
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,2 @@
|
|||
from .selectivesearch import selective_search
|
||||
|
|
@ -0,0 +1,342 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
from past.builtins import cmp
|
||||
import skimage.io
|
||||
import skimage.feature
|
||||
import skimage.color
|
||||
import skimage.transform
|
||||
import skimage.util
|
||||
import skimage.segmentation
|
||||
import numpy
|
||||
|
||||
|
||||
# "Selective Search for Object Recognition" by J.R.R. Uijlings et al.
|
||||
#
|
||||
# - Modified version with LBP extractor for texture vectorization
|
||||
|
||||
|
||||
def _generate_segments(im_orig, scale, sigma, min_size):
|
||||
"""
|
||||
segment smallest regions by the algorithm of Felzenswalb and
|
||||
Huttenlocher
|
||||
"""
|
||||
|
||||
# open the Image
|
||||
im_mask = skimage.segmentation.felzenszwalb(
|
||||
skimage.util.img_as_float(im_orig), scale=scale, sigma=sigma,
|
||||
min_size=min_size)
|
||||
|
||||
# merge mask channel to the image as a 4th channel
|
||||
im_orig = numpy.append(
|
||||
im_orig, numpy.zeros(im_orig.shape[:2])[:, :, numpy.newaxis], axis=2)
|
||||
im_orig[:, :, 3] = im_mask
|
||||
|
||||
return im_orig
|
||||
|
||||
|
||||
def _sim_colour(r1, r2):
|
||||
"""
|
||||
calculate the sum of histogram intersection of colour
|
||||
"""
|
||||
return sum([min(a, b) for a, b in zip(r1["hist_c"], r2["hist_c"])])
|
||||
|
||||
|
||||
def _sim_texture(r1, r2):
|
||||
"""
|
||||
calculate the sum of histogram intersection of texture
|
||||
"""
|
||||
return sum([min(a, b) for a, b in zip(r1["hist_t"], r2["hist_t"])])
|
||||
|
||||
|
||||
def _sim_size(r1, r2, imsize):
|
||||
"""
|
||||
calculate the size similarity over the image
|
||||
"""
|
||||
return 1.0 - (r1["size"] + r2["size"]) / imsize
|
||||
|
||||
|
||||
def _sim_fill(r1, r2, imsize):
|
||||
"""
|
||||
calculate the fill similarity over the image
|
||||
"""
|
||||
bbsize = (
|
||||
(max(r1["max_x"], r2["max_x"]) - min(r1["min_x"], r2["min_x"]))
|
||||
* (max(r1["max_y"], r2["max_y"]) - min(r1["min_y"], r2["min_y"]))
|
||||
)
|
||||
return 1.0 - (bbsize - r1["size"] - r2["size"]) / imsize
|
||||
|
||||
|
||||
def _calc_sim(r1, r2, imsize):
|
||||
return (_sim_colour(r1, r2) + _sim_texture(r1, r2)
|
||||
+ _sim_size(r1, r2, imsize) + _sim_fill(r1, r2, imsize))
|
||||
|
||||
|
||||
def _calc_colour_hist(img):
|
||||
"""
|
||||
calculate colour histogram for each region
|
||||
|
||||
the size of output histogram will be BINS * COLOUR_CHANNELS(3)
|
||||
|
||||
number of bins is 25 as same as [uijlings_ijcv2013_draft.pdf]
|
||||
|
||||
extract HSV
|
||||
"""
|
||||
|
||||
BINS = 25
|
||||
hist = numpy.array([])
|
||||
|
||||
for colour_channel in (0, 1, 2):
|
||||
|
||||
# extracting one colour channel
|
||||
c = img[:, colour_channel]
|
||||
|
||||
# calculate histogram for each colour and join to the result
|
||||
hist = numpy.concatenate(
|
||||
[hist] + [numpy.histogram(c, BINS, (0.0, 255.0))[0]])
|
||||
|
||||
# L1 normalize
|
||||
hist = hist / len(img)
|
||||
|
||||
return hist
|
||||
|
||||
|
||||
def _calc_texture_gradient(img):
|
||||
"""
|
||||
calculate texture gradient for entire image
|
||||
|
||||
The original SelectiveSearch algorithm proposed Gaussian derivative
|
||||
for 8 orientations, but we use LBP instead.
|
||||
|
||||
output will be [height(*)][width(*)]
|
||||
"""
|
||||
ret = numpy.zeros((img.shape[0], img.shape[1], img.shape[2]))
|
||||
|
||||
for colour_channel in (0, 1, 2):
|
||||
ret[:, :, colour_channel] = skimage.feature.local_binary_pattern(
|
||||
img[:, :, colour_channel], 8, 1.0)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def _calc_texture_hist(img):
|
||||
"""
|
||||
calculate texture histogram for each region
|
||||
|
||||
calculate the histogram of gradient for each colours
|
||||
the size of output histogram will be
|
||||
BINS * ORIENTATIONS * COLOUR_CHANNELS(3)
|
||||
"""
|
||||
BINS = 10
|
||||
|
||||
hist = numpy.array([])
|
||||
|
||||
for colour_channel in (0, 1, 2):
|
||||
|
||||
# mask by the colour channel
|
||||
fd = img[:, colour_channel]
|
||||
|
||||
# calculate histogram for each orientation and concatenate them all
|
||||
# and join to the result
|
||||
hist = numpy.concatenate(
|
||||
[hist] + [numpy.histogram(fd, BINS, (0.0, 1.0))[0]])
|
||||
|
||||
# L1 Normalize
|
||||
hist = hist / len(img)
|
||||
|
||||
return hist
|
||||
|
||||
|
||||
def _extract_regions(img):
|
||||
|
||||
R = {}
|
||||
|
||||
# get hsv image
|
||||
hsv = skimage.color.rgb2hsv(img[:, :, :3])
|
||||
|
||||
# pass 1: count pixel positions
|
||||
for y, i in enumerate(img):
|
||||
|
||||
for x, (r, g, b, l) in enumerate(i):
|
||||
|
||||
# initialize a new region
|
||||
if l not in R:
|
||||
R[l] = {
|
||||
"min_x": 0xffff, "min_y": 0xffff,
|
||||
"max_x": 0, "max_y": 0, "labels": [l]}
|
||||
|
||||
# bounding box
|
||||
if R[l]["min_x"] > x:
|
||||
R[l]["min_x"] = x
|
||||
if R[l]["min_y"] > y:
|
||||
R[l]["min_y"] = y
|
||||
if R[l]["max_x"] < x:
|
||||
R[l]["max_x"] = x
|
||||
if R[l]["max_y"] < y:
|
||||
R[l]["max_y"] = y
|
||||
|
||||
# pass 2: calculate texture gradient
|
||||
tex_grad = _calc_texture_gradient(img)
|
||||
|
||||
# pass 3: calculate colour histogram of each region
|
||||
for k, v in R.items():
|
||||
|
||||
# colour histogram
|
||||
masked_pixels = hsv[:, :, :][img[:, :, 3] == k]
|
||||
R[k]["size"] = len(masked_pixels / 4)
|
||||
R[k]["hist_c"] = _calc_colour_hist(masked_pixels)
|
||||
|
||||
# texture histogram
|
||||
R[k]["hist_t"] = _calc_texture_hist(tex_grad[:, :][img[:, :, 3] == k])
|
||||
|
||||
return R
|
||||
|
||||
|
||||
def _extract_neighbours(regions):
|
||||
|
||||
def intersect(a, b):
|
||||
if (a["min_x"] < b["min_x"] < a["max_x"]
|
||||
and a["min_y"] < b["min_y"] < a["max_y"]) or (
|
||||
a["min_x"] < b["max_x"] < a["max_x"]
|
||||
and a["min_y"] < b["max_y"] < a["max_y"]) or (
|
||||
a["min_x"] < b["min_x"] < a["max_x"]
|
||||
and a["min_y"] < b["max_y"] < a["max_y"]) or (
|
||||
a["min_x"] < b["max_x"] < a["max_x"]
|
||||
and a["min_y"] < b["min_y"] < a["max_y"]):
|
||||
return True
|
||||
return False
|
||||
|
||||
R = list(regions.items())
|
||||
neighbours = []
|
||||
for cur, a in enumerate(R[:-1]):
|
||||
for b in R[cur + 1:]:
|
||||
if intersect(a[1], b[1]):
|
||||
neighbours.append((a, b))
|
||||
|
||||
return neighbours
|
||||
|
||||
|
||||
def _merge_regions(r1, r2):
|
||||
new_size = r1["size"] + r2["size"]
|
||||
rt = {
|
||||
"min_x": min(r1["min_x"], r2["min_x"]),
|
||||
"min_y": min(r1["min_y"], r2["min_y"]),
|
||||
"max_x": max(r1["max_x"], r2["max_x"]),
|
||||
"max_y": max(r1["max_y"], r2["max_y"]),
|
||||
"size": new_size,
|
||||
"hist_c": (
|
||||
r1["hist_c"] * r1["size"] + r2["hist_c"] * r2["size"]) / new_size,
|
||||
"hist_t": (
|
||||
r1["hist_t"] * r1["size"] + r2["hist_t"] * r2["size"]) / new_size,
|
||||
"labels": r1["labels"] + r2["labels"]
|
||||
}
|
||||
return rt
|
||||
|
||||
def mycmp(x, y):
|
||||
return cmp(x[1],y[1])
|
||||
|
||||
def cmp_to_key(mycmp):
|
||||
'Convert a cmp= function into a key= function'
|
||||
class K(object):
|
||||
def __init__(self, obj, *args):
|
||||
self.obj = obj
|
||||
def __lt__(self, other):
|
||||
return mycmp(self.obj, other.obj) < 0
|
||||
def __gt__(self, other):
|
||||
return mycmp(self.obj, other.obj) > 0
|
||||
def __eq__(self, other):
|
||||
return mycmp(self.obj, other.obj) == 0
|
||||
def __le__(self, other):
|
||||
return mycmp(self.obj, other.obj) <= 0
|
||||
def __ge__(self, other):
|
||||
return mycmp(self.obj, other.obj) >= 0
|
||||
def __ne__(self, other):
|
||||
return mycmp(self.obj, other.obj) != 0
|
||||
return K
|
||||
|
||||
def selective_search(
|
||||
im_orig, scale=1.0, sigma=0.8, min_size=50):
|
||||
'''Selective Search
|
||||
|
||||
Parameters
|
||||
----------
|
||||
im_orig : ndarray
|
||||
Input image
|
||||
scale : int
|
||||
Free parameter. Higher means larger clusters in felzenszwalb segmentation.
|
||||
sigma : float
|
||||
Width of Gaussian kernel for felzenszwalb segmentation.
|
||||
min_size : int
|
||||
Minimum component size for felzenszwalb segmentation.
|
||||
Returns
|
||||
-------
|
||||
img : ndarray
|
||||
image with region label
|
||||
region label is stored in the 4th value of each pixel [r,g,b,(region)]
|
||||
regions : array of dict
|
||||
[
|
||||
{
|
||||
'rect': (left, top, right, bottom),
|
||||
'labels': [...]
|
||||
},
|
||||
...
|
||||
]
|
||||
'''
|
||||
assert im_orig.shape[2] == 3, "3ch image is expected"
|
||||
|
||||
# load image and get smallest regions
|
||||
# region label is stored in the 4th value of each pixel [r,g,b,(region)]
|
||||
img = _generate_segments(im_orig, scale, sigma, min_size)
|
||||
|
||||
if img is None:
|
||||
return None, {}
|
||||
|
||||
imsize = img.shape[0] * img.shape[1]
|
||||
R = _extract_regions(img)
|
||||
|
||||
# extract neighbouring information
|
||||
neighbours = list(_extract_neighbours(R))
|
||||
|
||||
# calculate initial similarities
|
||||
S = {}
|
||||
for (ai, ar), (bi, br) in neighbours:
|
||||
S[(ai, bi)] = _calc_sim(ar, br, imsize)
|
||||
|
||||
# hierarchal search
|
||||
while S != {}:
|
||||
|
||||
# get highest similarity
|
||||
if sys.version_info[0] < 3:
|
||||
i, j = sorted(S.items(), cmp=mycmp)[-1][0]
|
||||
else:
|
||||
i, j = sorted(S.items(), key=cmp_to_key(mycmp))[-1][0]
|
||||
|
||||
# merge corresponding regions
|
||||
t = max(R.keys()) + 1.0
|
||||
R[t] = _merge_regions(R[i], R[j])
|
||||
|
||||
# mark similarities for regions to be removed
|
||||
key_to_delete = []
|
||||
for k, v in S.items():
|
||||
if (i in k) or (j in k):
|
||||
key_to_delete.append(k)
|
||||
|
||||
# remove old similarities of related regions
|
||||
for k in key_to_delete:
|
||||
del S[k]
|
||||
|
||||
# calculate similarity set with the new region
|
||||
for k in filter(lambda a: a != (i, j), key_to_delete):
|
||||
n = k[1] if k[0] in (i, j) else k[0]
|
||||
S[(t, n)] = _calc_sim(R[t], R[n], imsize)
|
||||
|
||||
regions = []
|
||||
for k, r in R.items():
|
||||
regions.append({
|
||||
'rect': (
|
||||
r['min_x'], r['min_y'],
|
||||
r['max_x'] - r['min_x'], r['max_y'] - r['min_y']),
|
||||
'size': r['size'],
|
||||
'labels': r['labels']
|
||||
})
|
||||
|
||||
return img, regions
|
|
@ -8,7 +8,7 @@ command = TrainConvNet:Write:Test
|
|||
|
||||
makeMode = false ; traceLevel = 1 ; deviceId = "auto"
|
||||
|
||||
rootDir = ".." ; dataDir = "$rootDir$/DataSets/CIFAR10" ;
|
||||
rootDir = ".." ; dataDir = "$rootDir$/DataSets/CIFAR-10" ;
|
||||
outputDir = "Output" ; modelDir = "$outputDir$/Models"
|
||||
|
||||
modelPath = "$ModelDir$/RegrSimple_CIFAR10.cmf"
|
||||
|
|
|
@ -38,12 +38,12 @@ or prefix the call to the cntk executable with the corresponding folder.
|
|||
|
||||
### Run
|
||||
|
||||
Run the example from the Speech/Data folder using:
|
||||
Run the example from the Speech/Data folder using (or use the LSTM variant):
|
||||
|
||||
`cntk configFile=../Config/FeedForward.cntk`
|
||||
|
||||
or run from any folder and specify the Data folder as the `currentDirectory`,
|
||||
e.g. running from the Speech folder using:
|
||||
e.g. running from the Speech folder using (or use the LSTM variant):
|
||||
|
||||
`cntk configFile=Config/FeedForward.cntk currentDirectory=Data`
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Build Language Understanding Models with CNTK
|
||||
|
||||
This example demonstrates how to use build language understanding model with CNTK using ATIS data set. This example is similar to
|
||||
This example demonstrates how to use build language understanding model with CNTK using ATIS data set. The recipeice in this example are in BrainScript. For Python click [here](https://github.com/Microsoft/CNTK/blob/master/bindings/python/examples/LanguageUnderstanding/LanguageUnderstanding.py). This example is similar to
|
||||
[SLU example](https://github.com/Microsoft/CNTK/tree/master/Examples/Text/Miscellaneous/SLU). They are different in that
|
||||
- CNTKTextFormatReader is used here, instead of LUSequenceReader
|
||||
- With CNTKTextFormatReader, the input format is much more flexible. In the example setting, sparse contextual feature vectors are explored
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче