Ich habe in der letzten Woche gerade ziemlich viel in diesem Bereich gespielt und sogar darüber nachgedacht, einen Blogbeitrag darüber zu schreiben. Ich denke, diese Antwort kann genauso gut sein.
Sie können den MFT-Weg gehen, der in C++ erledigt werden muss, aber die Dinge, die Sie schreiben müssten, wären zwischen C# und C++ nicht sehr verschieden. Das einzige, was zu beachten ist, ist, dass die MFT im YUV-Farbraum arbeitet, so dass sich Ihre typischen Convolution-Filter/-Effekte etwas anders verhalten oder eine Konvertierung in RGB erfordern. Wenn Sie sich für diese Route entscheiden Auf der C# -Anwendungsseite müssen Sie nur MediaCapture.AddEffectAsync() aufrufen. Nun, das und Sie müssen Ihre Package.appxmanifest usw. bearbeiten, aber lassen Sie uns mit den ersten Dingen zuerst gehen.
Wenn Sie auf die Media capture using webcam sample schauen - es tut schon, was Sie brauchen. Es wendet einen Graustufeneffekt auf Ihren Kamera-Feed an. Es enthält ein C++ - MFT-Projekt, das in einer Anwendung verwendet wird, die in der C# -Version verfügbar ist. Ich musste den Effekt auf ein MediaElement anwenden, das möglicherweise nicht das ist, was Sie brauchen, aber genauso einfach - rufen Sie MediaElement.AddVideoEffect() auf und Ihre Videodatei-Wiedergabe wendet jetzt den Graustufeneffekt an. Um die MFT verwenden - Sie müssen einfach einen Verweis auf das GrayscaleTransform Projekt hinzufügen und folgende Zeilen zu Ihrer appxmanifest hinzufügen:
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>GrayscaleTransform.dll</Path>
<ActivatableClass ActivatableClassId="GrayscaleTransform.GrayscaleEffect" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
Wie der MFT-Code funktioniert:
Die folgenden Zeilen erzeugen ein Pixel Farbtransformationsmatrix
Je nach Pixelformat des Video-Feeds wird eine andere Transformationsmethode zum Scannen der Pixel ausgewählt. Suchen Sie nach diesen Zeilen:
m_pTransformFn = TransformImage_YUY2;
m_pTransformFn = TransformImage_UYVY;
m_pTransformFn = TransformImage_NV12;
Für meine Probe M4V-Datei - das Format wird als NV12 erkannt, so dass er ruft TransformImage_NV12.
Für Pixel innerhalb des spezifizierten Bereichs (m_rcDest) oder innerhalb des gesamten Bildschirms, wenn kein Bereich angegeben wurde - rufen die Methoden TransformImage_ ~ TransformChroma (mat, & u, & v). Für andere Pixel - die Werte vom Originalbild werden kopiert.
TransformChroma transformiert die Pixel mit m_transform.Wenn Sie den Effekt ändern möchten - Sie können einfach die Matrix m_transform ändern oder wenn Sie wie in einem Kantenerkennungsfilter Zugriff auf benachbarte Pixel benötigen - ändern Sie die TransformImage_-Methoden, um diese Pixel zu verarbeiten.
Dies ist eine Möglichkeit, dies zu tun. Ich denke, es ist ziemlich CPU-intensiv, also persönlich bevorzuge ich es, einen Pixel-Shader für solche Operationen zu schreiben. Wie wenden Sie einen Pixel-Shader auf einen Videostream an? Nun, ich bin noch nicht ganz da, aber ich glaube, dass du transfer video frames auf eine DirectX-Oberfläche ziemlich leicht und später einen Pixel-Shader aufrufen kannst. Bisher konnte ich die Videoframes übertragen und hoffe, die Shader nächste Woche anwenden zu können. Ich könnte einen Blogeintrag darüber schreiben. Ich nahm die meplayer-Klasse von der Media engine native C++ playback sample und verschoben es zu einem Vorlage C++ DirectX-Projekt in eine WinRTComponent-Bibliothek konvertiert, dann mit einer C#/XAML-Anwendung, die Swapchain-Klasse, die SwapChainBackgroundPanel erstellt, die ich im C# -Projekt verwendet um das Video anzuzeigen. Ich musste einige Änderungen in der Meplayer-Klasse vornehmen. Erstens - ich musste es in einen öffentlichen Namespace verschieben, der es anderen Assemblys zur Verfügung stellen würde. Dann hatte ich die swapchain es in ein Format für die Verwendung mit einem SwapChainBackgroundPanel akzeptiert erstellt zu ändern:
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = m_rcTarget.right;
swapChainDesc.Height = m_rcTarget.bottom;
// Most common swapchain format is DXGI_FORMAT_R8G8B8A8-UNORM
swapChainDesc.Format = m_d3dFormat;
swapChainDesc.Stereo = false;
// Don't use Multi-sampling
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
//swapChainDesc.BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // Allow it to be used as a render target.
// Use more than 1 buffer to enable Flip effect.
//swapChainDesc.BufferCount = 4;
swapChainDesc.BufferCount = 2;
//swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Flags = 0;
Endlich - statt Aufruf CreateSwapChainForCoreWindow - Ich rufe CreateSwapChainForComposition und Zuordnen der swapchain mit meinem SwapChainBackgroundPanel:
// Create the swap chain and then associate it with the SwapChainBackgroundPanel.
DX::ThrowIfFailed(
spDXGIFactory.Get()->CreateSwapChainForComposition(
spDevice.Get(),
&swapChainDesc,
nullptr, // allow on all displays
&m_spDX11SwapChain)
);
ComPtr<ISwapChainBackgroundPanelNative> dxRootPanelAsSwapChainBackgroundPanel;
// Set the swap chain on the SwapChainBackgroundPanel.
reinterpret_cast<IUnknown*>(m_swapChainPanel)->QueryInterface(
IID_PPV_ARGS(&dxRootPanelAsSwapChainBackgroundPanel)
);
DX::ThrowIfFailed(
dxRootPanelAsSwapChainBackgroundPanel->SetSwapChain(m_spDX11SwapChain.Get())
);
* EDIT folgt
Forgot über eine weitere Sache. Wenn Sie herausfinden möchten, wie Sie Frames in eine WriteableBitmap aufnehmen (indem Sie beispielsweise MediaCapture.CapturePhotoToStreamAsync() mit einem MemoryStream aufrufen und anschließend WriteableBitmap aufrufen. SetSource() im Stream), können Sie Ihre Bilder mit WriteableBitmapEx bearbeiten. Es ist vielleicht keine Spitzenleistung, aber wenn Ihre Auflösung nicht zu hoch ist oder Ihre Bildrate nicht hoch genug ist, reicht das vielleicht aus. Das Projekt auf CodePlex unterstützt WinRT noch nicht offiziell, aber ich habe eine Version, die funktionieren sollte, dass Sie here (Dropbox) versuchen können.
Können Sie mir sagen, wie Sie es geschafft haben, die Kantenerkennung auf dem Bild zu machen? – kalyan