Foto videokamera v Unity

Povolení funkce pro přístup ke kameře

Aby aplikace používala kameru, musí být deklarována funkce WebCam.

  1. V Unity Editoru přejděte na nastavení přehrávače tak, že přejdete na stránku Upravit > přehrávač nastavení > projektu.
  2. Vyberte kartu Windows Store.
  3. V části Možnosti nastavení > publikování zkontrolujte možnosti WebCam a Mikrofon .

S kamerou může najednou probíhat pouze jedna operace. V Unity 2018 a starších verzích nebo UnityEngine.Windows.WebCam.Mode v Unity 2019 a novějších verzích můžete zkontrolovat, ve UnityEngine.XR.WSA.WebCam.Mode kterém režimu je kamera aktuálně zapnutá. Dostupné režimy jsou fotka, video nebo žádný.

Zachycení fotek

Obor názvů (před Unity 2019):UnityEngine.XR.WSA.WebCam
Obor názvů (Unity 2019 a novější):UnityEngine.Windows.WebCam
Typ:PhotoCapture

Typ PhotoCapture umožňuje pořizovat fotografie pomocí fotokamery. Obecný vzor použití photoCapture k pořízení fotky je následující:

  1. Vytvoření objektu PhotoCapture
  2. Vytvoření objektu CameraParameters s požadovaným nastavením
  3. Spuštění foto režimu přes StartPhotoModeAsync
  4. Pořízení požadované fotky
    • (volitelné) Interakce s tímto obrázkem
  5. Zastavení foto režimu a vyčištění prostředků

Běžné nastavení pro PhotoCapture

Pro všechny tři použití začněte stejnými prvními třemi kroky výše.

Začněte vytvořením objektu PhotoCapture .

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

Dále uložte objekt, nastavte parametry a spusťte režim fotografie.

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

Nakonec také použijete stejný kód pro vyčištění, který je zde uvedený.

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

Po provedení těchto kroků můžete zvolit, jaký typ fotky chcete zachytit.

Zachycení fotky do souboru

Nejjednodušší je zachytit fotku přímo do souboru. Fotku je možné uložit jako JPG nebo PNG.

Pokud jste úspěšně spustili režim fotky, pořiďte fotku a uložte ji na disk.

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 zachycení fotky na disk ukončete režim fotky a pak vyčistěte objekty.

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

Zachycení fotky do Textury2D s umístěním

Při zachytávání dat do Textury2D se proces podobá zachycení na disk.

Postupujte podle výše uvedeného postupu nastavení.

V OnPhotoModeStarted zachyťte snímek do paměti.

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

Výsledek pak použijete na texturu a použijete výše uvedený běžný kód pro čištění.

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

Lokalizovatelná kamera

Pokud chcete umístit tuto texturu do scény a zobrazit ji pomocí lokatable kamerových matic, přidejte do složky OnCapturedPhotoToMemory v result.success kontrole následující kód:

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 poskytla ukázkový kód pro použití matice projekce na konkrétní shader na svých fórech.

Zachycení fotky a interakce s nezpracovanými bajty

Pokud chcete pracovat s nezpracovanými bajty v rámci paměti, postupujte podle stejných kroků nastavení jako výše a OnPhotoModeStarted jako při zachycení fotky do textury Texture2D. Rozdíl je v OnCapturedPhotoToMemory , kde můžete získat nezpracované bajty a pracovat s nimi.

V tomto příkladu vytvoříte seznam , který se bude dále zpracovávat nebo aplikovat na texturu přes 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);
}

Záznam videa

Obor názvů (před Unity 2019):UnityEngine.XR.WSA.WebCam
Obor názvů (Unity 2019 a novější):UnityEngine.Windows.WebCam
Typ:VideoCapture

VideoCapture funguje podobně jako PhotoCapture. Jedinými dvěma rozdíly jsou, že musíte zadat hodnotu Snímků za sekundu (FPS) a můžete uložit pouze přímo na disk jako soubor .mp4. Postup použití videocapture je následující:

  1. Vytvoření objektu VideoCapture
  2. Vytvoření objektu CameraParameters s požadovaným nastavením
  3. Spuštění video režimu přes StartVideoModeAsync
  4. Spustit nahrávání videa
  5. Zastavit nahrávání videa
  6. Zastavení video režimu a vyčištění prostředků

Začněte vytvořením objektu VideoCapture VideoCapturem_VideoCapture = null;

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

Dále nastavte parametry, které budete potřebovat pro nahrávání, a spusťte ho.

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 spuštění zahajte nahrávání.

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 spuštění nahrávání můžete aktualizovat uživatelské rozhraní nebo chování a povolit zastavení. Tady se jen zapíšete.

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

Později budete chtít záznam zastavit například pomocí časovače nebo uživatelského vstupu.

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

Jakmile se nahrávání zastaví, zastavte režim videa a vyčistěte prostředky.

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

Poradce při potížích

  • Nejsou k dispozici žádná řešení.
    • Ujistěte se, že je v projektu zadaná funkce WebCam .

Další kontrolní bod vývoje

Pokud sledujete kontrolní bod vývoje Unity, který jsme si vytyčili, jste uprostřed zkoumání Mixed Reality funkcí platformy a rozhraní API. Odtud můžete pokračovat k dalšímu tématu:

Nebo přejděte přímo k nasazení aplikace do zařízení nebo emulátoru:

Kdykoli se můžete vrátit k kontrolním bodům vývoje Unity .

Viz také