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 "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 UnityEngine.XR.WSA.WebCam.Mode welchem Modus sich die Kamera derzeit in Unity 2018 und früher oder UnityEngine.Windows.WebCam.Mode in Unity 2019 und höher befindet. Verfügbare Modi sind Foto, Video oder keiner.

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 Stillfotos machen. Das allgemeine Muster für die Verwendung von PhotoCapture zum Aufnehmen eines Fotos ist wie folgt:

  1. Erstellen eines PhotoCapture-Objekts
  2. Erstellen eines CameraParameters-Objekts mit den gewünschten Einstellungen
  3. Starten des Fotomodus über StartPhotoModeAsync
  4. Nehmen Sie das gewünschte Foto auf
    • (optional) Interagieren mit diesem Bild
  5. Beenden des Fotomodus und sauber 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 sauber-Up-Code, der hier dargestellt wird.

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

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

Aufnehmen eines Fotos in einer Datei

Der einfachste Vorgang besteht darin, ein Foto direkt in eine Datei aufzunehmen. Das Foto kann als JPG oder PNG gespeichert werden.

Wenn Sie den Fotomodus erfolgreich gestartet haben, machen 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 sauber Sie Ihre Objekte auf.

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 einer Textur2D mit Position

Beim Erfassen von Daten in einer Textur2D ähnelt der Prozess der Aufzeichnung mit dem Datenträger.

Führen Sie den oben beschriebenen Setupvorgang aus.

Erfassen Sie in OnPhotoModeStarted einen Frame in den 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 sauber-Up-Code.

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 der Szene zu platzieren und sie mithilfe der result.success verwertbaren 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 ihren Foren bereitgestellt.

Aufnehmen eines Fotos und Interagieren mit den rohen Bytes

Führen Sie die gleichen Setupschritte wie oben und OnPhotoModeStarted aus, um mit den rohen Bytes eines In-Memory-Frames zu interagieren, wie beim Aufzeichnen eines Fotos in einer Textur2D.To interact with the raw bytes of a memory frame, the same setup steps as above and OnPhotoModeStarted as beim Aufzeichnen eines Fotos in a Texture2D. Der Unterschied besteht in OnCapturedPhotoToMemory , wo Sie die rohen Bytes abrufen 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
Typ:VideoCapture

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

  1. Erstellen eines VideoCapture-Objekts
  2. Erstellen eines CameraParameters-Objekts mit den gewünschten Einstellungen
  3. Starten des Videomodus über StartVideoModeAsync
  4. Videoaufnahme starten
  5. Videoaufzeichnung beenden
  6. Beenden des Videomodus und sauber 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 benötigen und starten möchten.

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 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 sollten Sie die Aufzeichnung mit einem Timer oder einer Benutzereingabe für instance beenden.

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

Sobald die Aufzeichnung beendet wurde, beenden Sie den Videomodus, und sauber Ihre Ressourcen auf.

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

  • Keine Auflösungen verfügbar
    • Stellen Sie sicher, dass die WebCam-Funktion in Ihrem Projekt angegeben ist.

Nächster Entwicklungsprüfpunkt

Wenn Sie die von uns vorgestellte Unity-Entwicklungsprüfpunktreise verfolgen, sind Sie gerade dabei, die Mixed Reality Plattformfunktionen und APIs zu erkunden. 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