Zdjęcie Aparat wideo w aparacie Unity

Włączanie możliwości dostępu do aparatu

Możliwość "WebCam" musi być zadeklarowana, aby aplikacja korzystała z aparatu.

  1. W Edytorze aparatu Unity przejdź do ustawień odtwarzacza, przechodząc do strony "Edytuj > odtwarzacz ustawień > projektu"
  2. Wybierz kartę "Sklep Windows"
  3. W sekcji "Możliwości ustawień > publikowania" sprawdź możliwości aplikacji WebCam i mikrofonu

W danym momencie może wystąpić tylko jedna operacja z aparatem. Możesz sprawdzić, w którym trybie aparat jest aktualnie włączony UnityEngine.XR.WSA.WebCam.Mode w środowisku Unity 2018 i nowszym lub UnityEngine.Windows.WebCam.Mode w środowisku Unity 2019 lub nowszym. Dostępne tryby to zdjęcia, wideo lub brak.

Przechwytywanie zdjęć

Przestrzeń nazw (przed aparatem Unity 2019):UnityEngine.XR.WSA.WebCam
Przestrzeń nazw (Unity 2019 i nowsze):UnityEngine.Windows.WebCam
Type:PhotoCapture

Typ PhotoCapture umożliwia robienie zdjęć z aparatem fotograficznym wideo. Ogólny wzorzec używania funkcji PhotoCapture do wykonania zdjęcia jest następujący:

  1. Tworzenie obiektu PhotoCapture
  2. Utwórz obiekt CameraParameters z żądanymi ustawieniami
  3. Uruchamianie trybu zdjęć za pomocą polecenia StartPhotoModeAsync
  4. Wykonaj zdjęcie, które chcesz wykonać
    • (opcjonalnie) Interakcja z tym obrazem
  5. Zatrzymywanie trybu zdjęć i czyszczenie zasobów

Typowe konfigurowanie aplikacji PhotoCapture

W przypadku wszystkich trzech zastosowań zacznij od tych samych pierwszych trzech kroków powyżej

Zacznij od utworzenia obiektu PhotoCapture

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

Następnie zapisz obiekt, ustaw parametry i uruchom tryb fotografii

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);
}

W końcu użyjesz również tego samego kodu czyszczenia przedstawionego tutaj

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

Po wykonaniu tych kroków możesz wybrać typ zdjęcia do przechwycenia.

Przechwytywanie zdjęcia do pliku

Najprostszą operacją jest przechwycenie zdjęcia bezpośrednio do pliku. Zdjęcie można zapisać jako JPG lub PNG.

Jeśli tryb zdjęć został pomyślnie uruchomiony, wykonaj zdjęcie i zapisz je na dysku

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!");
    }
}

Po przechwyceniu zdjęcia na dysku zamknij tryb zdjęć, a następnie wyczyść obiekty

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");
    }
}

Przechwytywanie zdjęcia do tekstury 2D z lokalizacją

Podczas przechwytywania danych do funkcji Texture2D proces jest podobny do przechwytywania na dysku.

Postępuj zgodnie z powyższym procesem instalacji.

W obszarze OnPhotoModeStarted przechwyć ramkę do pamięci.

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

Następnie zastosujesz wynik do tekstury i użyjesz wspólnego kodu czyszczenia powyżej.

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);
}

Aparat lokalizowalny

Aby umieścić tę teksturę w scenie i wyświetlić ją przy użyciu macierzy aparatów lokalizacyjnej, dodaj następujący kod do elementu OnCapturedPhotoToMemory w czeku result.success :

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);
}

Aparat Unity dostarczył przykładowy kod do zastosowania macierzy projekcji do określonego cieniowania na forach.

Przechwytywanie zdjęcia i interakcja z nieprzetworzonymi bajtami

Aby korzystać z nieprzetworzonych bajtów w ramce pamięci, wykonaj te same kroki konfiguracji co powyżej i OnPhotoModeStarted , jak w przechwytywaniu zdjęcia do tekstury2D. Różnica dotyczy elementu OnCapturedPhotoToMemory , gdzie można uzyskać nieprzetworzone bajty i korzystać z nich.

W tym przykładzie utworzysz listę , która będzie dalej przetwarzana lub stosowana do tekstury za pośrednictwem metody SetPixels()

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);
}

Przechwytywanie wideo

Przestrzeń nazw (przed aparatem Unity 2019):UnityEngine.XR.WSA.WebCam
Przestrzeń nazw (Unity 2019 i nowsze):UnityEngine.Windows.WebCam
Type:VideoCapture

Funkcje VideoCapture podobne do PhotoCapture. Jedyną różnicą jest to, że musisz określić wartość ramki na sekundę (FPS) i można zapisać tylko bezpośrednio na dysku jako plik .mp4. Kroki korzystania z narzędzia VideoCapture są następujące:

  1. Tworzenie obiektu VideoCapture
  2. Utwórz obiekt CameraParameters z żądanymi ustawieniami
  3. Uruchamianie trybu wideo za pomocą polecenia StartVideoModeAsync
  4. Rozpocznij nagrywanie wideo
  5. Zatrzymywanie nagrywania wideo
  6. Zatrzymywanie trybu wideo i czyszczenie zasobów

Zacznij od utworzenia obiektu VideoCapture VideoCapture m_VideoCapture = null;

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

Następnie skonfiguruj parametry, które będą potrzebne do nagrywania i uruchamiania.

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!");
    }
}

Po uruchomieniu rozpocznij nagrywanie

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);
    }
}

Po rozpoczęciu nagrywania możesz zaktualizować interfejs użytkownika lub zachowania, aby włączyć zatrzymywanie. W tym miejscu po prostu logujesz się.

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.
}

W późniejszym momencie należy zatrzymać nagrywanie przy użyciu czasomierza lub danych wejściowych użytkownika, na przykład.

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

Po zatrzymaniu nagrywania zatrzymaj tryb wideo i wyczyść zasoby.

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;
}

Rozwiązywanie problemów

  • Nie są dostępne żadne rozwiązania
    • Upewnij się, że w projekcie określono funkcję WebCam .

Następny punkt kontrolny programowania

Jeśli obserwujesz określoną przez nas podróż do punktu kontrolnego tworzenia aparatu Unity, jesteś w trakcie eksplorowania możliwości platformy Mixed Reality i interfejsów API. W tym miejscu możesz przejść do następnego tematu:

Możesz też przejść bezpośrednio do wdrożenia aplikacji na urządzeniu lub emulatorze:

Zawsze możesz wrócić do punktów kontrolnych programowania aparatu Unity w dowolnym momencie.

Zobacz też