Foto-/Videokamera in Unity

Aktivieren der Funktion für den Kamerazugriff

Die Funktion "WebCam" muss deklariert werden, damit eine App die Kamera verwenden kann.

  1. Navigieren Sie im Unity-Editor zu den Playereinstellungen, indem Sie zur Seite "Project Einstellungen >> Player bearbeiten" navigieren.
  2. Wählen Sie die Registerkarte "Windows Store" aus.
  3. Überprüfen Sie im Abschnitt "Einstellungen > Funktionen" die WebCam- und Mikrofonfunktionen.

Es kann immer nur ein einzelner Vorgang mit der Kamera erfolgen. Sie können überprüfen, in welchem Modus sich die Kamera derzeit in UnityEngine.XR.WSA.WebCam.Mode Unity 2018 UnityEngine.Windows.WebCam.Mode und früher oder in Unity 2019 und höher befindet. Verfügbare Modi sind Foto, Video oder keine.

Fotoaufnahme

Namespace (vor Unity 2019):UnityEngine.XR.WSA.WebCam
Namespace (Unity 2019 und höher):UnityEngine.Windows. Webcam
Typ:PhotoCapture

Mit dem PhotoCapture-Typ können Sie mit der Fotovideokamera weiterhin Fotos machen. Das allgemeine Muster für die Verwendung von PhotoCapture zum Foto ist wie folgt:

  1. Erstellen eines PhotoCapture-Objekts
  2. Erstellen eines CameraParameters-Objekts mit den von Ihnen ausgewählten Einstellungen
  3. Starten des Fotomodus über StartPhotoModeAsync
  4. Nehmen Sie das Foto auf, das Sie möchten.
    • (optional) Interagieren mit diesem Bild
  5. Beenden des Fotomodus und Bereinen von Ressourcen

Allgemeine Einrichtung für PhotoCapture

Beginnen Sie für alle drei Verwendungen mit den gleichen ersten drei Schritten oben.

Erstellen Sie zunächst ein PhotoCapture-Objekt .

private void Start()
{
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

Speichern Sie als Nächstes Ihr Objekt, legen Sie Ihre Parameter fest, und starten Sie den Fotomodus.

private PhotoCapture photoCaptureObject = null;

void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

    Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

    CameraParameters c = new CameraParameters();
    c.hologramOpacity = 0.0f;
    c.cameraResolutionWidth = cameraResolution.width;
    c.cameraResolutionHeight = cameraResolution.height;
    c.pixelFormat = CapturePixelFormat.BGRA32;

    captureObject.StartPhotoModeAsync(c, false, OnPhotoModeStarted);
}

Am Ende verwenden Sie auch den gleichen Bereinigungscode, der hier dargestellt wird.

void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
    photoCaptureObject.Dispose();
    photoCaptureObject = null;
}

Nach diesen Schritten können Sie auswählen, welcher Fototyp erfasst werden soll.

Aufnehmen eines Fotos in einer Datei

Der einfachste Vorgang besteht im erfassen eines Fotos direkt in einer Datei. Das Foto kann als JPG oder PNG gespeichert werden.

Wenn Sie den Fotomodus erfolgreich gestartet haben, erstellen Sie ein Foto, und speichern Sie es auf dem Datenträger.

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format(@"CapturedImage{0}_n.jpg", Time.time);
        string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

Nachdem Sie das Foto auf dem Datenträger erfasst haben, beenden Sie den Fotomodus, und bereinigtEn Sie ihre Objekte.

void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        Debug.Log("Saved Photo to disk!");
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }
    else
    {
        Debug.Log("Failed to save Photo to disk");
    }
}

Aufnehmen eines Fotos auf einem Texture2D mit Standort

Beim Erfassen von Daten in einem Texture2D ähnelt der Prozess der Erfassung auf dem Datenträger.

Führen Sie den oben beschriebenen Setupvorgang aus.

Erfassen Sie in OnPhotoModeStarted einen Frame im Arbeitsspeicher.

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

Anschließend wenden Sie Ihr Ergebnis auf eine Textur an und verwenden den oben genannten allgemeinen Bereinigungscode.

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        // Create our Texture2D for use and set the correct resolution
        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
        // Copy the raw image data into our target texture
        photoCaptureFrame.UploadImageDataToTexture(targetTexture);
        // Do as we wish with the texture such as apply it to a material, etc.
    }
    // Clean up
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

Ausrichtbare Kamera

Fügen Sie onCapturedPhotoToMemory in der Überprüfung den folgenden Code hinzu, um diese Textur in result.success der Szene zu platzieren und mithilfe der verteilbaren Kameramatrizen anzuzeigen:

if (photoCaptureFrame.hasLocationData)
{
    photoCaptureFrame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix);

    Vector3 position = cameraToWorldMatrix.GetColumn(3) - cameraToWorldMatrix.GetColumn(2);
    Quaternion rotation = Quaternion.LookRotation(-cameraToWorldMatrix.GetColumn(2), cameraToWorldMatrix.GetColumn(1));

    photoCaptureFrame.TryGetProjectionMatrix(Camera.main.nearClipPlane, Camera.main.farClipPlane, out Matrix4x4 projectionMatrix);
}

Unity hat Beispielcode zum Anwenden der Projektionsmatrix auf einen bestimmten Shader in seinen Foren bereitgestellt.

