我可以在Unity中使用设备摄像头拍照吗?

23

我完全不熟悉Unity3D的更复杂功能集,想知道它是否有能力拍照并对其进行操作。具体来说,我希望用户自拍后在脸部轮廓线上描绘,从而创建一个PNG文件,然后将其贴图映射到模型上。

我知道将脸部映射到模型上很简单,但我想知道我是否需要将拍照/雕刻功能编写到涵盖Chrome应用程序中,还是可以在Unity内部完成所有操作。我不需要教程,只是想问一下这是否可能。


对于2016年,这里有一个完整的解释如何做到这一点... http://answers.unity3d.com/questions/909967/getting-a-web-cam-to-play-on-ui-texture-image.html#answer-910020 重要...请按照链接获取“神奇”的代码,在iOS/Android上正确地旋转、反转、旋转图像。 - Fattie
8个回答

27
是的,这是可能的。您需要查看WebCamTexture功能。
您创建一个WebCamTexture并调用其Play()函数来启动相机。WebCamTexture作为任何纹理,允许您通过GetPixels()调用获取像素。这使您可以在所需时拍摄快照,并将其保存在Texture2D中。调用EncodeToPNG(), 然后写入文件即可。
请注意,下面的代码是根据文档的快速编写,我没有测试过它。如果有多个可用设备,则可能需要选择正确的设备。
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);
    }
}

现在,当在 Android 设备上进行此操作时,如何处理相机旋转? - Codejoy
这里需要处理的是什么,@Codejoy?你想要发生什么? - Bart
回复晚了吗?我已经整理好了代码,将其附加到带有spriteRenderer的gameObject上...它启动相机,如果我按下按钮就拍照,但不显示实时视图...你有什么想法我做错了什么吗?(在2D UI环境中工作) - Matt
这在设备上随机旋转。 - Oliver Dixon
相机所做的就是提供原始数据。在某些设备上,这确实意味着结果可能会被旋转或翻转。您可以通过http://docs.unity3d.com/ScriptReference/WebCamTexture-videoRotationAngle.html来解决这个问题。 - Bart
1
有点晚了,但我想添加一个关键信息,关于这个解决方案。设备上的相机有两种模式 - 视频和照片。当您显示预览时,相机处于视频模式,这在大多数情况下会提供次优质量。从该输入创建静止照片将与同一设备拍摄的常规照片相比,提供非常差的照片质量。 - Krystian

7

对于那些想要让相机实时渲染的人,以下是我成功实现的方法。首先,我编辑了巴特的答案,使纹理在Update上分配而不仅仅是在Start上:

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

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

然后我将脚本附加到一个具有RawImage组件的GameObject上。您可以通过在Unity编辑器中的层次结构中右键单击-> UI-> RawImage轻松创建一个(这需要Unity 4.6及以上版本)。运行它应该会在您的视图中显示摄像机的实时视频。截至本文撰写时,Unity 5支持在免费个人版Unity 5中使用网络摄像头。

我希望这能帮助任何想要在Unity中捕获实时相机视频的人。


5

4

1

您需要在设备列表中搜索并选择您的摄像头设备索引,以便用于播放网络摄像头纹理。 您可以使用以下代码:

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

    }
}

“仅有代码的答案并不是高质量的答案”(https://meta.stackoverflow.com/questions/392712/explaining-entirely-code-based-answers)。虽然这段代码可能很有用,但您可以通过解释它为什么有效、如何有效、何时应该使用以及其限制是什么来改进它。请编辑您的答案,包括解释和相关文档链接。 - Muhammad Mohsin Khan

1

是的,你可以。我创建了Android原生相机插件,它可以打开你的Android设备相机,拍摄照片,录制视频并将其保存在设备的所需位置,只需要几行代码。


0

0

如果您想在不使用第三方插件的情况下实现此操作,那么@FuntionR的解决方案将会有所帮助。但是,如果您想将拍摄的照片保存到图库(Android和iOS),则无法在Unity中实现,您需要编写本地代码将照片传输到图库,然后从Unity中调用它。

这里有一篇总结性的博客,将指导您实现目标。 http://unitydevelopers.blogspot.com/2018/07/pick-image-from-gallery-in-unity3d.html

编辑:请注意,上述线程描述了从图库选择图像的过程,但同样的过程也适用于将图像保存到图库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接