Zdjęcie Aparat wideo w aparacie Unity

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

Aby aplikacja korzystała z aparatu, należy zadeklarować możliwość "WebCam".

  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 aparacie Unity 2018 i nowszym lub UnityEngine.Windows.WebCam.Mode w aparacie 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
Typ: PhotoCapture

Typ PhotoCapture umożliwia robienie zdjęć z aparatem fotograficznym. Ogólny wzorzec używania aplikacji 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 trzech pierwszych 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 oczyszczania 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 uchwyceniu 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 tekstury2D z lokalizacją

Podczas przechwytywania danych do tekstury2D proces jest podobny do przechwytywania na dysku.

Postępuj zgodnie z powyższym procesem konfiguracji.

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 oczyszczania 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 lokalizowalnych, dodaj następujący kod do kontrolki 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 wchodzić w interakcje z nieprzetworzonymi bajtami 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 , w którym można uzyskać nieprzetworzone bajty i wchodzić z nimi w interakcje.

W tym przykładzie utworzysz listę do dalszego przetworzenia lub zastosowania do tekstury za pomocą 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
Typ: VideoCapture

Funkcje VideoCapture podobnie jak PhotoCapture. Jedyną różnicą jest to, że należy określić wartość Frame Per Second (FPS) i można zapisać bezpośrednio na dysku jako plik .mp4. Kroki korzystania z usługi 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. Zatrzymaj nagrywanie 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 wystarczy się zalogować.

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 nagrania 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

  • Brak dostępnych rozwiązań
    • Upewnij się, że w projekcie określono funkcję WebCam .

Następny punkt kontrolny programowania

Jeśli obserwujesz określoną podróż do punktu kontrolnego tworzenia aparatu Unity, jesteś w trakcie eksplorowania możliwości i interfejsów API platformy rzeczywistości mieszanej. 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ż