Path: blob/master/samples/wp8/OcvImageManipulation/PhoneXamlDirect3DApp1/PhoneXamlDirect3DApp1Comp/Direct3DInterop.cpp
16344 views
#include "pch.h"1#include "Direct3DInterop.h"2#include "Direct3DContentProvider.h"3#include <windows.storage.streams.h>4#include <wrl.h>5#include <robuffer.h>6#include <opencv2\core.hpp>7#include <opencv2\imgproc.hpp>8#include <opencv2\features2d.hpp>9#include <algorithm>1011using namespace Windows::Storage::Streams;12using namespace Microsoft::WRL;13using namespace Windows::Foundation;14using namespace Windows::UI::Core;15using namespace Microsoft::WRL;16using namespace Windows::Phone::Graphics::Interop;17using namespace Windows::Phone::Input::Interop;18using namespace Windows::Foundation;19using namespace Windows::Foundation::Collections;20using namespace Windows::Phone::Media::Capture;2122#if !defined(_M_ARM)23#pragma message("warning: Direct3DInterop.cpp: Windows Phone camera code does not run in the emulator.")24#pragma message("warning: Direct3DInterop.cpp: Please compile as an ARM build and run on a device.")25#endif2627namespace PhoneXamlDirect3DApp1Comp28{29// Called each time a preview frame is available30void CameraCapturePreviewSink::OnFrameAvailable(31DXGI_FORMAT format,32UINT width,33UINT height,34BYTE* pixels35)36{37m_Direct3dInterop->UpdateFrame(pixels, width, height);38}3940// Called each time a captured frame is available41void CameraCaptureSampleSink::OnSampleAvailable(42ULONGLONG hnsPresentationTime,43ULONGLONG hnsSampleDuration,44DWORD cbSample,45BYTE* pSample)46{474849}5051Direct3DInterop::Direct3DInterop()52: m_algorithm(OCVFilterType::ePreview)53, m_contentDirty(false)54, m_backFrame(nullptr)55, m_frontFrame(nullptr)56{57}5859bool Direct3DInterop::SwapFrames()60{61std::lock_guard<std::mutex> lock(m_mutex);62if(m_backFrame != nullptr)63{64std::swap(m_backFrame, m_frontFrame);65return true;66}67return false;68}6970void Direct3DInterop::UpdateFrame(byte* buffer,int width,int height)71{72std::lock_guard<std::mutex> lock(m_mutex);73if(m_backFrame == nullptr)74{75m_backFrame = std::shared_ptr<cv::Mat> (new cv::Mat(height, width, CV_8UC4));76m_frontFrame = std::shared_ptr<cv::Mat> (new cv::Mat(height, width, CV_8UC4));77}7879memcpy(m_backFrame.get()->data, buffer, 4 * height*width);80m_contentDirty = true;81RequestAdditionalFrame();82}8384void Direct3DInterop::ProcessFrame()85{86if (SwapFrames())87{88if (m_renderer)89{90cv::Mat* mat = m_frontFrame.get();9192switch (m_algorithm)93{94case OCVFilterType::ePreview:95{96break;97}9899case OCVFilterType::eGray:100{101ApplyGrayFilter(mat);102break;103}104105case OCVFilterType::eCanny:106{107ApplyCannyFilter(mat);108break;109}110111case OCVFilterType::eBlur:112{113ApplyBlurFilter(mat);114break;115}116117case OCVFilterType::eFindFeatures:118{119ApplyFindFeaturesFilter(mat);120break;121}122123case OCVFilterType::eSepia:124{125ApplySepiaFilter(mat);126break;127}128}129130m_renderer->CreateTextureFromByte(mat->data, mat->cols, mat->rows);131}132}133}134135void Direct3DInterop::ApplyGrayFilter(cv::Mat* mat)136{137cv::Mat intermediateMat;138cv::cvtColor(*mat, intermediateMat, COLOR_RGBA2GRAY);139cv::cvtColor(intermediateMat, *mat, COLOR_GRAY2BGRA);140}141142void Direct3DInterop::ApplyCannyFilter(cv::Mat* mat)143{144cv::Mat intermediateMat;145cv::Canny(*mat, intermediateMat, 80, 90);146cv::cvtColor(intermediateMat, *mat, COLOR_GRAY2BGRA);147}148149void Direct3DInterop::ApplyBlurFilter(cv::Mat* mat)150{151cv::Mat intermediateMat;152// cv::Blur(image, intermediateMat, 80, 90);153cv::cvtColor(intermediateMat, *mat, COLOR_GRAY2BGRA);154}155156void Direct3DInterop::ApplyFindFeaturesFilter(cv::Mat* mat)157{158cv::Mat intermediateMat;159cv::Ptr<cv::FastFeatureDetector> detector = cv::FastFeatureDetector::create(50);160std::vector<cv::KeyPoint> features;161162cv::cvtColor(*mat, intermediateMat, COLOR_RGBA2GRAY);163detector->detect(intermediateMat, features);164165for( unsigned int i = 0; i < std::min(features.size(), (size_t)50); i++ )166{167const cv::KeyPoint& kp = features[i];168cv::circle(*mat, cv::Point((int)kp.pt.x, (int)kp.pt.y), 10, cv::Scalar(255,0,0,255));169}170}171172void Direct3DInterop::ApplySepiaFilter(cv::Mat* mat)173{174const float SepiaKernelData[16] =175{176/* B */0.131f, 0.534f, 0.272f, 0.f,177/* G */0.168f, 0.686f, 0.349f, 0.f,178/* R */0.189f, 0.769f, 0.393f, 0.f,179/* A */0.000f, 0.000f, 0.000f, 1.f180};181182const cv::Mat SepiaKernel(4, 4, CV_32FC1, (void*)SepiaKernelData);183cv::transform(*mat, *mat, SepiaKernel);184}185186IDrawingSurfaceContentProvider^ Direct3DInterop::CreateContentProvider()187{188ComPtr<Direct3DContentProvider> provider = Make<Direct3DContentProvider>(this);189return reinterpret_cast<IDrawingSurfaceContentProvider^>(provider.Detach());190}191192// IDrawingSurfaceManipulationHandler193void Direct3DInterop::SetManipulationHost(DrawingSurfaceManipulationHost^ manipulationHost)194{195manipulationHost->PointerPressed +=196ref new TypedEventHandler<DrawingSurfaceManipulationHost^, PointerEventArgs^>(this, &Direct3DInterop::OnPointerPressed);197198manipulationHost->PointerMoved +=199ref new TypedEventHandler<DrawingSurfaceManipulationHost^, PointerEventArgs^>(this, &Direct3DInterop::OnPointerMoved);200201manipulationHost->PointerReleased +=202ref new TypedEventHandler<DrawingSurfaceManipulationHost^, PointerEventArgs^>(this, &Direct3DInterop::OnPointerReleased);203}204205void Direct3DInterop::RenderResolution::set(Windows::Foundation::Size renderResolution)206{207if (renderResolution.Width != m_renderResolution.Width ||208renderResolution.Height != m_renderResolution.Height)209{210m_renderResolution = renderResolution;211212if (m_renderer)213{214m_renderer->UpdateForRenderResolutionChange(m_renderResolution.Width, m_renderResolution.Height);215RecreateSynchronizedTexture();216}217}218}219220// Event Handlers221222void Direct3DInterop::OnPointerPressed(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)223{224// Insert your code here.225}226227void Direct3DInterop::OnPointerMoved(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)228{229// Insert your code here.230}231232void Direct3DInterop::OnPointerReleased(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)233{234// Insert your code here.235}236237void Direct3DInterop::StartCamera()238{239// Set the capture dimensions240Size captureDimensions;241captureDimensions.Width = 640;242captureDimensions.Height = 480;243244// Open the AudioVideoCaptureDevice for video only245IAsyncOperation<AudioVideoCaptureDevice^> ^openOperation = AudioVideoCaptureDevice::OpenForVideoOnlyAsync(CameraSensorLocation::Back, captureDimensions);246247openOperation->Completed = ref new AsyncOperationCompletedHandler<AudioVideoCaptureDevice^>(248[this] (IAsyncOperation<AudioVideoCaptureDevice^> ^operation, Windows::Foundation::AsyncStatus status)249{250if (status == Windows::Foundation::AsyncStatus::Completed)251{252auto captureDevice = operation->GetResults();253254// Save the reference to the opened video capture device255pAudioVideoCaptureDevice = captureDevice;256257// Retrieve the native ICameraCaptureDeviceNative interface from the managed video capture device258ICameraCaptureDeviceNative *iCameraCaptureDeviceNative = NULL;259HRESULT hr = reinterpret_cast<IUnknown*>(captureDevice)->QueryInterface(__uuidof(ICameraCaptureDeviceNative), (void**) &iCameraCaptureDeviceNative);260261// Save the pointer to the native interface262pCameraCaptureDeviceNative = iCameraCaptureDeviceNative;263264// Initialize the preview dimensions (see the accompanying article at )265// The aspect ratio of the capture and preview resolution must be equal,266// 4:3 for capture => 4:3 for preview, and 16:9 for capture => 16:9 for preview.267Size previewDimensions;268previewDimensions.Width = 640;269previewDimensions.Height = 480;270271IAsyncAction^ setPreviewResolutionAction = pAudioVideoCaptureDevice->SetPreviewResolutionAsync(previewDimensions);272setPreviewResolutionAction->Completed = ref new AsyncActionCompletedHandler(273[this](IAsyncAction^ action, Windows::Foundation::AsyncStatus status)274{275HResult hr = action->ErrorCode;276277if (status == Windows::Foundation::AsyncStatus::Completed)278{279// Create the sink280MakeAndInitialize<CameraCapturePreviewSink>(&pCameraCapturePreviewSink);281pCameraCapturePreviewSink->SetDelegate(this);282pCameraCaptureDeviceNative->SetPreviewSink(pCameraCapturePreviewSink);283284// Set the preview format285pCameraCaptureDeviceNative->SetPreviewFormat(DXGI_FORMAT::DXGI_FORMAT_B8G8R8A8_UNORM);286}287}288);289290// Retrieve IAudioVideoCaptureDeviceNative native interface from managed projection.291IAudioVideoCaptureDeviceNative *iAudioVideoCaptureDeviceNative = NULL;292hr = reinterpret_cast<IUnknown*>(captureDevice)->QueryInterface(__uuidof(IAudioVideoCaptureDeviceNative), (void**) &iAudioVideoCaptureDeviceNative);293294// Save the pointer to the IAudioVideoCaptureDeviceNative native interface295pAudioVideoCaptureDeviceNative = iAudioVideoCaptureDeviceNative;296297// Set sample encoding format to ARGB. See the documentation for further values.298pAudioVideoCaptureDevice->VideoEncodingFormat = CameraCaptureVideoFormat::Argb;299300// Initialize and set the CameraCaptureSampleSink class as sink for captures samples301MakeAndInitialize<CameraCaptureSampleSink>(&pCameraCaptureSampleSink);302pAudioVideoCaptureDeviceNative->SetVideoSampleSink(pCameraCaptureSampleSink);303304// Start recording (only way to receive samples using the ICameraCaptureSampleSink interface305pAudioVideoCaptureDevice->StartRecordingToSinkAsync();306}307}308);309310}311// Interface With Direct3DContentProvider312HRESULT Direct3DInterop::Connect(_In_ IDrawingSurfaceRuntimeHostNative* host)313{314m_renderer = ref new QuadRenderer();315m_renderer->Initialize();316m_renderer->UpdateForWindowSizeChange(WindowBounds.Width, WindowBounds.Height);317m_renderer->UpdateForRenderResolutionChange(m_renderResolution.Width, m_renderResolution.Height);318StartCamera();319320return S_OK;321}322323void Direct3DInterop::Disconnect()324{325m_renderer = nullptr;326}327328HRESULT Direct3DInterop::PrepareResources(_In_ const LARGE_INTEGER* presentTargetTime, _Out_ BOOL* contentDirty)329{330*contentDirty = m_contentDirty;331if(m_contentDirty)332{333ProcessFrame();334}335m_contentDirty = false;336return S_OK;337}338339HRESULT Direct3DInterop::GetTexture(_In_ const DrawingSurfaceSizeF* size, _Out_ IDrawingSurfaceSynchronizedTextureNative** synchronizedTexture, _Out_ DrawingSurfaceRectF* textureSubRectangle)340{341m_renderer->Update();342m_renderer->Render();343return S_OK;344}345346ID3D11Texture2D* Direct3DInterop::GetTexture()347{348return m_renderer->GetTexture();349}350}351352353