Kamera Video Foto di Unity

Mengaktifkan kemampuan untuk akses kamera

Kemampuan "WebCam" harus dideklarasikan agar aplikasi dapat menggunakan kamera.

  1. Di Editor Unity, buka pengaturan pemutar dengan menavigasi ke halaman "Edit > Pemutar Pengaturan > Proyek"
  2. Pilih tab "Bursa Windows"
  3. Di bagian "Kemampuan Pengaturan > Penerbitan", periksa kemampuan WebCam dan Mikrofon

Hanya satu operasi yang dapat terjadi dengan kamera pada satu waktu. Anda dapat memeriksa mode mana kamera saat ini berada di UnityEngine.XR.WSA.WebCam.Mode Unity 2018 dan yang lebih lama atau UnityEngine.Windows.WebCam.Mode di Unity 2019 dan yang lebih baru. Mode yang tersedia adalah foto, video, atau tidak ada.

Pengambilan foto

Namespace (sebelum Unity 2019):UnityEngine.XR.WSA.WebCam
Namespace (Unity 2019 dan yang lebih baru):UnityEngine.Windows.WebCam
Type:PhotoCapture

Jenis PhotoCapture memungkinkan Anda untuk mengambil foto diam dengan Kamera Video Foto. Pola umum untuk menggunakan PhotoCapture untuk mengambil foto adalah sebagai berikut:

  1. Membuat objek PhotoCapture
  2. Membuat objek CameraParameters dengan pengaturan yang Anda inginkan
  3. Mulai Mode Foto melalui StartPhotoModeAsync
  4. Ambil foto yang Anda inginkan
    • (opsional) Berinteraksi dengan gambar tersebut
  5. Hentikan Mode Foto dan bersihkan sumber daya

Pengaturan umum untuk PhotoCapture

Untuk ketiga kegunaannya, mulailah dengan tiga langkah pertama yang sama di atas

Mulailah dengan membuat objek PhotoCapture

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

Selanjutnya, simpan objek Anda, atur parameter Anda, dan mulai Mode Foto

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

Pada akhirnya, Anda juga akan menggunakan kode pembersihan yang sama yang disajikan di sini

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

Setelah langkah-langkah ini, Anda dapat memilih jenis foto mana yang akan diambil.

Mengambil foto ke file

Operasi paling sederhana adalah mengambil foto langsung ke file. Foto dapat disimpan sebagai JPG atau PNG.

Jika Anda berhasil memulai mode foto, ambil foto dan simpan di 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!");
    }
}

Setelah mengambil foto ke disk, keluar dari mode foto lalu bersihkan objek Anda

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

Mengambil foto ke Texture2D dengan lokasi

Saat mengambil data ke Texture2D, prosesnya mirip dengan menangkap disk.

Ikuti proses penyiapan di atas.

Di OnPhotoModeStarted, ambil bingkai ke memori.

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

Anda kemudian akan menerapkan hasil Anda ke tekstur dan menggunakan kode pembersihan umum di atas.

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

Kamera yang dapat di-locatable

Untuk menempatkan tekstur ini dalam adegan dan menampilkannya menggunakan matriks kamera yang dapat di-locatable, tambahkan kode berikut ke OnCapturedPhotoToMemory dalam result.success pemeriksaan:

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 telah menyediakan kode sampel untuk menerapkan matriks proyeksi ke shader tertentu di forum mereka.

Mengambil foto dan berinteraksi dengan byte mentah

Untuk berinteraksi dengan byte mentah dari bingkai memori, ikuti langkah-langkah penyiapan yang sama seperti di atas dan OnPhotoModeStarted seperti dalam menangkap foto ke Texture2D. Perbedaannya ada di OnCapturedPhotoToMemory di mana Anda bisa mendapatkan byte mentah dan berinteraksi dengannya.

Dalam contoh ini, Anda akan membuat Daftar untuk diproses lebih lanjut atau diterapkan ke tekstur melalui 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);
}

Pengambilan video

Namespace (sebelum Unity 2019):UnityEngine.XR.WSA.WebCam
Namespace (Unity 2019 dan yang lebih baru):UnityEngine.Windows.WebCam
Type:VideoCapture

Fungsi VideoCapture mirip dengan PhotoCapture. Satu-satunya dua perbedaan adalah Anda harus menentukan nilai Frame Per Second (FPS) dan Anda hanya dapat menyimpan langsung ke disk sebagai file .mp4. Langkah-langkah untuk menggunakan VideoCapture adalah sebagai berikut:

  1. Membuat objek VideoCapture
  2. Membuat objek CameraParameters dengan pengaturan yang Anda inginkan
  3. Mulai Mode Video melalui StartVideoModeAsync
  4. Mulai merekam video
  5. Berhenti merekam video
  6. Hentikan Mode Video dan bersihkan sumber daya

Mulailah dengan membuat objek VideoCapture kami VideoCapture m_VideoCapture = null;

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

Selanjutnya, siapkan parameter yang Anda inginkan untuk perekaman dan mulai.

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

Setelah dimulai, mulai rekaman

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

Setelah perekaman dimulai, Anda dapat memperbarui UI atau perilaku Anda untuk mengaktifkan penghentian. Di sini Anda hanya log.

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

Di titik selanjutnya, Anda mungkin ingin menghentikan rekaman menggunakan timer atau input pengguna, misalnya.

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

Setelah perekaman berhenti, hentikan mode video dan bersihkan sumber daya Anda.

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

Pemecahan Masalah

  • Tidak ada resolusi yang tersedia
    • Pastikan kemampuan WebCam ditentukan dalam proyek Anda.

Titik Pemeriksaan Pengembangan Berikutnya

Jika Anda mengikuti perjalanan titik pemeriksaan pengembangan Unity yang telah kami susun, Anda berada di tengah-tengah menjelajahi kemampuan platform dan API Mixed Reality. Dari sini, Anda dapat melanjutkan ke topik berikutnya:

Atau lompat langsung untuk menyebarkan aplikasi Anda di perangkat atau emulator:

Anda selalu dapat kembali ke titik pemeriksaan pengembangan Unity kapan saja.

Lihat juga