'Can I take a photo in Unity using the device's camera?

I'm entirely unfamiliar with Unity3D's more complex feature set and am curious if it has the capability to take a picture and then manipulate it. Specifically my desire is to have the user take a selfie and then have them trace around their face to create a PNG that would then be texture mapped onto a model.

I know that the face mapping onto a model is simple, but I'm wondering if I need to write the photo/carving functionality into the encompassing Chrome app, or if it can all be done from within Unity. I don't need a tutorial on how to do it, just asking if it's something that is possible.



Solution 1:[1]

Yes, this is possible. You will want to look at the WebCamTexture functionality.

You create a WebCamTexture and call its Play() function which starts the camera. WebCamTexture, as any Texture, allows you to get the pixels via a GetPixels() call. This allows you to take a snapshot in when you like, and you can save this in a Texture2D. A call to EncodeToPNG() and subsequent write to file should get you there.

Do note that the code below is a quick write-up based on the documentation. I have not tested it. You might have to select a correct device if there are more than one available.

using UnityEngine;
using System.Collections;
using System.IO;

public class WebCamPhotoCamera : MonoBehaviour 
{
    WebCamTexture webCamTexture;

    void Start() 
    {
        webCamTexture = new WebCamTexture();
        GetComponent<Renderer>().material.mainTexture = webCamTexture; //Add Mesh Renderer to the GameObject to which this script is attached to
        webCamTexture.Play();
    }

    IEnumerator TakePhoto()  // Start this Coroutine on some button click
    {

    // NOTE - you almost certainly have to do this here:

     yield return new WaitForEndOfFrame(); 

    // it's a rare case where the Unity doco is pretty clear,
    // http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
    // be sure to scroll down to the SECOND long example on that doco page 

        Texture2D photo = new Texture2D(webCamTexture.width, webCamTexture.height);
        photo.SetPixels(webCamTexture.GetPixels());
        photo.Apply();

        //Encode to a PNG
        byte[] bytes = photo.EncodeToPNG();
        //Write out the PNG. Of course you have to substitute your_path for something sensible
        File.WriteAllBytes(your_path + "photo.png", bytes);
    }
}

Solution 2:[2]

For those trying to get the camera to render live feed, here's how I managed to pull it off. First, I edited Bart's answer so the texture would be assigned on Update rather than just on Start:

void Start()
{
    webCamTexture = new WebCamTexture();
    webCamTexture.Play();
}

void Update()
{
    GetComponent<RawImage>().texture = webCamTexture;
}

Then I attached the script to a GameObject with a RawImage component. You can easily create one by Right Click -> UI -> RawImage in the Hierarchy in the Unity Editor (this requires Unity 4.6 and above). Running it should show a live feed of the camera in your view. As of this writing, Unity 5 supports the use of webcams in the free personal edition of Unity 5.

I hope this helps anyone looking for a good way to capture live camera feed in Unity.

Solution 3:[3]

It is possible. I highly recommend you look at WebcamTexture Unity API. It has some useful functions:

  1. GetPixel() -- Returns pixel color at coordinates (x, y).
  2. GetPixels() -- Get a block of pixel colors.
  3. GetPixels32() -- Returns the pixels data in raw format.
  4. MarkNonReadable() -- Marks WebCamTexture as unreadable
  5. Pause() -- Pauses the camera.
  6. Play() -- Starts the camera.
  7. Stop() -- Stops the camera.

Solution 4:[4]

Bart's answer has a required modification. I used his code and the pic I was getting was black. Required modification is that we have to convert TakePhoto to a coroutine and add

yield return new WaitForEndOfFrame(); 

at the start of Coroutine. (Courtsey @fafase) For more details see http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html

You can also refer to

Take photo using webcam is giving black output[Unity3D]

Solution 5:[5]

Yes, You can. I created Android Native camera plugin that can open your Android device camera, capture image, record video and save that in the desired location of your device with just a few lines of code.

Solution 6:[6]

There is a plugin available for this type of functionality called Camera Capture Kit - https://www.assetstore.unity3d.com/en/#!/content/56673 and while the functionality provided is geared towards mobile it contains a demo of how you can use the WebCamTexture to take a still image.

Solution 7:[7]

If you want to do that without using a third party plugin then @FuntionR solution will help you. But, if you want to save the captured photo to the gallery (Android & iOS)then it's not possible within unity, you have to write native code to transfer photo to gallery and then call it from unity.

Here is a summarise blog which will guide you to achieve your goal. http://unitydevelopers.blogspot.com/2018/07/pick-image-from-gallery-in-unity3d.html

Edit: Note that, the above thread describes image picking from the gallery, but the same process will be for saving the image to the gallery.

Solution 8:[8]

you need to find your webcam device Index by search it in the devices list and select it for webcam texture to play. you can use this code:

using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
using System.Collections.Generic;


public class GetCam : MonoBehaviour
{
    WebCamTexture webCam;
    string your_path = "C:\\Users\\Jay\\Desktop";// any path you want to save your image
    public RawImage display;
    public AspectRatioFitter fit;

    public void Start()
    {
        if(WebCamTexture.devices.Length==0)
        {
            Debug.LogError("can not found any camera!");
            return;
        }
        int index = -1;
        for (int i = 0; i < WebCamTexture.devices.Length; i++)
        {
            if (WebCamTexture.devices[i].name.ToLower().Contains("your webcam name"))
            {
                Debug.LogError("WebCam Name:" + WebCamTexture.devices[i].name + "   Webcam Index:" + i);
                index = i;
            }
        }

        if (index == -1)
        {
            Debug.LogError("can not found your camera name!");
            return;
        }

        WebCamDevice device = WebCamTexture.devices[index];
        webCam = new WebCamTexture(device.name);
        webCam.Play();
        StartCoroutine(TakePhoto());
        display.texture = webCam;

    }

   
    public void Update()
    { 
        float ratio = (float)webCam.width / (float)webCam.height;
        fit.aspectRatio = ratio;


        float ScaleY = webCam.videoVerticallyMirrored ? -1f : 1f;
        display.rectTransform.localScale = new Vector3(1f, ScaleY, 1f);

        int orient = -webCam.videoRotationAngle;
        display.rectTransform.localEulerAngles = new Vector3(0, 0, orient);



    }

    public void callTakePhoto() // call this function in button click event
    {
        StartCoroutine(TakePhoto());
    }
    IEnumerator TakePhoto()  // Start this Coroutine on some button click
    {

        // NOTE - you almost certainly have to do this here:

        yield return new WaitForEndOfFrame();

        // it's a rare case where the Unity doco is pretty clear,
        // http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
        // be sure to scroll down to the SECOND long example on that doco page 

        Texture2D photo = new Texture2D(webCam.width, webCam.height);
        photo.SetPixels(webCam.GetPixels());
        photo.Apply();

        //Encode to a PNG
        byte[] bytes = photo.EncodeToPNG();
        //Write out the PNG. Of course you have to substitute your_path for something sensible
        File.WriteAllBytes(your_path + "\\photo.png", bytes);

    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Junaid Pathan
Solution 2
Solution 3
Solution 4 Community
Solution 5 Habibur Rahman Ovie
Solution 6 Chris
Solution 7 Ratan Uday Kumar
Solution 8