Freigeben über


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. Wechseln Sie im Unity-Editor zu den Spielereinstellungen, indem Sie zur Seite "Projekteinstellungen-Player > bearbeiten>" navigieren.
  2. Wählen Sie die Registerkarte "Windows Store" aus.
  3. Überprüfen Sie im Abschnitt "Funktionen für Veröffentlichungseinstellungen > " die WebCam - und Mikrofonfunktionen .

Mit der Kamera kann jeweils nur ein einzelner Vorgang ausgeführt werden. Sie können überprüfen, in welchem Modus sich die Kamera derzeit in UnityEngine.XR.WSA.WebCam.Mode Unity 2018 und früher oder UnityEngine.Windows.WebCam.Mode 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 weiterhin Fotos mit der Fotovideokamera aufnehmen. Das allgemeine Muster für die Verwendung von PhotoCapture zum Aufnehmen eines Fotos lautet wie folgt:

  1. Erstellen eines PhotoCapture-Objekts
  2. Erstellen eines CameraParameters-Objekts mit den gewünschten Einstellungen
  3. Starten des Fotomodus über StartPhotoModeAsync
  4. Aufnehmen des gewünschten Fotos
    • (optional) Interagieren mit diesem Bild
  5. Beenden des Fotomodus und Bereinigen von Ressourcen

Allgemeine Einrichtung für PhotoCapture

Beginnen Sie für alle drei Verwendungen mit denselben drei Schritten oben

Erstellen eines PhotoCapture-Objekts

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 hier vorgestellten Bereinigungscode.

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

Nach diesen Schritten können Sie auswählen, welche Art von Foto aufgenommen werden soll.

Erfassen eines Fotos in einer Datei

Der einfachste Vorgang besteht darin, ein Foto direkt in einer Datei aufzunehmen. 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 der Festplatte aufgenommen haben, beenden Sie den Fotomodus, und bereinigen Sie dann 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 in eine Texture2D mit Position

Beim Erfassen von Daten in eine Texture2D ähnelt der Prozess der Aufzeichnung auf dem Datenträger.

Folgen Sie dem oben beschriebenen Setupprozess.

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 allgemeinen Bereinigungscode oben.

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

Wenn Sie diese Textur in der Szene platzieren und mit den locatablen Kameramatrizen anzeigen möchten, fügen Sie in der result.success Prüfung den folgenden Code zu OnCapturedPhotoToMemory hinzu:

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 ihren Foren bereitgestellt.

Aufnehmen eines Fotos und Interagieren mit den unformatierten Bytes

Um mit den unformatierten Bytes eines Speicherframes zu interagieren, führen Sie die gleichen Setupschritte wie oben und OnPhotoModeStarted aus wie beim Aufnehmen eines Fotos in einer Texture2D. Der Unterschied besteht in "OnCapturedPhotoToMemory ", in dem Sie die unformatierten Bytes abrufen und mit ihnen interagieren können.

In diesem Beispiel erstellen Sie eine Liste , die weiter verarbeitet oder auf eine Textur über SetPixels() 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
Typ: VideoCapture

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

  1. Erstellen eines VideoCapture-Objekts
  2. Erstellen eines CameraParameters-Objekts mit den gewünschten Einstellungen
  3. Starten des Videomodus über StartVideoModeAsync
  4. Videoaufzeichnung starten
  5. Videoaufnahme beenden
  6. Beenden des Videomodus und Bereinigen von Ressourcen

Erstellen Sie zunächst unser VideoCapture-Objekt VideoCapture m_VideoCapture = null;

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

Richten Sie als Nächstes die gewünschten Parameter für die Aufzeichnung ein, 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 Starten 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 Ihr Verhalten aktualisieren, um das Beenden zu aktivieren. Hier melden Sie sich einfach an.

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 möchten Sie die Aufzeichnung z. B. mit einem Timer oder benutzereingaben beenden.

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

Nachdem die Aufzeichnung beendet wurde, beenden Sie den Videomodus, und bereinigen Sie 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 Auflösungen verfügbar.
    • Stellen Sie sicher, dass die WebCam-Funktion in Ihrem Projekt angegeben ist.

Nächster Entwicklungsprüfpunkt

Wenn Sie dem Weg der Unity-Entwicklungsprüfpunkte folgen, den wir eingerichtet haben, befinden Sie sich mitten in der Erkundung der Mixed Reality-Plattformfunktionen und APIs. 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