Foto videokamera i Unity

Aktivera funktionen för kameraåtkomst

Funktionen "WebCam" måste deklareras för att en app ska kunna använda kameran.

  1. I Unity-redigeraren går du till spelarinställningarna genom att gå till sidan Redigera > projektinställningar >
  2. Välj fliken "Windows Store"
  3. I avsnittet "Funktioner för publiceringsinställningar>" kontrollerar du funktionerna WebCam och Mikrofon

Endast en enda åtgärd kan utföras med kameran i taget. Du kan kontrollera vilket läge kameran för närvarande är i i UnityEngine.XR.WSA.WebCam.Mode Unity 2018 och tidigare eller UnityEngine.Windows.WebCam.Mode i Unity 2019 och senare. Tillgängliga lägen är foto, video eller inget.

Fotoinspelning

Namnområde (före Unity 2019):UnityEngine.XR.WSA.WebCam
Namnområde (Unity 2019 och senare):UnityEngine.Windows.WebCam
Typ:PhotoCapture

Med PhotoCapture-typen kan du ta stillbilder med fotovideokameran. Det allmänna mönstret för att använda PhotoCapture för att ta ett foto är följande:

  1. Skapa ett PhotoCapture-objekt
  2. Skapa ett CameraParameters-objekt med önskade inställningar
  3. Starta fotoläge via StartPhotoModeAsync
  4. Ta det foto du vill ha
    • (valfritt) Interagera med den bilden
  5. Stoppa fotoläge och rensa resurser

Gemensam konfiguration för PhotoCapture

För alla tre användningsområden börjar du med samma första tre steg ovan

Börja med att skapa ett PhotoCapture-objekt

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

Lagra sedan objektet, ange parametrarna och starta fotoläget

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

I slutändan använder du också samma rensningskod som visas här

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

Efter de här stegen kan du välja vilken typ av foto som ska avbildas.

Ta ett foto till en fil

Den enklaste åtgärden är att ta ett foto direkt till en fil. Fotot kan sparas som en JPG eller en PNG.

Om du har startat fotoläget kan du ta ett foto och lagra det på disken

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

När du har hämtat fotot till disken avslutar du fotoläget och rensar sedan objekten

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

Ta ett foto till en Texture2D med plats

När du samlar in data till en Texture2D liknar processen att samla in till disken.

Följ konfigurationsprocessen ovan.

I OnPhotoModeStarted avbildar du en ram till minnet.

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

Sedan tillämpar du resultatet på en struktur och använder den vanliga rensningskoden ovan.

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

Locatable kamera

Om du vill placera den här strukturen i scenen och visa den med hjälp av de locatable kameramatriserna lägger du till följande kod i OnCapturedPhotoToMemory i result.success kontrollen:

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 har tillhandahållit exempelkod för att tillämpa projektionsmatrisen på en specifik skuggning på sina forum.

Ta ett foto och interagera med rådatabyte

Om du vill interagera med råbyte i en minnesram följer du samma installationssteg som ovan och OnPhotoModeStarted som när du tar ett foto till en Texture2D. Skillnaden är i OnCapturedPhotoToMemory där du kan hämta rådatabyte och interagera med dem.

I det här exemplet skapar du en lista som ska bearbetas ytterligare eller tillämpas på en struktur via 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);
}

Videoinspelning

Namnområde (före Unity 2019):UnityEngine.XR.WSA.WebCam
Namnområde (Unity 2019 och senare):UnityEngine.Windows.WebCam
Typ:VideoCapture

VideoCapture fungerar på samma sätt som PhotoCapture. De enda två skillnaderna är att du måste ange ett FPS-värde (Frames Per Second) och du kan bara spara direkt på disken som en .mp4 fil. Stegen för att använda VideoCapture är följande:

  1. Skapa ett VideoCapture-objekt
  2. Skapa ett CameraParameters-objekt med önskade inställningar
  3. Starta videoläge via StartVideoModeAsync
  4. Börja spela in video
  5. Sluta spela in video
  6. Stoppa videoläge och rensa resurser

Börja med att skapa videocapture-objektetVideoCapture m_VideoCapture = null;

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

Konfigurera sedan de parametrar som du vill använda för inspelningen och starta.

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

Starta inspelningen när den har startats

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

När inspelningen har startat kan du uppdatera användargränssnittet eller beteenden för att aktivera stopp. Här loggar du bara.

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

Vid ett senare tillfälle vill du stoppa inspelningen med en timer eller användarindata, till exempel.

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

När inspelningen har stoppats stoppar du videoläget och rensar dina resurser.

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

Felsökning

  • Det finns inga tillgängliga lösningar
    • Kontrollera att WebCam-funktionen har angetts i projektet.

Nästa kontrollpunkt för utveckling

Om du följer vägspärren för Unity-utveckling som vi har lagt fram är du mitt uppe i att utforska de Mixed Reality plattformsfunktionerna och API:erna. Härifrån kan du fortsätta till nästa avsnitt:

Eller gå direkt till distributionen av appen på en enhet eller emulator:

Du kan alltid gå tillbaka till unity-utvecklingskontrollpunkterna när som helst.

Se även