diff --git a/.gitignore b/.gitignore
index e9c85891..45668ccb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@
*.userprefs
# Build results
+[Bb]uild/
[Dd]ebugPublic/
[Rr]eleases/
[Ii]nt/
diff --git a/.gitmodules b/.gitmodules
index 19ffb64f..7ada222b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "Samples/RustSqueezenet/winrt-rs"]
path = Samples/RustSqueezenet/winrt-rs
url = https://github.com/microsoft/winrt-rs.git
+[submodule "external/opencv"]
+ path = external/opencv
+ url = https://github.com/opencv/opencv.git
diff --git a/Samples/WinMLSamplesGallery/WinMLSamplesGallery (Package)/WinMLSamplesGallery (Package).wapproj b/Samples/WinMLSamplesGallery/WinMLSamplesGallery (Package)/WinMLSamplesGallery (Package).wapproj
index a9a6028d..5258aa4e 100644
--- a/Samples/WinMLSamplesGallery/WinMLSamplesGallery (Package)/WinMLSamplesGallery (Package).wapproj
+++ b/Samples/WinMLSamplesGallery/WinMLSamplesGallery (Package)/WinMLSamplesGallery (Package).wapproj
@@ -128,7 +128,7 @@
-
+
diff --git a/Samples/WinMLSamplesGallery/WinMLSamplesGallery/SampleMetadata/SampleMetadata.cs b/Samples/WinMLSamplesGallery/WinMLSamplesGallery/SampleMetadata/SampleMetadata.cs
index 23e043c7..e88c3038 100644
--- a/Samples/WinMLSamplesGallery/WinMLSamplesGallery/SampleMetadata/SampleMetadata.cs
+++ b/Samples/WinMLSamplesGallery/WinMLSamplesGallery/SampleMetadata/SampleMetadata.cs
@@ -39,6 +39,17 @@ namespace WinMLSamplesGallery
for (int i = 0; i < metadataJsonArray.Count; i++)
{
JsonObject currentSampleMetadata = metadataJsonArray[i].GetObject();
+
+ bool shouldHideSample = false;
+#if !USE_OPENCV
+ shouldHideSample |= currentSampleMetadata["Tag"].GetString() == "OpenCVInterop";
+#endif
+
+ if (shouldHideSample)
+ {
+ continue;
+ }
+
allSampleMetadata.Add(new SampleMetadata
{
Title = currentSampleMetadata["Title"].GetString(),
diff --git a/Samples/WinMLSamplesGallery/WinMLSamplesGallery/Samples/OpenCVInterop/README.md b/Samples/WinMLSamplesGallery/WinMLSamplesGallery/Samples/OpenCVInterop/README.md
index 8d730934..c5eab40f 100644
--- a/Samples/WinMLSamplesGallery/WinMLSamplesGallery/Samples/OpenCVInterop/README.md
+++ b/Samples/WinMLSamplesGallery/WinMLSamplesGallery/Samples/OpenCVInterop/README.md
@@ -22,7 +22,22 @@ Windows ML will be used to resize and tensorize the image into NCHW format, as w
- [OpenCV LICENSE](../../../../../external/opencv/4.5.4/LICENSE)
## Getting Started
-- Check out the [source](https://github.com/microsoft/Windows-Machine-Learning/blob/91e493d699df80a633654929418f41bab136ae1d/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.cpp#L21)
+In order to build this sample, OpenCV will need to be built and linked into the WinML Samples Gallery. The OpenCV project is included as a submodule, and will need to be synced and built for your Platform Architecture and Configuration before it will appear in the Windows ML Samples Gallery. To do so follow these instructions:
+- Launch a Visual Studio Developer Command Prompt.
+- Navigate to root.
+- Sync submodules with `git submodule update --init --recursive`
+- Launch Powershell with `powershell`
+- Build the OpenCV project with
+
+ `.\external\tools\BuildOpenCV.ps1 -Architecture -Configuration `
+
+ For example:
+
+ `.\external\tools\BuildOpenCV.ps1 -Architecture x64 -Configuration Debug`
+- Launch the `WinMLSamplesGallery.sln` and build with the same **Architecture** and **Configuration** to see the sample appear.
+
+
+You can check out the source [here](https://github.com/microsoft/Windows-Machine-Learning/blob/91e493d699df80a633654929418f41bab136ae1d/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.cpp#L21).
## Feedback
Please file an issue [here](https://github.com/microsoft/Windows-Machine-Learning/issues/new) if you encounter any issues with this sample.
diff --git a/Samples/WinMLSamplesGallery/WinMLSamplesGallery/WinMLSamplesGallery.csproj b/Samples/WinMLSamplesGallery/WinMLSamplesGallery/WinMLSamplesGallery.csproj
index 1e80d083..e575e226 100644
--- a/Samples/WinMLSamplesGallery/WinMLSamplesGallery/WinMLSamplesGallery.csproj
+++ b/Samples/WinMLSamplesGallery/WinMLSamplesGallery/WinMLSamplesGallery.csproj
@@ -9,7 +9,13 @@
win10-x86;win10-x64;win10-arm64
true
false
+ opencv_world454d.lib
+ opencv_world454.lib
+ $(SolutionDir)..\..\build\external\opencv\cmake_config\$(Platform)\lib\$(Configuration)\$(OpenCVLib)
+ False
+ True
$(DefineConstants);USE_LARGE_MODELS
+ $(DefineConstants);USE_OPENCV
true
diff --git a/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.cpp b/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.cpp
index 1b874ff6..3fb01fcc 100644
--- a/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.cpp
+++ b/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.cpp
@@ -7,9 +7,7 @@
#include "winrt/Microsoft.AI.MachineLearning.h"
#include "WeakBuffer.h"
-
#include
-
#include
namespace wrl = ::Microsoft::WRL;
@@ -20,31 +18,44 @@ namespace winrt::WinMLSamplesGalleryNative::implementation
{
OpenCVImage::OpenCVImage(winrt::hstring path)
{
+#ifdef USE_OPENCV
image_ = cv::imread(winrt::to_string(path), cv::IMREAD_COLOR);
+#endif
}
+#ifdef USE_OPENCV
OpenCVImage::OpenCVImage(cv::Mat&& image) : image_(std::move(image)) {
}
+#endif
winrt::Windows::Storage::Streams::IBuffer OpenCVImage::AsWeakBuffer()
{
+#ifdef USE_OPENCV
auto cz_buffer = image_.ptr();
auto size = image_.total()* image_.elemSize();
winrt::com_ptr ptr;
wrl::MakeAndInitialize>(ptr.put(), cz_buffer, cz_buffer + size);
return ptr.as();
+#else
+ return nullptr;
+#endif
}
winrt::Microsoft::AI::MachineLearning::ITensor OpenCVImage::AsTensor()
{
+#ifdef USE_OPENCV
auto buffer = AsWeakBuffer();
return winrt::Microsoft::AI::MachineLearning::TensorUInt8Bit::CreateFromBuffer(
std::vector{ 1, image_.rows, image_.cols, 3 }, buffer);
+#else
+ return nullptr;
+#endif
}
winrt::Windows::Graphics::Imaging::SoftwareBitmap OpenCVImage::AsSoftwareBitmap()
{
+#ifdef USE_OPENCV
cv::Mat bgra_image;
cv::cvtColor(image_, bgra_image, cv::COLOR_RGB2RGBA);
@@ -55,11 +66,16 @@ namespace winrt::WinMLSamplesGalleryNative::implementation
winrt::Windows::Graphics::Imaging::SoftwareBitmap::CreateCopyFromBuffer(
bgra_buffer, winrt::Windows::Graphics::Imaging::BitmapPixelFormat::Bgra8, image_.cols, image_.rows);
return software_bitmap;
+#else
+ return nullptr;
+#endif
}
void OpenCVImage::Close()
{
+#ifdef USE_OPENCV
image_.deallocate();
+#endif
}
winrt::WinMLSamplesGalleryNative::OpenCVImage OpenCVImage::CreateFromPath(hstring const& path) {
@@ -67,6 +83,7 @@ namespace winrt::WinMLSamplesGalleryNative::implementation
}
winrt::WinMLSamplesGalleryNative::OpenCVImage OpenCVImage::AddSaltAndPepperNoise(winrt::WinMLSamplesGalleryNative::OpenCVImage image) {
+#ifdef USE_OPENCV
auto& image_mat = image.as().get()->image_;
cv::Mat saltpepper_noise = cv::Mat::zeros(image_mat.rows, image_mat.cols, CV_8U);
randu(saltpepper_noise, 0, 255);
@@ -79,12 +96,19 @@ namespace winrt::WinMLSamplesGalleryNative::implementation
saltpepper_img.setTo(0, black);
return winrt::make(std::move(saltpepper_img));
+#else
+ return nullptr;
+#endif
}
winrt::WinMLSamplesGalleryNative::OpenCVImage OpenCVImage::DenoiseMedianBlur(winrt::WinMLSamplesGalleryNative::OpenCVImage image) {
+#ifdef USE_OPENCV
auto& image_mat = image.as().get()->image_;
cv::Mat denoised;
cv::medianBlur(image_mat, denoised, 5);
return winrt::make(std::move(denoised));
+#else
+ return nullptr;
+#endif
}
}
diff --git a/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.h b/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.h
index 5887408b..2345394b 100644
--- a/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.h
+++ b/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/OpenCVImage.h
@@ -1,14 +1,19 @@
#pragma once
#include "OpenCVImage.g.h"
-#include
+#ifdef USE_OPENCV
+#include
+#endif
+
namespace winrt::WinMLSamplesGalleryNative::implementation
{
struct OpenCVImage : OpenCVImageT
{
OpenCVImage(winrt::hstring path);
- OpenCVImage(cv::Mat&& image);
+#ifdef USE_OPENCV
+ OpenCVImage(cv::Mat&& image);
+#endif
static winrt::WinMLSamplesGalleryNative::OpenCVImage CreateFromPath(hstring const& path);
static winrt::WinMLSamplesGalleryNative::OpenCVImage AddSaltAndPepperNoise(winrt::WinMLSamplesGalleryNative::OpenCVImage image);
@@ -20,7 +25,9 @@ namespace winrt::WinMLSamplesGalleryNative::implementation
void Close();
private:
+#ifdef USE_OPENCV
cv::Mat image_;
+#endif
};
}
namespace winrt::WinMLSamplesGalleryNative::factory_implementation
diff --git a/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/WinMLSamplesGalleryNative.vcxproj b/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/WinMLSamplesGalleryNative.vcxproj
index f5a88948..3f81dc86 100644
--- a/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/WinMLSamplesGalleryNative.vcxproj
+++ b/Samples/WinMLSamplesGallery/WinMLSamplesGalleryNative/WinMLSamplesGalleryNative.vcxproj
@@ -98,42 +98,44 @@
WinMLSamplesGalleryNative.def
+
+
+
+ $(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)
+
+
+
+
+
+ opencv_world454d.lib
+ opencv_world454.lib
+ $(SolutionDir)..\..\build\external\opencv\cmake_config\$(PlatformString)\lib\$(Configuration)\$(OpenCVLib)
+ False
+ True
+
+
+
+ $(SolutionDir)..\..\build\external\opencv\cmake_config\$(PlatformString)\install\include;%(AdditionalIncludeDirectories)
+ %(AdditionalOptions) /DUSE_OPENCV=1
+
+
+ $(SolutionDir)..\..\build\external\opencv\cmake_config\$(PlatformString)\lib\$(Configuration)
+ $(OpenCVLib);%(AdditionalDependencies)
+
+
+
_DEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)..\..\external\opencv\4.5.4\neutral\include;$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)
- $(SolutionDir)..\..\external\opencv\4.5.4\neutral\include;$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)
- $(SolutionDir)..\..\external\opencv\4.5.4\neutral\include;$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)
-
- $(SolutionDir)..\..\external\opencv\4.5.4\$(PlatformString)\$(Configuration)\lib
- opencv_world454d.lib;%(AdditionalDependencies)
-
-
- $(SolutionDir)..\..\external\opencv\4.5.4\$(PlatformString)\$(Configuration)\lib
- opencv_world454d.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
-
-
- $(SolutionDir)..\..\external\opencv\4.5.4\$(PlatformString)\$(Configuration)\lib
- opencv_world454d.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
-
NDEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)..\..\external\opencv\4.5.4\neutral\include;$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)
- $(SolutionDir)..\..\external\opencv\4.5.4\neutral\include;$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)
- $(SolutionDir)..\..\external\opencv\4.5.4\neutral\include;$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)
true
true
- $(SolutionDir)..\..\external\opencv\4.5.4\$(PlatformString)\$(Configuration)\lib
- $(SolutionDir)..\..\external\opencv\4.5.4\$(PlatformString)\$(Configuration)\lib
- $(SolutionDir)..\..\external\opencv\4.5.4\$(PlatformString)\$(Configuration)\lib
- opencv_world454.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
- opencv_world454.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
- opencv_world454.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
diff --git a/azure-pipelines-samples.yml b/azure-pipelines-samples.yml
index 98048e4d..4a26598b 100644
--- a/azure-pipelines-samples.yml
+++ b/azure-pipelines-samples.yml
@@ -58,7 +58,6 @@ steps:
targetType: inline
script: if (-not (Test-Path "${ENV:programfiles(x86)}\windows Kits\10\include\10.0.18362.0\")) { choco install windows-sdk-10-version-1903-all -y }
-
- task: PowerShell@2
displayName: 'Restore WinMLSamplesGalleryNative Nuget Packages'
inputs:
@@ -74,7 +73,7 @@ steps:
inputs:
solution: 'Samples/WinMLSamplesGallery/WinMLSamplesGallery.sln'
vsVersion: "16.0"
- msbuildArgs: '-v:diag /p:OutDir=$(System.DefaultWorkingDirectory)\bin\$(BuildPlatform)\$(BuildConfiguration)\WinMLSamplesGallery\ /p:WindowsTargetPlatformVersion=$(WindowsTargetPlatformVersion) /p:UseLargeModels=true /t:Restore,Clean,Build'
+ msbuildArgs: '/p:OutDir=$(System.DefaultWorkingDirectory)\bin\$(BuildPlatform)\$(BuildConfiguration)\WinMLSamplesGallery\ /p:WindowsTargetPlatformVersion=$(WindowsTargetPlatformVersion) /p:UseLargeModels=true /t:Restore,Clean,Build'
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
msbuildArchitecture: x64
diff --git a/external/opencv b/external/opencv
new file mode 160000
index 00000000..4223495e
--- /dev/null
+++ b/external/opencv
@@ -0,0 +1 @@
+Subproject commit 4223495e6cd67011f86b8ecd9be1fa105018f3b1
diff --git a/external/tools/BuildOpenCV.ps1 b/external/tools/BuildOpenCV.ps1
new file mode 100644
index 00000000..7012070e
--- /dev/null
+++ b/external/tools/BuildOpenCV.ps1
@@ -0,0 +1,32 @@
+Param
+(
+ # Build architecture.
+ [ValidateSet(
+ 'x64',
+ 'x86',
+ 'ARM64')]
+ [string]$Architecture = 'x64',
+
+ # Build configuration.
+ [ValidateSet('Debug', 'Release')][string]$Configuration = 'Debug',
+
+ # Location to generate build files.
+ [string]$CMakeBuildDirectory = "$PSScriptRoot\..\..\build\external\opencv\cmake_config\$Architecture\",
+
+ # Cleans build files before proceeding.
+ [switch]$Clean
+)
+
+if ($Clean) {
+ Remove-Item -Recurse -Force $CMakeBuildDirectory
+}
+
+& $PSScriptRoot\CMakeConfigureOpenCV.ps1 -Architecture $Architecture
+
+# Build OpenCV
+$solution = $CMakeBuildDirectory + "OpenCV.sln"
+msbuild /p:Configuration=$Configuration /t:Build $solution
+
+# Install
+$installProject = $CMakeBuildDirectory + "INSTALL.vcxproj"
+msbuild /p:Configuration=$Configuration $installProject
\ No newline at end of file
diff --git a/external/tools/CMakeConfigureOpenCV.ps1 b/external/tools/CMakeConfigureOpenCV.ps1
new file mode 100644
index 00000000..0fc9649c
--- /dev/null
+++ b/external/tools/CMakeConfigureOpenCV.ps1
@@ -0,0 +1,48 @@
+Param
+(
+ # Build architecture.
+ [ValidateSet(
+ 'x64',
+ 'x86',
+ 'ARM64')]
+ [string]$Architecture = 'x64',
+
+ # CMake generator.
+ [ValidateSet(
+ 'Visual Studio 15 2017',
+ 'Visual Studio 16 2019')]
+ [string]$Generator='Visual Studio 16 2019',
+
+ # Location to generate build files.
+ [string]$BuildDirectory = "$PSScriptRoot\..\..\build\external\opencv\cmake_config\$Architecture",
+
+ # Cleans build files before proceeding.
+ [switch]$Clean
+)
+
+
+$Args = New-Object Collections.Generic.List[String]
+
+if ($Architecture -eq 'x86') {
+ $Args.Add("-A Win32")
+}
+else {
+ $Args.Add("-A " + $Architecture)
+}
+
+$Args.Add("-G " + $Generator)
+$Args.Add("-DCMAKE_SYSTEM_NAME=Windows")
+$Args.Add("-DCMAKE_SYSTEM_VERSION=10.0")
+$Args.Add("-DWITH_OPENCL=OFF")
+$Args.Add("-DWITH_FFMPEG=OFF")
+$Args.Add("-DWITH_CUDA=OFF")
+$Args.Add("-DBUILD_EXAMPLES=OFF")
+$Args.Add("-DBUILD_TESTS=OFF")
+$Args.Add("-DBUILD_opencv_world=ON")
+
+if ($Clean) {
+ $Args.Add("--clean")
+}
+
+$Args.Add("-B " + $BuildDirectory)
+cmake $Args "$PSScriptRoot\..\opencv"