2012-03-25 5 views
3

Ich versuche, Bildbearbeitungseffekte in Windows 8 App direkt auf Kamera-Feeds anzuwenden. Ich habe einen Weg mit Canvas und Neuzeichnen von Bildern nach dem Anwenden von Effekten aus der Webcam direkt versucht. Aber dieser Ansatz funktioniert gut für grundlegende Effekte, aber für Effekte wie Kantenerkennung erzeugt er große Verzögerung und Flimmern während der Verwendung von Leinwand-Ansatz.Wie kann man Bildeffekte wie Kantenerkennung in der Windows 8 App auf den Kamerastrom anwenden?

Andere Möglichkeit ist MFT (Media Foundation Transformation) zu erstellen, aber es kann in C implementiert werden, über die ich keine Ahnung habe.

Kann mir jemand sagen, wie kann ich mein Ziel erreichen Auswirkungen auf die Webcam-Stream direkt in Windows 8 Metro-Stil App Anwendung entweder durch Leinwand Ansatz zu verbessern, so dass große Effekte wie Kantenerkennung don keine Probleme haben oder wie kann ich MFT anwenden in C#, da ich an C# Sprache oder durch einen anderen Ansatz gearbeitet habe?

+0

Können Sie mir sagen, wie Sie es geschafft haben, die Kantenerkennung auf dem Bild zu machen? – kalyan

Antwort

6

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.

+0

Vielen Dank für die Antwort. Ich muss nur wissen, wie MediaCapture.CapturePhotoToStreamAsync() für meine Kantenerkennung Algorithmus auf Kamera-Feeds durchführen wird. Ich benutze Faltungsfilter. Wird es gut genug Leistung für Kamera-Feed von 720 * 481 sein? Ich werde direkt die Auswirkungen auf die Kamera-Feeds zeigen. –

+0

Richtig, bitte teilen Sie was Sie herausfinden! –

+0

Ein verwandter Artikel von Jeremiah Morrill ist auch hier verfügbar: http://jeremiamohorrill.wordpress.com/2012/04/25/gpu-accelerated-media-effects-in-windows-8-metro/ –

1

Soweit ich weiß, müssen MFTs in C++ implementiert werden. Ich glaube, dass es ein SDK-Sample für die Medienumwandlung gibt, das die Implementierung einiger unkomplizierter Transformationen aus einer Anwendung im Metro-Stil zeigt.

Verwandte Themen