Aufnehmen eines Fotos und Interagieren mit den rohen Bytes

Um mit den unformatierten Bytes eines im Arbeitsspeicherrahmen zu interagieren, führen Sie die gleichen Einrichtungsschritte wie oben und OnPhotoModeStarted wie beim Erfassen eines Fotos in einem Texture2D aus. Der Unterschied besteht in OnCapturedPhotoToMemory , wo Sie die unformatierten Bytes erhalten und mit ihnen interagieren können.

In diesem Beispiel erstellen Sie eine Liste, die über SetPixels() weiter verarbeitet oder auf eine Textur angewendet werden soll.

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        List<byte> imageBufferList = new List<byte>();
        // Copy the raw IMFMediaBuffer data into our empty byte list.
        photoCaptureFrame.CopyRawImageDataIntoBuffer(imageBufferList);

        // In this example, we captured the image using the BGRA32 format.
        // So our stride will be 4 since we have a byte for each rgba channel.
        // The raw image data will also be flipped so we access our pixel data
        // in the reverse order.
        int stride = 4;
        float denominator = 1.0f / 255.0f;
        List<Color> colorArray = new List<Color>();
        for (int i = imageBufferList.Count - 1; i >= 0; i -= stride)
        {
            float a = (int)(imageBufferList[i - 0]) * denominator;
            float r = (int)(imageBufferList[i - 1]) * denominator;
            float g = (int)(imageBufferList[i - 2]) * denominator;
            float b = (int)(imageBufferList[i - 3]) * denominator;

            colorArray.Add(new Color(r, g, b, a));
        }
        // Now we could do something with the array such as texture.SetPixels() or run image processing on the list
    }
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

Videoaufnahme

Namespace (vor Unity 2019):UnityEngine.XR.WSA.WebCam
Namespace (Unity 2019 und höher):UnityEngine.Windows. Webcam
Type:VideoCapture

VideoCapture funktioniert ähnlich wie PhotoCapture. Die einzigen beiden Unterschiede sind, dass Sie einen FPS-Wert (Frames Per Second) angeben müssen und sie nur direkt auf dem Datenträger als .mp4 speichern können. Die Schritte zur Verwendung von VideoCapture lauten wie folgt:

  1. Erstellen eines VideoCapture-Objekts
  2. Erstellen eines CameraParameters-Objekts mit den von Ihnen ausgewählten Einstellungen
  3. Starten des Videomodus über StartVideoModeAsync
  4. Videoaufzeichnung starten
  5. Aufzeichnung von Videos beenden
  6. Beenden des Videomodus und Bereinen von Ressourcen

Erstellen Sie zunächst das VideoCapture-ObjektVideoCapture m_VideoCapture = NULL.

void Start ()
{
    VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}

Richten Sie als Nächstes die Parameter ein, die Sie für die Aufzeichnung wünschen, und starten Sie sie.

void OnVideoCaptureCreated(VideoCapture videoCapture)
{
    if (videoCapture != null)
    {
        m_VideoCapture = videoCapture;

        Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();

        CameraParameters cameraParameters = new CameraParameters();
        cameraParameters.hologramOpacity = 0.0f;
        cameraParameters.frameRate = cameraFramerate;
        cameraParameters.cameraResolutionWidth = cameraResolution.width;
        cameraParameters.cameraResolutionHeight = cameraResolution.height;
        cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;

        m_VideoCapture.StartVideoModeAsync(cameraParameters,
                                            VideoCapture.AudioState.None,
                                            OnStartedVideoCaptureMode);
    }
    else
    {
        Debug.LogError("Failed to create VideoCapture Instance!");
    }
}

Beginnen Sie nach dem Start mit der Aufzeichnung.

void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format("MyVideo_{0}.mp4", Time.time);
        string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
    }
}

Nachdem die Aufzeichnung gestartet wurde, können Sie Ihre Benutzeroberfläche oder Verhaltensweisen aktualisieren, um das Beenden zu aktivieren. Hier protokollieren Sie einfach.

void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Started Recording Video!");
    // We will stop the video from recording via other input such as a timer or a tap, etc.
}

Zu einem späteren Zeitpunkt sollten Sie die Aufzeichnung beispielsweise mithilfe eines Timers oder einer Benutzereingabe beenden.

// The user has indicated to stop recording
void StopRecordingVideo()
{
    m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}

Nachdem die Aufzeichnung beendet wurde, beenden Sie den Videomodus, und bereinigt Ihre Ressourcen.

void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Stopped Recording Video!");
    m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}

void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    m_VideoCapture.Dispose();
    m_VideoCapture = null;
}

Problembehandlung

  • Es sind keine Lösungen verfügbar.
    • Stellen Sie sicher, dass die WebCam-Funktion in Ihrem Projekt angegeben ist.

Nächster Entwicklungsprüfpunkt

Wenn Sie die von uns an den Prüfpunkt für die Unity-Entwicklung 2017 2017 2016 2016 2016 durchgeführte Entwicklungsprozess durch die Neuen Mixed Reality Plattformfunktionen und APIs durchdrennen. Von hier aus können Sie mit dem nächsten Thema fortfahren:

Oder wechseln Sie direkt zur Bereitstellung Ihrer App auf einem Gerät oder Emulator:

Sie können jederzeit zu den Prüfpunkten für die Unity-Entwicklung zurückkehren.

Siehe auch